//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_BITCODE_H
-#define LLVM_BITCODE_H
+#ifndef LLVM_BITCODE_READERWRITER_H
+#define LLVM_BITCODE_READERWRITER_H
-#include <iosfwd>
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/FunctionInfo.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
#include <string>
namespace llvm {
- class Module;
- class ModuleProvider;
- class MemoryBuffer;
- class ModulePass;
class BitstreamWriter;
+ class DataStreamer;
class LLVMContext;
+ class Module;
+ class ModulePass;
class raw_ostream;
-
- /// getBitcodeModuleProvider - 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.
- ModuleProvider *getBitcodeModuleProvider(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 output
- /// stream.
- void WriteBitcodeToFile(const Module *M, std::ostream &Out);
-
- /// WriteBitcodeToFile - Write the specified module to the specified
- /// raw output stream.
- 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(std::ostream &Str);
-
- /// createBitcodeWriterPass - Create and return a pass that writes the module
- /// to the specified ostream.
- ModulePass *createBitcodeWriterPass(raw_ostream &Str);
-
-
- /// isBitcodeWrapper - Return true fi this is a wrapper for LLVM IR bitcode
- /// files.
- static bool inline isBitcodeWrapper(unsigned char *BufPtr,
- unsigned char *BufEnd) {
- return (BufPtr != BufEnd && BufPtr[0] == 0xDE && BufPtr[1] == 0xC0 &&
- BufPtr[2] == 0x17 && BufPtr[3] == 0x0B);
+
+ /// 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<std::unique_ptr<Module>>
+ getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&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<std::unique_ptr<Module>> getStreamedBitcodeModule(
+ StringRef Name, std::unique_ptr<DataStreamer> 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<std::unique_ptr<Module>>
+ parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr);
+
+ /// Check if the given bitcode buffer contains a function summary block.
+ bool hasFunctionSummary(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler);
+
+ /// Parse the specified bitcode buffer, returning the function info index.
+ /// If ExportingModule is true, check for functions in the index from this
+ /// module when the combined index is built during parsing and set flag.
+ /// If IsLazy is true, parse the entire function summary into
+ /// the index. Otherwise skip the function summary section, and only create
+ /// an index object with a map from function name to function summary offset.
+ /// The index is used to perform lazy function summary reading later.
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>>
+ getFunctionInfoIndex(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler,
+ const Module *ExportingModule = nullptr,
+ bool IsLazy = false);
+
+ /// This method supports lazy reading of function summary data from the
+ /// combined index during function importing. When reading the combined index
+ /// file, getFunctionInfoIndex is first invoked with IsLazy=true.
+ /// Then this method is called for each function considered for importing,
+ /// to parse the summary information for the given function name into
+ /// the index.
+ std::error_code
+ readFunctionSummary(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler,
+ StringRef FunctionName,
+ std::unique_ptr<FunctionInfoIndex> Index);
+
+ /// \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.
+ ///
+ /// If \c EmitFunctionSummary, emit the function summary index (currently
+ /// for use in ThinLTO optimization).
+ void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
+ bool ShouldPreserveUseListOrder = false,
+ bool EmitFunctionSummary = false);
+
+ /// Write the specified function summary index to the given raw output stream,
+ /// where it will be written in a new bitcode block. This is used when
+ /// writing the combined index file for ThinLTO.
+ void WriteFunctionSummaryToFile(const FunctionInfoIndex &Index,
+ raw_ostream &Out);
+
+ /// isBitcodeWrapper - Return true if the given bytes are the magic bytes
+ /// for an LLVM IR bitcode wrapper.
+ ///
+ 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 &&
+ BufPtr[0] == 0xDE &&
+ BufPtr[1] == 0xC0 &&
+ BufPtr[2] == 0x17 &&
+ BufPtr[3] == 0x0B;
}
-
+
+ /// isRawBitcode - Return true if the given bytes are the magic bytes for
+ /// raw LLVM IR bitcode (without a wrapper).
+ ///
+ 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 &&
+ BufPtr[0] == 'B' &&
+ BufPtr[1] == 'C' &&
+ BufPtr[2] == 0xc0 &&
+ BufPtr[3] == 0xde;
+ }
+
+ /// isBitcode - Return true if the given bytes are the magic bytes for
+ /// LLVM IR bitcode, either with or without a wrapper.
+ ///
+ inline bool isBitcode(const unsigned char *BufPtr,
+ const unsigned char *BufEnd) {
+ return isBitcodeWrapper(BufPtr, BufEnd) ||
+ isRawBitcode(BufPtr, BufEnd);
+ }
+
/// SkipBitcodeWrapperHeader - Some systems wrap bc files with a special
/// header for padding or other reasons. The format of this header is:
///
/// 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 = 1, CorruptedBitcode };
+ inline std::error_code make_error_code(BitcodeError E) {
+ return std::error_code(static_cast<int>(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<llvm::BitcodeError> : std::true_type {};
+}
+
#endif