aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLai Wei-Chih <Robert.Lai@mediatek.com>2013-05-22 17:11:25 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2015-03-24 11:54:04 -0700
commitd0a379abb38851da152cf716d566b2654909df90 (patch)
tree51e811b729791338e52a85f3afce3a025564f0e3
parent231648ee7ef532c2cc9064bd6514a02dc8db399b (diff)
downloadllvm-d0a379abb38851da152cf716d566b2654909df90.tar.gz
[ndk][pndk] Import Wrap library for bitcode wrapper.
source: https://android.googlesource.com/platform/frameworks/compile/libbcc/ commit: 25b7205e16e422469da74f88e74ad79e7c284ac7 libbcc/bcinfo libbcc/include/bcinfo
-rw-r--r--include/llvm/Wrap/BCHeaderField.h118
-rw-r--r--include/llvm/Wrap/BitcodeWrapper.h149
-rw-r--r--include/llvm/Wrap/bitcode_wrapperer.h221
-rw-r--r--include/llvm/Wrap/file_wrapper_input.h58
-rw-r--r--include/llvm/Wrap/file_wrapper_output.h45
-rw-r--r--include/llvm/Wrap/in_memory_wrapper_input.h56
-rw-r--r--include/llvm/Wrap/support_macros.h41
-rw-r--r--include/llvm/Wrap/wrapper_input.h49
-rw-r--r--include/llvm/Wrap/wrapper_output.h45
-rw-r--r--lib/Makefile2
-rw-r--r--lib/Wrap/BitcodeWrapper.cpp52
-rw-r--r--lib/Wrap/LLVMBuild.txt21
-rw-r--r--lib/Wrap/Makefile14
-rw-r--r--lib/Wrap/bitcode_wrapperer.cpp382
-rw-r--r--lib/Wrap/file_wrapper_input.cpp64
-rw-r--r--lib/Wrap/file_wrapper_output.cpp48
-rw-r--r--lib/Wrap/in_memory_wrapper_input.cpp60
-rw-r--r--lib/Wrap/wrapper_output.cpp25
18 files changed, 1449 insertions, 1 deletions
diff --git a/include/llvm/Wrap/BCHeaderField.h b/include/llvm/Wrap/BCHeaderField.h
new file mode 100644
index 00000000000..fd8d585f009
--- /dev/null
+++ b/include/llvm/Wrap/BCHeaderField.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LLVM_WRAP_BCHEADER_FIELD_H__
+#define LLVM_WRAP_BCHEADER_FIELD_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+// Class representing a variable-size metadata field in the bitcode header.
+// Also contains the list of known Tag IDs.
+// Contains a pointer to the data but does not own the data, so it can be
+// copied with the trivial copy constructor/assignment operator.
+
+// The serialized format has 2 fixed subfields (ID and length) and the
+// variable-length data subfield
+class BCHeaderField {
+ public:
+ typedef enum {
+ kInvalid = 0,
+ kBitcodeHash = 1,
+ kAndroidCompilerVersion = 0x4001,
+ kAndroidOptimizationLevel = 0x4002
+ } Tag;
+ typedef uint16_t FixedSubfield;
+
+ BCHeaderField(Tag ID, size_t len, uint8_t* data) :
+ ID_(ID), len_(len), data_(data) {}
+ size_t GetTotalSize() {
+ // Round up to 4 byte alignment
+ return (kTagLenSize + len_ + 3) & ~3;
+ }
+
+ bool Write(uint8_t* buf, size_t buf_len) {
+ size_t fields_len = kTagLenSize + len_;
+ size_t pad_len = (4 - (fields_len & 3)) & 3;
+ // Ensure buffer is large enough and that length can be represented
+ // in 16 bits
+ const size_t max_uint16_t = 65535;
+ if (buf_len < fields_len + pad_len ||
+ len_ > max_uint16_t) return false;
+
+ WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf);
+ WriteFixedSubfield(static_cast<FixedSubfield>(len_),
+ buf + sizeof(FixedSubfield));
+ memcpy(buf + kTagLenSize, data_, len_);
+ // Pad out to 4 byte alignment
+ if (pad_len) {
+ memset(buf + fields_len, 0, pad_len);
+ }
+ return true;
+ }
+
+ bool Read(const uint8_t* buf, size_t buf_len) {
+ if (buf_len < kTagLenSize) return false;
+ FixedSubfield field;
+ ReadFixedSubfield(&field, buf);
+ ID_ = static_cast<Tag>(field);
+ ReadFixedSubfield(&field, buf + sizeof(FixedSubfield));
+ len_ = static_cast<size_t>(field);
+ if (buf_len < kTagLenSize + len_) return false;
+ memcpy(data_, buf + kTagLenSize, len_);
+ return true;
+ }
+
+ void Print() {
+ fprintf(stderr, "Field ID: %d, data length %d, total length %d\n",
+ ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize()));
+ fprintf(stderr, "Data:");
+ for (size_t i = 0; i < len_; i++) fprintf(stderr, "0x%x ", data_[i]);
+ fprintf(stderr, "\n");
+ }
+
+ // Get the data size from a serialized field to allow allocation
+ static size_t GetDataSizeFromSerialized(const uint8_t* buf) {
+ FixedSubfield len;
+ ReadFixedSubfield(&len, buf + sizeof(FixedSubfield));
+ return len;
+ }
+
+ Tag getID() const {
+ return ID_;
+ }
+
+ size_t getLen() const {
+ return len_;
+ }
+
+ private:
+ // Combined size of the fixed subfields
+ const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
+ static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) {
+ buf[0] = value & 0xFF;
+ buf[1] = (value >> 8) & 0xFF;
+ }
+ static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) {
+ *value = buf[0] | buf[1] << 8;
+ }
+ Tag ID_;
+ size_t len_;
+ uint8_t *data_;
+};
+
+#endif // LLVM_WRAP_BCHEADER_FIELD_H__
diff --git a/include/llvm/Wrap/BitcodeWrapper.h b/include/llvm/Wrap/BitcodeWrapper.h
new file mode 100644
index 00000000000..a5ce2624004
--- /dev/null
+++ b/include/llvm/Wrap/BitcodeWrapper.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2011-2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BITCODEWRAPPER_H__
+#define __BITCODEWRAPPER_H__
+
+#include "llvm/Wrap/BCHeaderField.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+struct AndroidBitcodeWrapper {
+ uint32_t Magic;
+ uint32_t Version;
+ uint32_t BitcodeOffset;
+ uint32_t BitcodeSize;
+ uint32_t HeaderVersion;
+ uint32_t TargetAPI;
+ uint32_t PNaClVersion;
+ uint16_t CompilerVersionTag;
+ uint16_t CompilerVersionLen;
+ uint32_t CompilerVersion;
+ uint16_t OptimizationLevelTag;
+ uint16_t OptimizationLevelLen;
+ uint32_t OptimizationLevel;
+};
+
+enum BCFileType {
+ BC_NOT_BC = 0,
+ BC_WRAPPER = 1,
+ BC_RAW = 2
+};
+
+class BitcodeWrapper {
+ private:
+ enum BCFileType mFileType;
+ const char *mBitcode;
+ size_t mBitcodeSize;
+
+ uint32_t mHeaderVersion;
+ uint32_t mTargetAPI;
+ uint32_t mCompilerVersion;
+ uint32_t mOptimizationLevel;
+
+ public:
+ /**
+ * Reads wrapper information from \p bitcode.
+ *
+ * \param bitcode - input bitcode string.
+ * \param bitcodeSize - length of \p bitcode string (in bytes).
+ */
+ BitcodeWrapper(const char *bitcode, size_t bitcodeSize);
+
+ ~BitcodeWrapper();
+
+ /**
+ * Attempt to unwrap the target bitcode. This function is \deprecated.
+ *
+ * \return true on success and false if an error occurred.
+ */
+ bool unwrap();
+
+ /**
+ * \return type of bitcode file.
+ */
+ enum BCFileType getBCFileType() const {
+ return mFileType;
+ }
+
+ /**
+ * \return header version of bitcode wrapper.
+ */
+ uint32_t getHeaderVersion() const {
+ return mHeaderVersion;
+ }
+
+ /**
+ * \return target API version for this bitcode.
+ */
+ uint32_t getTargetAPI() const {
+ return mTargetAPI;
+ }
+
+ /**
+ * \return compiler version that generated this bitcode.
+ */
+ uint32_t getCompilerVersion() const {
+ return mCompilerVersion;
+ }
+
+ /**
+ * \return compiler optimization level for this bitcode.
+ */
+ uint32_t getOptimizationLevel() const {
+ return mOptimizationLevel;
+ }
+
+};
+
+/**
+ * Helper function to emit just the bitcode wrapper returning the number of
+ * bytes that were written.
+ *
+ * \param wrapper - where to write header information into.
+ * \param bitcodeSize - size of bitcode in bytes.
+ * \param targetAPI - target API version for this bitcode.
+ * \param compilerVersion - compiler version that generated this bitcode.
+ * \param optimizationLevel - compiler optimization level for this bitcode.
+ *
+ * \return number of wrapper bytes written into the \p buffer.
+ */
+static inline size_t writeAndroidBitcodeWrapper(AndroidBitcodeWrapper *wrapper,
+ size_t bitcodeSize, uint32_t targetAPI, uint32_t compilerVersion,
+ uint32_t optimizationLevel) {
+ if (!wrapper) {
+ return 0;
+ }
+
+ wrapper->Magic = 0x0B17C0DE;
+ wrapper->Version = 0;
+ wrapper->BitcodeOffset = sizeof(*wrapper);
+ wrapper->BitcodeSize = bitcodeSize;
+ wrapper->HeaderVersion = 0;
+ wrapper->TargetAPI = targetAPI;
+ wrapper->PNaClVersion = 0;
+ wrapper->CompilerVersionTag = BCHeaderField::kAndroidCompilerVersion;
+ wrapper->CompilerVersionLen = 4;
+ wrapper->CompilerVersion = compilerVersion;
+ wrapper->OptimizationLevelTag = BCHeaderField::kAndroidOptimizationLevel;
+ wrapper->OptimizationLevelLen = 4;
+ wrapper->OptimizationLevel = optimizationLevel;
+
+ return sizeof(*wrapper);
+}
+
+#endif // __BITCODEWRAPPER_H__
diff --git a/include/llvm/Wrap/bitcode_wrapperer.h b/include/llvm/Wrap/bitcode_wrapperer.h
new file mode 100644
index 00000000000..26b9664f8a1
--- /dev/null
+++ b/include/llvm/Wrap/bitcode_wrapperer.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define utility class to wrap/unwrap bitcode files. Does wrapping/unwrapping
+// in such a way that the wrappered bitcode file is still a bitcode file.
+
+#ifndef LLVM_WRAP_BITCODE_WRAPPERER_H__
+#define LLVM_WRAP_BITCODE_WRAPPERER_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <vector>
+
+#include "llvm/Wrap/support_macros.h"
+#include "llvm/Wrap/BCHeaderField.h"
+#include "llvm/Wrap/wrapper_input.h"
+#include "llvm/Wrap/wrapper_output.h"
+
+// The bitcode wrapper header is the following 7 fixed 4-byte fields:
+// 1) 0B17C0DE - The magic number expected by llvm for wrapped bitcodes
+// 2) Version # 0 - The current version of wrapped bitcode files
+// 3) (raw) bitcode offset
+// 4) (raw) bitcode size
+// 5) Android header version
+// 6) Android target API
+// 7) PNaCl Bitcode version
+// plus 0 or more variable-length fields (consisting of ID, length, data)
+
+// Initial buffer size. It is expanded if needed to hold large variable-size
+// fields.
+static const size_t kBitcodeWrappererBufferSize = 1024;
+
+// Support class for outputting a wrapped bitcode file from a raw bitcode
+// file (and optionally additional header fields), or for outputting a raw
+// bitcode file from a wrapped one.
+class BitcodeWrapperer {
+ public:
+ // Create a bitcode wrapperer using the following
+ // input and output files.
+ BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile);
+
+ // Returns true if the input file begins with a bitcode
+ // wrapper magic number. As a side effect, _wrapper_ fields are set.
+ bool IsInputBitcodeWrapper();
+
+ // Returns true if the input file begins with a bitcode
+ // file magic number.
+ bool IsInputBitcodeFile();
+
+ // Add a variable-length field to the header. The caller is responsible
+ // for freeing the data pointed to by the BCHeaderField.
+ void AddHeaderField(BCHeaderField* field);
+
+ // Generate a wrapped bitcode file from the input bitcode file
+ // and the current header data. Return true on success.
+ bool GenerateWrappedBitcodeFile();
+
+ // Unwrap the wrapped bitcode file, to the corresponding
+ // outfile. Return true on success.
+ bool GenerateRawBitcodeFile();
+
+ // Print current wrapper header fields to stderr for debugging.
+ void PrintWrapperHeader();
+
+ uint32_t getAndroidHeaderVersion() {
+ return android_header_version_;
+ }
+
+ uint32_t getAndroidTargetAPI() {
+ return android_target_api_;
+ }
+
+ uint32_t getAndroidCompilerVersion() {
+ return android_compiler_version_;
+ }
+
+ uint32_t getAndroidOptimizationLevel() {
+ return android_optimization_level_;
+ }
+
+ ~BitcodeWrapperer();
+
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(BitcodeWrapperer);
+
+ // Refills the buffer with more bytes. Does this in a way
+ // such that it is maximally filled.
+ void FillBuffer();
+
+ // Returns the number of bytes in infile.
+ off_t GetInFileSize() {
+ if (infile_ != NULL) {
+ return infile_->Size();
+ } else {
+ return 0;
+ }
+ }
+
+ // Returns the offset of bitcode (i.e. the size of the wrapper header)
+ // if the output file were to be written now.
+ size_t BitcodeOffset();
+
+ // Returns true if we can read a word. If necessary, fills the buffer
+ // with enough characters so that there are at least a 32-bit value
+ // in the buffer. Returns false if there isn't a 32-bit value
+ // to read from the input file.
+ bool CanReadWord();
+
+ // Read a (32-bit) word from the input. Return true
+ // if able to read the word.
+ bool ReadWord(uint32_t& word);
+
+ // Write a (32-bit) word to the output. Return true if successful
+ bool WriteWord(uint32_t word);
+
+ // Write all variable-sized header fields to the output. Return true
+ // if successful.
+ bool WriteVariableFields();
+
+ // Parse the bitcode wrapper header in the infile, if any. Return true
+ // if successful.
+ bool ParseWrapperHeader();
+
+ // Returns the i-th character in front of the cursor in the buffer.
+ uint8_t BufferLookahead(int i) { return buffer_[cursor_ + i]; }
+
+ // Returns how many unread bytes are in the buffer.
+ size_t GetBufferUnreadBytes() { return buffer_size_ - cursor_; }
+
+
+ // Backs up the read cursor to the beginning of the input buffer.
+ void ResetCursor() {
+ cursor_ = 0;
+ }
+
+ // Generates the header sequence for the wrapped bitcode being
+ // generated.
+ bool WriteBitcodeWrapperHeader();
+
+ // Copies size bytes of infile to outfile, using the buffer.
+ bool BufferCopyInToOut(uint32_t size);
+
+ // Discards the old infile and replaces it with the given file.
+ void ReplaceInFile(WrapperInput* new_infile);
+
+ // Discards the old outfile and replaces it with the given file.
+ void ReplaceOutFile(WrapperOutput* new_outfile);
+
+ // Moves to the given position in the input file. Returns false
+ // if unsuccessful.
+ bool Seek(uint32_t pos);
+
+ // Clear the buffer of all contents.
+ void ClearBuffer();
+
+ // The input file being processed. Can be either
+ // a bitcode file, a wrappered bitcode file, or a secondary
+ // file to be wrapped.
+ WrapperInput* infile_;
+
+ // The output file being generated. Can be either
+ // a bitcode file, a wrappered bitcode file, or a secondary
+ // unwrapped file.
+ WrapperOutput* outfile_;
+
+ // A buffer of bytes read from the input file.
+ std::vector<uint8_t> buffer_;
+
+ // The number of bytes that were read from the input file
+ // into the buffer.
+ size_t buffer_size_;
+
+ // The index to the current read point within the buffer.
+ size_t cursor_;
+
+ // True when eof of input is reached.
+ bool infile_at_eof_;
+
+ // The 32-bit value defining the offset of the raw bitcode in the input file.
+ uint32_t infile_bc_offset_;
+
+ // The 32-bit value defining the generated offset of the wrapped bitcode.
+ // This value changes as new fields are added with AddHeaderField
+ uint32_t wrapper_bc_offset_;
+
+ // The 32-bit value defining the size of the raw wrapped bitcode.
+ uint32_t wrapper_bc_size_;
+
+ // Android header version and target API
+ uint32_t android_header_version_;
+ uint32_t android_target_api_;
+ uint32_t android_compiler_version_;
+ uint32_t android_optimization_level_;
+
+ // PNaCl bitcode version
+ uint32_t pnacl_bc_version_;
+
+ // Vector of variable header fields
+ std::vector<BCHeaderField> header_fields_;
+ // If any bufferdata from header fields is owned, it is stored here and
+ // freed on destruction.
+ std::vector<uint8_t*> variable_field_data_;
+
+ // True if there was an error condition (e.g. the file is not bitcode)
+ bool error_;
+};
+
+#endif // LLVM_WRAP_BITCODE_WRAPPERER_H__
diff --git a/include/llvm/Wrap/file_wrapper_input.h b/include/llvm/Wrap/file_wrapper_input.h
new file mode 100644
index 00000000000..4ea5d7d861c
--- /dev/null
+++ b/include/llvm/Wrap/file_wrapper_input.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Defines utility allowing files for bitcode input wrapping.
+
+#ifndef FILE_WRAPPER_INPUT_H__
+#define FILE_WRAPPER_INPUT_H__
+
+#include <stdio.h>
+
+#include "llvm/Wrap/support_macros.h"
+#include "llvm/Wrap/wrapper_input.h"
+
+// Define a class to wrap named files.
+class FileWrapperInput : public WrapperInput {
+ public:
+ FileWrapperInput(const char* _name);
+ ~FileWrapperInput();
+ // Tries to read the requested number of bytes into the buffer. Returns the
+ // actual number of bytes read.
+ virtual size_t Read(uint8_t* buffer, size_t wanted);
+ // Returns true if at end of file. Note: May return false
+ // until Read is called, and returns 0.
+ virtual bool AtEof();
+ // Returns the size of the file (in bytes).
+ virtual off_t Size();
+ // Moves to the given offset within the file. Returns
+ // false if unable to move to that position.
+ virtual bool Seek(uint32_t pos);
+ private:
+ // The name of the file.
+ const char* _name;
+ // True once eof has been encountered.
+ bool _at_eof;
+ // True if size has been computed.
+ bool _size_found;
+ // The size of the file.
+ off_t _size;
+ // The corresponding (opened) file.
+ FILE* _file;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(FileWrapperInput);
+};
+
+#endif // FILE_WRAPPER_INPUT_H__
diff --git a/include/llvm/Wrap/file_wrapper_output.h b/include/llvm/Wrap/file_wrapper_output.h
new file mode 100644
index 00000000000..19801065006
--- /dev/null
+++ b/include/llvm/Wrap/file_wrapper_output.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Defines utility allowing files for bitcode output wrapping.
+
+#ifndef FILE_WRAPPER_OUTPUT_H__
+#define FILE_WRAPPER_OUTPUT_H__
+
+#include <stdio.h>
+
+#include "llvm/Wrap/support_macros.h"
+#include "llvm/Wrap/wrapper_output.h"
+
+// Define a class to wrap named files. */
+class FileWrapperOutput : public WrapperOutput {
+ public:
+ FileWrapperOutput(const char* name);
+ ~FileWrapperOutput();
+ // Writes a single byte, returning false if unable to write.
+ virtual bool Write(uint8_t byte);
+ // Writes the specified number of bytes in the buffer to
+ // output. Returns false if unable to write.
+ virtual bool Write(const uint8_t* buffer, size_t buffer_size);
+ private:
+ // The name of the file
+ const char* _name;
+ // The corresponding (opened) file.
+ FILE* _file;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(FileWrapperOutput);
+};
+#endif // FILE_WRAPPER_OUTPUT_H__
diff --git a/include/llvm/Wrap/in_memory_wrapper_input.h b/include/llvm/Wrap/in_memory_wrapper_input.h
new file mode 100644
index 00000000000..f4e2aba80c6
--- /dev/null
+++ b/include/llvm/Wrap/in_memory_wrapper_input.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Defines utility allowing in-memory buffers for bitcode input wrapping.
+
+#ifndef IN_MEMORY_WRAPPER_INPUT_H__
+#define IN_MEMORY_WRAPPER_INPUT_H__
+
+#include <stdio.h>
+
+#include "llvm/Wrap/support_macros.h"
+#include "llvm/Wrap/wrapper_input.h"
+
+// Define a class to wrap named files.
+class InMemoryWrapperInput : public WrapperInput {
+ public:
+ InMemoryWrapperInput(const char* buffer, size_t size);
+ ~InMemoryWrapperInput();
+ // Tries to read the requested number of bytes into the buffer. Returns the
+ // actual number of bytes read.
+ virtual size_t Read(uint8_t* buffer, size_t wanted);
+ // Returns true if at end of buffer. Note: May return false
+ // until Read is called, and returns 0.
+ virtual bool AtEof();
+ // Returns the size of the buffer (in bytes).
+ virtual off_t Size();
+ // Moves to the given offset within the buffer. Returns
+ // false if unable to move to that position.
+ virtual bool Seek(uint32_t pos);
+ private:
+ // The actual in-memory buffer
+ const char* _buffer;
+ // The position in the buffer
+ size_t _pos;
+ // True once eof has been encountered.
+ bool _at_eof;
+ // The size of the buffer.
+ size_t _size;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(InMemoryWrapperInput);
+};
+
+#endif // IN_MEMORY_WRAPPER_INPUT_H__
diff --git a/include/llvm/Wrap/support_macros.h b/include/llvm/Wrap/support_macros.h
new file mode 100644
index 00000000000..5d3b8ceac6f
--- /dev/null
+++ b/include/llvm/Wrap/support_macros.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define support macros for defining classes, etc.
+
+#ifndef LLVM_SUPPORT_SUPPORT_MACROS_H__
+#define LLVM_SUPPORT_SUPPORT_MACROS_H__
+
+// Define macro, to use within a class declaration, to disallow constructor
+// copy. Defines copy constructor declaration under the assumption that it
+// is never defined.
+#define DISALLOW_CLASS_COPY(class_name) \
+ class_name(class_name& arg) // Do not implement
+
+// Define macro, to use within a class declaration, to disallow assignment.
+// Defines assignment operation declaration under the assumption that it
+// is never defined.
+#define DISALLOW_CLASS_ASSIGN(class_name) \
+ void operator=(class_name& arg) // Do not implement
+
+// Define macro to add copy and assignment declarations to a class file,
+// for which no bodies will be defined, effectively disallowing these from
+// being defined in the class.
+#define DISALLOW_CLASS_COPY_AND_ASSIGN(class_name) \
+ DISALLOW_CLASS_COPY(class_name); \
+ DISALLOW_CLASS_ASSIGN(class_name)
+
+#endif // LLVM_SUPPORT_SUPPORT_MACROS_H__
diff --git a/include/llvm/Wrap/wrapper_input.h b/include/llvm/Wrap/wrapper_input.h
new file mode 100644
index 00000000000..d3330df7732
--- /dev/null
+++ b/include/llvm/Wrap/wrapper_input.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define a generic interface to a file/memory region that contains
+// a bitcode file, a wrapped bitcode file, or a data file to wrap.
+
+#ifndef LLVM_WRAP_WRAPPER_INPUT_H__
+#define LLVM_WRAP_WRAPPER_INPUT_H__
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "support_macros.h"
+
+// The following is a generic interface to a file/memory region that contains
+// a bitcode file, a wrapped bitcode file, or data file to wrap.
+class WrapperInput {
+ public:
+ WrapperInput() {}
+ virtual ~WrapperInput() {}
+ // Tries to read the requested number of bytes into the buffer. Returns the
+ // actual number of bytes read.
+ virtual size_t Read(uint8_t* buffer, size_t wanted) = 0;
+ // Returns true if at end of input. Note: May return false until
+ // Read is called, and returns 0.
+ virtual bool AtEof() = 0;
+ // Returns the size of the input (in bytes).
+ virtual off_t Size() = 0;
+ // Moves to the given offset within the input region. Returns false
+ // if unable to move to that position.
+ virtual bool Seek(uint32_t pos) = 0;
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(WrapperInput);
+};
+
+#endif // LLVM_WRAP_WRAPPER_INPUT_H__
diff --git a/include/llvm/Wrap/wrapper_output.h b/include/llvm/Wrap/wrapper_output.h
new file mode 100644
index 00000000000..74eab908eb7
--- /dev/null
+++ b/include/llvm/Wrap/wrapper_output.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Defines a generic interface to a file/memory region that
+// contains a generated wrapped bitcode file, bitcode file,
+// or data file.
+
+#ifndef LLVM_WRAP_WRAPPER_OUTPUT_H__
+#define LLVM_WRAP_WRAPPER_OUTPUT_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "llvm/Wrap/support_macros.h"
+
+// The following is a generic interface to a file/memory region
+// that contains a generated bitcode file, wrapped bitcode file,
+// or a data file.
+class WrapperOutput {
+ public:
+ WrapperOutput() {}
+ virtual ~WrapperOutput() {}
+ // Writes a single byte, returning false if unable to write.
+ virtual bool Write(uint8_t byte) = 0;
+ // Writes the specified number of bytes in the buffer to
+ // output. Returns false if unable to write.
+ virtual bool Write(const uint8_t* buffer, size_t buffer_size);
+ private:
+ DISALLOW_CLASS_COPY_AND_ASSIGN(WrapperOutput);
+};
+
+#endif // LLVM_WRAP_WRAPPER_OUTPUT_H__
diff --git a/lib/Makefile b/lib/Makefile
index 0ddf917599f..8061bb57329 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -12,6 +12,6 @@ include $(LEVEL)/Makefile.config
PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \
ExecutionEngine Linker LTO MC Object Option DebugInfo \
- IRReader LineEditor ProfileData
+ IRReader LineEditor ProfileData Wrap
include $(LEVEL)/Makefile.common
diff --git a/lib/Wrap/BitcodeWrapper.cpp b/lib/Wrap/BitcodeWrapper.cpp
new file mode 100644
index 00000000000..d779d3a27c7
--- /dev/null
+++ b/lib/Wrap/BitcodeWrapper.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011-2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Wrap/BitcodeWrapper.h"
+#include "llvm/Wrap/bitcode_wrapperer.h"
+#include "llvm/Wrap/in_memory_wrapper_input.h"
+
+#include <cstdlib>
+#include <cstring>
+
+BitcodeWrapper::BitcodeWrapper(const char *bitcode, size_t bitcodeSize)
+ : mFileType(BC_NOT_BC), mBitcode(bitcode),
+ mBitcodeSize(bitcodeSize),
+ mHeaderVersion(0), mTargetAPI(0), mCompilerVersion(0),
+ mOptimizationLevel(3) {
+ InMemoryWrapperInput inMem(mBitcode, mBitcodeSize);
+ BitcodeWrapperer wrapperer(&inMem, NULL);
+ if (wrapperer.IsInputBitcodeWrapper()) {
+ mFileType = BC_WRAPPER;
+ mHeaderVersion = wrapperer.getAndroidHeaderVersion();
+ mTargetAPI = wrapperer.getAndroidTargetAPI();
+ mCompilerVersion = wrapperer.getAndroidCompilerVersion();
+ mOptimizationLevel = wrapperer.getAndroidOptimizationLevel();
+ } else if (wrapperer.IsInputBitcodeFile()) {
+ mFileType = BC_RAW;
+ }
+}
+
+
+BitcodeWrapper::~BitcodeWrapper() {
+ return;
+}
+
+
+bool BitcodeWrapper::unwrap() {
+ return mFileType != BC_NOT_BC;
+}
+
diff --git a/lib/Wrap/LLVMBuild.txt b/lib/Wrap/LLVMBuild.txt
new file mode 100644
index 00000000000..87507113387
--- /dev/null
+++ b/lib/Wrap/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./lib/Wrap/LLVMBuild.txt ------------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = Wrap
+parent = Libraries
diff --git a/lib/Wrap/Makefile b/lib/Wrap/Makefile
new file mode 100644
index 00000000000..641f6c46b87
--- /dev/null
+++ b/lib/Wrap/Makefile
@@ -0,0 +1,14 @@
+##===- lib/Wrap/Makefile ---------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = LLVMWrap
+BUILD_ARCHIVE := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/Wrap/bitcode_wrapperer.cpp b/lib/Wrap/bitcode_wrapperer.cpp
new file mode 100644
index 00000000000..65f94b7c67a
--- /dev/null
+++ b/lib/Wrap/bitcode_wrapperer.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "llvm/Wrap/bitcode_wrapperer.h"
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+using std::vector;
+
+// The number of bytes in a 32 bit integer.
+static const uint32_t kWordSize = 4;
+
+// Number of LLVM-defined fixed fields in the header.
+static const uint32_t kLLVMFields = 4;
+
+// Total number of fixed fields in the header.
+static const uint32_t kFixedFields = 7;
+
+// The magic number that must exist for bitcode wrappers.
+static const uint32_t kWrapperMagicNumber = 0x0B17C0DE;
+
+// The version number associated with a wrapper file.
+// Note: llvm currently only allows the value 0. When this changes,
+// we should consider making this a command line option.
+static const uint32_t kLLVMVersionNumber = 0;
+
+// Fields defined by Android bitcode header.
+static const uint32_t kAndroidHeaderVersion = 0;
+static const uint32_t kAndroidTargetAPI = 0;
+static const uint32_t kAndroidDefaultCompilerVersion = 0;
+static const uint32_t kAndroidDefaultOptimizationLevel = 3;
+
+// PNaCl bitcode version number.
+static const uint32_t kPnaclBitcodeVersion = 0;
+
+// Max size for variable fields. Currently only used for writing them
+// out to files (the parsing works for arbitrary sizes).
+static const size_t kMaxVariableFieldSize = 256;
+
+BitcodeWrapperer::BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile)
+ : infile_(infile),
+ outfile_(outfile),
+ buffer_size_(0),
+ cursor_(0),
+ infile_at_eof_(false),
+ infile_bc_offset_(0),
+ wrapper_bc_offset_(0),
+ wrapper_bc_size_(0),
+ android_header_version_(kAndroidHeaderVersion),
+ android_target_api_(kAndroidTargetAPI),
+ android_compiler_version_(kAndroidDefaultCompilerVersion),
+ android_optimization_level_(kAndroidDefaultOptimizationLevel),
+ pnacl_bc_version_(0),
+ error_(false) {
+ buffer_.resize(kBitcodeWrappererBufferSize);
+ if (IsInputBitcodeWrapper()) {
+ ParseWrapperHeader();
+ } else if (IsInputBitcodeFile()) {
+ wrapper_bc_offset_ = kWordSize * kFixedFields;
+ wrapper_bc_size_ = GetInFileSize();
+ } else {
+ fprintf(stderr, "Error: input file is not a bitcode file.\n");
+ error_ = true;
+ }
+}
+
+BitcodeWrapperer::~BitcodeWrapperer() {
+ for(size_t i = 0; i < variable_field_data_.size(); i++) {
+ delete [] variable_field_data_[i];
+ }
+}
+
+
+void BitcodeWrapperer::ClearBuffer() {
+ buffer_size_ = 0;
+ cursor_ = 0;
+ infile_at_eof_ = false;
+}
+
+bool BitcodeWrapperer::Seek(uint32_t pos) {
+ if (infile_ != NULL && infile_->Seek(pos)) {
+ ClearBuffer();
+ return true;
+ }
+ return false;
+}
+
+bool BitcodeWrapperer::CanReadWord() {
+ if (GetBufferUnreadBytes() < kWordSize) {
+ FillBuffer();
+ return GetBufferUnreadBytes() >= kWordSize;
+ } else {
+ return true;
+ }
+}
+
+void BitcodeWrapperer::FillBuffer() {
+ if (cursor_ > 0) {
+ // Before filling, move any remaining bytes to the
+ // front of the buffer. This allows us to assume
+ // that after the call to FillBuffer, readable
+ // text is contiguous.
+ if (cursor_ < buffer_size_) {
+ size_t i = 0;
+ while (cursor_ < buffer_size_) {
+ buffer_[i++] = buffer_[cursor_++];
+ }
+ cursor_ = 0;
+ buffer_size_ = i;
+ }
+ } else {
+ // Assume the buffer contents have been used,
+ // and we want to completely refill it.
+ buffer_size_ = 0;
+ }
+
+ // If we don't have an input, we can't refill the buffer at all.
+ if (infile_ == NULL) {
+ return;
+ }
+
+ // Now fill in remaining space.
+ size_t needed = buffer_.size() - buffer_size_;
+
+ while (buffer_.size() > buffer_size_) {
+ int actually_read = infile_->Read(&buffer_[buffer_size_], needed);
+ if (infile_->AtEof()) {
+ infile_at_eof_ = true;
+ }
+ if (actually_read) {
+ buffer_size_ += actually_read;
+ needed -= actually_read;
+ } else if (infile_at_eof_) {
+ break;
+ }
+ }
+}
+
+bool BitcodeWrapperer::ReadWord(uint32_t& word) {
+ if (!CanReadWord()) return false;
+ word = (((uint32_t) BufferLookahead(0)) << 0)
+ | (((uint32_t) BufferLookahead(1)) << 8)
+ | (((uint32_t) BufferLookahead(2)) << 16)
+ | (((uint32_t) BufferLookahead(3)) << 24);
+ cursor_ += kWordSize;
+ return true;
+}
+
+bool BitcodeWrapperer::WriteWord(uint32_t value) {
+ uint8_t buffer[kWordSize];
+ buffer[3] = (value >> 24) & 0xFF;
+ buffer[2] = (value >> 16) & 0xFF;
+ buffer[1] = (value >> 8) & 0xFF;
+ buffer[0] = (value >> 0) & 0xFF;
+ return outfile_->Write(buffer, kWordSize);
+}
+
+bool BitcodeWrapperer::WriteVariableFields() {
+ // This buffer may have to be bigger if we start using the fields
+ // for larger things.
+ uint8_t buffer[kMaxVariableFieldSize];
+ for (vector<BCHeaderField>::iterator it = header_fields_.begin();
+ it != header_fields_.end(); ++it) {
+ if (!it->Write(buffer, kMaxVariableFieldSize) ||
+ !outfile_->Write(buffer, it->GetTotalSize())) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool BitcodeWrapperer::ParseWrapperHeader() {
+ // Make sure LLVM-defined fields have been parsed
+ if (!IsInputBitcodeWrapper()) return false;
+ // Check the android/pnacl fields
+ if (!ReadWord(android_header_version_) ||
+ !ReadWord(android_target_api_) || !ReadWord(pnacl_bc_version_)) {
+ fprintf(stderr, "Error: file not long enough to contain header\n");
+ return false;
+ }
+ if (pnacl_bc_version_ != kPnaclBitcodeVersion) {
+ fprintf(stderr, "Error: bad PNaCl Bitcode version\n");
+ return false;
+ }
+ int field_data_total = wrapper_bc_offset_ - kWordSize * kFixedFields;
+ if (field_data_total > 0) {
+ // Read in the variable fields. We need to allocate space for the data.
+ int field_data_read = 0;
+
+ while (field_data_read < field_data_total) {
+ FillBuffer();
+ size_t buffer_needed = BCHeaderField::GetDataSizeFromSerialized(
+ &buffer_[cursor_]);
+ if (buffer_needed > buffer_.size()) {
+ buffer_.resize(buffer_needed +
+ sizeof(BCHeaderField::FixedSubfield) * 2);
+ FillBuffer();
+ }
+ variable_field_data_.push_back(new uint8_t[buffer_needed]);
+
+ BCHeaderField field(BCHeaderField::kInvalid, 0,
+ variable_field_data_.back());
+ field.Read(&buffer_[cursor_], buffer_size_);
+ header_fields_.push_back(field);
+ size_t field_size = field.GetTotalSize();
+ cursor_ += field_size;
+ field_data_read += field_size;
+ if (field_data_read > field_data_total) {
+ // We read too much data, the header is corrupted
+ fprintf(stderr, "Error: raw bitcode offset inconsistent with "
+ "variable field data\n");
+ return false;
+ }
+
+ struct IntFieldHelper {
+ BCHeaderField::FixedSubfield tag;
+ uint16_t len;
+ uint32_t val;
+ };
+ IntFieldHelper tempIntField;
+
+ switch (field.getID()) {
+ case BCHeaderField::kAndroidCompilerVersion:
+ if (field.Write((uint8_t*)&tempIntField,
+ sizeof(tempIntField))) {
+ android_compiler_version_ = tempIntField.val;
+ }
+ break;
+ case BCHeaderField::kAndroidOptimizationLevel:
+ if (field.Write((uint8_t*)&tempIntField,
+ sizeof(tempIntField))) {
+ android_optimization_level_ = tempIntField.val;
+ }
+ break;
+ default:
+ // Ignore other field types for now
+ break;
+ }
+ }
+ Seek(0);
+ }
+ return true;
+}
+
+bool BitcodeWrapperer::IsInputBitcodeWrapper() {
+ ResetCursor();
+ // First make sure that there are enough words (LLVM header)
+ // to peek at.
+ if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) {
+ FillBuffer();
+ if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) return false;
+ }
+
+ // Now make sure the magic number is right.
+ uint32_t first_word;
+ if ((!ReadWord(first_word)) ||
+ (kWrapperMagicNumber != first_word)) return false;
+
+ // Make sure the version is right.
+ uint32_t second_word;
+ if ((!ReadWord(second_word)) ||
+ (kLLVMVersionNumber != second_word)) return false;
+
+ // Make sure that the offset and size (for llvm) is defined.
+ uint32_t bc_offset;
+ uint32_t bc_size;
+ if (ReadWord(bc_offset) &&
+ ReadWord(bc_size)) {
+ // Before returning, save the extracted values.
+ wrapper_bc_offset_ = bc_offset;
+ infile_bc_offset_ = bc_offset;
+ wrapper_bc_size_ = bc_size;
+ return true;
+ }
+ // If reached, unable to read wrapped header.
+ return false;
+}
+
+bool BitcodeWrapperer::IsInputBitcodeFile() {
+ ResetCursor();
+ // First make sure that there are four bytes to peek at.
+ if (GetBufferUnreadBytes() < kWordSize) {
+ FillBuffer();
+ if (GetBufferUnreadBytes() < kWordSize) return false;
+ }
+ // If reached, Check if first 4 bytes match bitcode
+ // file magic number.
+ return (BufferLookahead(0) == 'B') &&
+ (BufferLookahead(1) == 'C') &&
+ (BufferLookahead(2) == 0xc0) &&
+ (BufferLookahead(3) == 0xde);
+}
+
+bool BitcodeWrapperer::BufferCopyInToOut(uint32_t size) {
+ while (size > 0) {
+ // Be sure buffer is non-empty before writing.
+ if (0 == buffer_size_) {
+ FillBuffer();
+ if (0 == buffer_size_) {
+ return false;
+ }
+ }
+ // copy the buffer to the output file.
+ size_t block = (buffer_size_ < size) ? buffer_size_ : size;
+ if (!outfile_->Write(&buffer_[cursor_], block)) return false;
+ size -= block;
+ buffer_size_ = 0;
+ }
+ // Be sure that there isn't more bytes on the input stream.
+ FillBuffer();
+ return buffer_size_ == 0;
+}
+
+void BitcodeWrapperer::AddHeaderField(BCHeaderField* field) {
+ header_fields_.push_back(*field);
+ wrapper_bc_offset_ += field->GetTotalSize();
+}
+
+bool BitcodeWrapperer::WriteBitcodeWrapperHeader() {
+ return
+ // Note: This writes out the 4 word header required by llvm wrapped
+ // bitcode.
+ WriteWord(kWrapperMagicNumber) &&
+ WriteWord(kLLVMVersionNumber) &&
+ WriteWord(wrapper_bc_offset_) &&
+ WriteWord(wrapper_bc_size_) &&
+ // 2 fixed fields defined by Android
+ WriteWord(android_header_version_) &&
+ WriteWord(android_target_api_) &&
+ // PNaClBitcode version
+ WriteWord(kPnaclBitcodeVersion) &&
+ // Common variable-length fields
+ WriteVariableFields();
+}
+
+void BitcodeWrapperer::PrintWrapperHeader() {
+ if (error_) {
+ fprintf(stderr, "Error condition exists: the following"
+ "data may not be reliable\n");
+ }
+ fprintf(stderr, "Wrapper magic:\t\t%x\n", kWrapperMagicNumber);
+ fprintf(stderr, "LLVM Bitcode version:\t%d\n", kLLVMVersionNumber);
+ fprintf(stderr, "Raw bitcode offset:\t%d\n", wrapper_bc_offset_);
+ fprintf(stderr, "Raw bitcode size:\t%d\n", wrapper_bc_size_);
+ fprintf(stderr, "Android header version:\t%d\n", android_header_version_);
+ fprintf(stderr, "Android target API:\t%d\n", android_target_api_);
+ fprintf(stderr, "PNaCl bitcode version:\t%d\n", kPnaclBitcodeVersion);
+ for (size_t i = 0; i < header_fields_.size(); i++) header_fields_[i].Print();
+}
+
+bool BitcodeWrapperer::GenerateWrappedBitcodeFile() {
+ if (!error_ &&
+ WriteBitcodeWrapperHeader() &&
+ Seek(infile_bc_offset_) &&
+ BufferCopyInToOut(wrapper_bc_size_)) {
+ off_t dangling = wrapper_bc_size_ & 3;
+ if (dangling) {
+ return outfile_->Write((const uint8_t*) "\0\0\0\0", 4 - dangling);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool BitcodeWrapperer::GenerateRawBitcodeFile() {
+ return !error_ && Seek(infile_bc_offset_) &&
+ BufferCopyInToOut(wrapper_bc_size_);
+}
diff --git a/lib/Wrap/file_wrapper_input.cpp b/lib/Wrap/file_wrapper_input.cpp
new file mode 100644
index 00000000000..008bd61c073
--- /dev/null
+++ b/lib/Wrap/file_wrapper_input.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "llvm/Wrap/file_wrapper_input.h"
+
+FileWrapperInput::FileWrapperInput(const char* name) :
+ _name(name), _at_eof(false), _size_found(false), _size(0) {
+ _file = fopen(name, "rb");
+ if (NULL == _file) {
+ fprintf(stderr, "Unable to open: %s\n", name);
+ exit(1);
+ }
+}
+
+FileWrapperInput::~FileWrapperInput() {
+ fclose(_file);
+}
+
+size_t FileWrapperInput::Read(uint8_t* buffer, size_t wanted) {
+ size_t found = fread((char*) buffer, 1, wanted, _file);
+ if (feof(_file) || ferror(_file)) {
+ _at_eof = true;
+ }
+ return found;
+}
+
+bool FileWrapperInput::AtEof() {
+ return _at_eof;
+}
+
+off_t FileWrapperInput::Size() {
+ if (_size_found) return _size;
+ struct stat st;
+ if (0 == stat(_name, &st)) {
+ _size_found = true;
+ _size = st.st_size;
+ return _size;
+ } else {
+ fprintf(stderr, "Unable to compute file size: %s\n", _name);
+ exit(1);
+ }
+ // NOT REACHABLE.
+ return 0;
+}
+
+bool FileWrapperInput::Seek(uint32_t pos) {
+ return 0 == fseek(_file, (long) pos, SEEK_SET);
+}
diff --git a/lib/Wrap/file_wrapper_output.cpp b/lib/Wrap/file_wrapper_output.cpp
new file mode 100644
index 00000000000..9a62c298aa8
--- /dev/null
+++ b/lib/Wrap/file_wrapper_output.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include "llvm/Wrap/file_wrapper_output.h"
+
+FileWrapperOutput::FileWrapperOutput(const char* name)
+ : _name(name) {
+ _file = fopen(name, "wb");
+ if (NULL == _file) {
+ fprintf(stderr, "Unable to open: %s\n", name);
+ exit(1);
+ }
+}
+
+FileWrapperOutput::~FileWrapperOutput() {
+ fclose(_file);
+}
+
+bool FileWrapperOutput::Write(uint8_t byte) {
+ return EOF != fputc(byte, _file);
+}
+
+bool FileWrapperOutput::Write(const uint8_t* buffer, size_t buffer_size) {
+ if (!buffer) {
+ return false;
+ }
+
+ if (buffer_size > 0) {
+ return buffer_size == fwrite(buffer, 1, buffer_size, _file);
+ } else {
+ return true;
+ }
+}
diff --git a/lib/Wrap/in_memory_wrapper_input.cpp b/lib/Wrap/in_memory_wrapper_input.cpp
new file mode 100644
index 00000000000..3a69834a513
--- /dev/null
+++ b/lib/Wrap/in_memory_wrapper_input.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "llvm/Wrap/in_memory_wrapper_input.h"
+
+InMemoryWrapperInput::InMemoryWrapperInput(const char* buffer, size_t size) :
+ _buffer(buffer), _pos(0), _size(size) {
+}
+
+InMemoryWrapperInput::~InMemoryWrapperInput() {
+}
+
+size_t InMemoryWrapperInput::Read(uint8_t* buffer, size_t wanted) {
+ size_t found = 0;
+
+ if (!buffer) {
+ return 0;
+ }
+
+ while (found < wanted) {
+ if (_pos >= _size) {
+ return found;
+ }
+ buffer[found++] = _buffer[_pos++];
+ }
+ return found;
+}
+
+bool InMemoryWrapperInput::AtEof() {
+ return (_pos >= _size);
+}
+
+off_t InMemoryWrapperInput::Size() {
+ return _size;
+}
+
+bool InMemoryWrapperInput::Seek(uint32_t pos) {
+ if (pos < _size) {
+ _pos = pos;
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/lib/Wrap/wrapper_output.cpp b/lib/Wrap/wrapper_output.cpp
new file mode 100644
index 00000000000..f2bfe338796
--- /dev/null
+++ b/lib/Wrap/wrapper_output.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "llvm/Wrap/wrapper_output.h"
+
+bool WrapperOutput::Write(const uint8_t* buffer, size_t buffer_size) {
+ // Default implementation that uses the byte write routine.
+ for (size_t i = 0; i < buffer_size; ++i) {
+ if (!Write(buffer[i])) return false;
+ }
+ return true;
+}