| Index: include/llvm/Bitcode/NaCl/NaClReaderWriter.h | 
| diff --git a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h | 
| index 2b905b97e855d426cc9894fc5798712fa11e2303..d505af0a1fb04a66b9d30ce180197d9cc65e1d53 100644 | 
| --- a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h | 
| +++ b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h | 
| @@ -8,22 +8,142 @@ | 
| // | 
| //===----------------------------------------------------------------------===// | 
| // | 
| -// This header defines interfaces to read and write LLVM bitcode files/streams. | 
| +// This header defines interfaces to read and write NaCl bitcode wire format | 
| +// files. | 
| // | 
| //===----------------------------------------------------------------------===// | 
|  | 
| #ifndef LLVM_BITCODE_NACL_NACLREADERWRITER_H | 
| #define LLVM_BITCODE_NACL_NACLREADERWRITER_H | 
|  | 
| +#include <string> | 
| + | 
| namespace llvm { | 
| +  class MemoryBuffer; | 
| +  class DataStreamer; | 
| +  class LLVMContext; | 
| class Module; | 
| class raw_ostream; | 
|  | 
| +  /// getNaClLazyBitcodeModule - Read the header of the specified bitcode buffer | 
| +  /// and prepare for lazy deserialization of function bodies.  If successful, | 
| +  /// this takes ownership of 'buffer' and returns a non-null pointer.  On | 
| +  /// error, this returns null, *does not* take ownership of Buffer, and fills | 
| +  /// in *ErrMsg with an error description if ErrMsg is non-null. | 
| +  Module *getNaClLazyBitcodeModule(MemoryBuffer *Buffer, | 
| +				   LLVMContext &Context, | 
| +				   std::string *ErrMsg = 0); | 
| + | 
| +  /// getNaClStreamedBitcodeModule - Read the header of the specified stream | 
| +  /// and prepare for lazy deserialization and streaming of function bodies. | 
| +  /// On error, this returns null, and fills in *ErrMsg with an error | 
| +  /// description if ErrMsg is non-null. | 
| +  Module *getNaClStreamedBitcodeModule(const std::string &name, | 
| +				       DataStreamer *streamer, | 
| +				       LLVMContext &Context, | 
| +				       std::string *ErrMsg = 0); | 
| + | 
| +  /// NaClParseBitcodeFile - Read the specified bitcode file, | 
| +  /// returning the module.  If an error occurs, this returns null and | 
| +  /// fills in *ErrMsg if it is non-null.  This method *never* takes | 
| +  /// ownership of Buffer. | 
| +  Module *NaClParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context, | 
| +			       std::string *ErrMsg = 0); | 
| + | 
| /// NaClWriteBitcodeToFile - Write the specified module to the | 
| /// specified raw output stream, using PNaCl wire format.  For | 
| /// streams where it matters, the given stream should be in "binary" | 
| /// mode. | 
| void NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out); | 
|  | 
| +  /// isNaClBitcodeWrapper - Return true if the given bytes are the | 
| +  /// magic bytes for an LLVM IR bitcode wrapper. | 
| +  /// | 
| +  inline bool isNaClBitcodeWrapper(const unsigned char *BufPtr, | 
| +                                   const unsigned char *BufEnd) { | 
| +    // See if you can find the hidden message in the magic bytes :-). | 
| +    // (Hint: it's a little-endian encoding.) | 
| +    return BufPtr != BufEnd && | 
| +           BufPtr[0] == 0xDE && | 
| +           BufPtr[1] == 0xC0 && | 
| +           BufPtr[2] == 0x17 && | 
| +           BufPtr[3] == 0x0B; | 
| +  } | 
| + | 
| +  /// isNaClRawBitcode - Return true if the given bytes are the magic | 
| +  /// bytes for raw LLVM IR bitcode (without a wrapper). | 
| +  /// | 
| +  inline bool isNaClRawBitcode(const unsigned char *BufPtr, | 
| +                               const unsigned char *BufEnd) { | 
| +    // These bytes sort of have a hidden message, but it's not in | 
| +    // little-endian this time, and it's a little redundant. | 
| +    return BufPtr != BufEnd && | 
| +           BufPtr[0] == 'B' && | 
| +           BufPtr[1] == 'C' && | 
| +           BufPtr[2] == 0xc0 && | 
| +           BufPtr[3] == 0xde; | 
| +  } | 
| + | 
| +  /// isNaClBitcode - Return true if the given bytes are the magic bytes for | 
| +  /// LLVM IR bitcode, either with or without a wrapper. | 
| +  /// | 
| +  inline bool isNaClBitcode(const unsigned char *BufPtr, | 
| +                        const unsigned char *BufEnd) { | 
| +    return isNaClBitcodeWrapper(BufPtr, BufEnd) || | 
| +           isNaClRawBitcode(BufPtr, BufEnd); | 
| +  } | 
| + | 
| +  /// SkipNaClBitcodeWrapperHeader - Some systems wrap bc files with a | 
| +  /// special header for padding or other reasons.  The format of this | 
| +  /// header is: | 
| +  /// | 
| +  /// struct bc_header { | 
| +  ///   uint32_t Magic;         // 0x0B17C0DE | 
| +  ///   uint32_t Version;       // Version, currently always 0. | 
| +  ///   uint32_t BitcodeOffset; // Offset to traditional bitcode file. | 
| +  ///   uint32_t BitcodeSize;   // Size of traditional bitcode file. | 
| +  ///   ... potentially other gunk ... | 
| +  /// }; | 
| +  /// | 
| +  /// TODO(kschimpf): Consider changing Magic and/or gunk to communicate | 
| +  ///     file is PNaCl wire format file (rather than LLVM bitcode). | 
| +  /// | 
| +  /// TODO(kschimpf): Add code to read gunk in, and store it so it is | 
| +  /// accessable. | 
| +  /// | 
| +  /// This function is called when we find a file with a matching magic number. | 
| +  /// In this case, skip down to the subsection of the file that is actually a | 
| +  /// BC file. | 
| +  /// If 'VerifyBufferSize' is true, check that the buffer is large enough to | 
| +  /// contain the whole bitcode file. | 
| +  inline bool SkipNaClBitcodeWrapperHeader(const unsigned char *&BufPtr, | 
| +                                           const unsigned char *&BufEnd, | 
| +                                           bool VerifyBufferSize) { | 
| +    enum { | 
| +      KnownHeaderSize = 4*4,  // Size of header we read. | 
| +      OffsetField = 2*4,      // Offset in bytes to Offset field. | 
| +      SizeField = 3*4         // Offset in bytes to Size field. | 
| +    }; | 
| + | 
| +    // Must contain the header! | 
| +    if (BufEnd-BufPtr < KnownHeaderSize) return true; | 
| + | 
| +    unsigned Offset = ( BufPtr[OffsetField  ]        | | 
| +                       (BufPtr[OffsetField+1] << 8)  | | 
| +                       (BufPtr[OffsetField+2] << 16) | | 
| +                       (BufPtr[OffsetField+3] << 24)); | 
| +    unsigned Size   = ( BufPtr[SizeField    ]        | | 
| +                       (BufPtr[SizeField  +1] << 8)  | | 
| +                       (BufPtr[SizeField  +2] << 16) | | 
| +                       (BufPtr[SizeField  +3] << 24)); | 
| + | 
| +    // Verify that Offset+Size fits in the file. | 
| +    if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr)) | 
| +      return true; | 
| +    BufPtr += Offset; | 
| +    BufEnd = BufPtr+Size; | 
| +    return false; | 
| +  } | 
| + | 
| } // end llvm namespace | 
| #endif | 
|  |