X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FBitcode%2FReaderWriter.h;h=6797aa133c42a63e9caa8bf4f49a1c7f19cbb0bb;hp=fa754c014621f52af5698561d1718ae014f24bca;hb=cd52a7a381a73c53ec4ef517ad87f19808cb1a28;hpb=c6cff9daf4ffd38b01ac79f6f6be752e0be4c704 diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index fa754c01462..6797aa133c4 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -11,62 +11,69 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_H -#define LLVM_BITCODE_H +#ifndef LLVM_BITCODE_READERWRITER_H +#define LLVM_BITCODE_READERWRITER_H +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include #include namespace llvm { - class Module; - class MemoryBuffer; - class ModulePass; class BitstreamWriter; + class DataStreamer; class LLVMContext; + class Module; + class ModulePass; class raw_ostream; - - /// getLazyBitcodeModule - 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 *getLazyBitcodeModule(MemoryBuffer *Buffer, - LLVMContext& Context, - std::string *ErrMsg = 0); - - /// getBitcodeTargetTriple - Read the header of the specified bitcode - /// buffer and extract just the triple information. If successful, - /// this returns a string and *does not* take ownership - /// of 'buffer'. On error, this returns "", and fills in *ErrMsg - /// if ErrMsg is non-null. - std::string getBitcodeTargetTriple(MemoryBuffer *Buffer, - LLVMContext& Context, - std::string *ErrMsg = 0); - - /// ParseBitcodeFile - 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 *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context, - std::string *ErrMsg = 0); - - /// WriteBitcodeToFile - Write the specified module to the specified - /// raw output stream. For streams where it matters, the given stream - /// should be in "binary" mode. - void WriteBitcodeToFile(const Module *M, raw_ostream &Out); - - /// WriteBitcodeToStream - Write the specified module to the specified - /// raw output stream. - void WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream); - - /// createBitcodeWriterPass - Create and return a pass that writes the module - /// to the specified ostream. - ModulePass *createBitcodeWriterPass(raw_ostream &Str); - - + + /// Read the header of the specified bitcode buffer and prepare for lazy + /// deserialization of function bodies. If ShouldLazyLoadMetadata is true, + /// lazily load metadata as well. If successful, this moves Buffer. On + /// error, this *does not* move Buffer. + ErrorOr> + getLazyBitcodeModule(std::unique_ptr &&Buffer, + LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr, + bool ShouldLazyLoadMetadata = false); + + /// Read the header of the specified stream and prepare for lazy + /// deserialization and streaming of function bodies. + ErrorOr> getStreamedBitcodeModule( + StringRef Name, std::unique_ptr Streamer, + LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// Read the header of the specified bitcode buffer and extract just the + /// triple information. If successful, this returns a string. On error, this + /// returns "". + std::string + getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// Read the specified bitcode file, returning the module. + ErrorOr> + parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// \brief Write the specified module to the specified raw output stream. + /// + /// For streams where it matters, the given stream should be in "binary" + /// mode. + /// + /// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a + /// Value in \c M. These will be reconstructed exactly when \a M is + /// deserialized. + void WriteBitcodeToFile(const Module *M, raw_ostream &Out, + bool ShouldPreserveUseListOrder = false); + /// isBitcodeWrapper - Return true if the given bytes are the magic bytes /// for an LLVM IR bitcode wrapper. /// - static inline bool isBitcodeWrapper(const unsigned char *BufPtr, - const unsigned char *BufEnd) { + inline bool isBitcodeWrapper(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 && @@ -79,8 +86,8 @@ namespace llvm { /// isRawBitcode - Return true if the given bytes are the magic bytes for /// raw LLVM IR bitcode (without a wrapper). /// - static inline bool isRawBitcode(const unsigned char *BufPtr, - const unsigned char *BufEnd) { + inline bool isRawBitcode(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 && @@ -93,8 +100,8 @@ namespace llvm { /// isBitcode - Return true if the given bytes are the magic bytes for /// LLVM IR bitcode, either with or without a wrapper. /// - static bool inline isBitcode(const unsigned char *BufPtr, - const unsigned char *BufEnd) { + inline bool isBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { return isBitcodeWrapper(BufPtr, BufEnd) || isRawBitcode(BufPtr, BufEnd); } @@ -109,37 +116,60 @@ namespace llvm { /// uint32_t BitcodeSize; // Size of traditional bitcode file. /// ... potentially other gunk ... /// }; - /// + /// /// 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. - static inline bool SkipBitcodeWrapperHeader(unsigned char *&BufPtr, - unsigned char *&BufEnd) { + /// If 'VerifyBufferSize' is true, check that the buffer is large enough to + /// contain the whole bitcode file. + inline bool SkipBitcodeWrapperHeader(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)); - + + unsigned Offset = support::endian::read32le(&BufPtr[OffsetField]); + unsigned Size = support::endian::read32le(&BufPtr[SizeField]); + // Verify that Offset+Size fits in the file. - if (Offset+Size > unsigned(BufEnd-BufPtr)) + if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr)) return true; BufPtr += Offset; BufEnd = BufPtr+Size; return false; } + + const std::error_category &BitcodeErrorCategory(); + enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; + inline std::error_code make_error_code(BitcodeError E) { + return std::error_code(static_cast(E), BitcodeErrorCategory()); + } + + class BitcodeDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + std::error_code EC; + + public: + BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity, + const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; + std::error_code getError() const { return EC; }; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_Bitcode; + } + }; + } // End llvm namespace +namespace std { +template <> struct is_error_code_enum : std::true_type {}; +} + #endif