aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
diff options
context:
space:
mode:
authorKarl Schimpf <kschimpf@google.com>2013-05-01 10:42:30 -0700
committerKarl Schimpf <kschimpf@google.com>2013-05-01 10:42:30 -0700
commitf42b26d0d46034cb2b91df810477fc0df2e67b27 (patch)
treebc8749b8fa6e36670df3171a27d9db2bfab608a7 /include/llvm/Bitcode/NaCl/NaClReaderWriter.h
parent595239b2b7297b62d9f804770f5f43d8bf637a0f (diff)
Copy LLVM bitcode reader to generate a PNaCl wire format reader.
Copy classes for LLVM BitcodeReader into a NaCl subdirectory, to create a wire format version. Renames classes/functions to include NaCl prefix, so that they don't conflict with the LLVM Bitcode reader. Also implements pnacl-thaw, showing that we can read the PNaCl wire format files. BUG= https://code.google.com/p/nativeclient/issues/detail?id=3405 R=jvoung@chromium.org Review URL: https://codereview.chromium.org/14314016
Diffstat (limited to 'include/llvm/Bitcode/NaCl/NaClReaderWriter.h')
-rw-r--r--include/llvm/Bitcode/NaCl/NaClReaderWriter.h122
1 files changed, 121 insertions, 1 deletions
diff --git a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
index 2b905b97e8..d505af0a1f 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