diff options
Diffstat (limited to 'include/llvm/Wrap/bitcode_wrapperer.h')
-rw-r--r-- | include/llvm/Wrap/bitcode_wrapperer.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/include/llvm/Wrap/bitcode_wrapperer.h b/include/llvm/Wrap/bitcode_wrapperer.h new file mode 100644 index 0000000000..89f2a4cbcc --- /dev/null +++ b/include/llvm/Wrap/bitcode_wrapperer.h @@ -0,0 +1,192 @@ +/* Copyright 2012 The Native Client Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can + * be found in the LICENSE file. + */ + +// 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/Support/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(); + + ~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_; + + // 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__ |