X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FBitcode%2FReader%2FBitcodeReader.h;h=593d8f93ccf3fb1ca60a8cec1cc6b1ea99a51a0c;hb=c34a25d59d382aa00a94b3f0603ce8724c66606d;hp=65c495b6699698445381462cc0eff9a36e2b236f;hpb=980e5aad4cfaa32e13b297f4201eb1088ca96cc4;p=oota-llvm.git diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h index 65c495b6699..593d8f93ccf 100644 --- a/lib/Bitcode/Reader/BitcodeReader.h +++ b/lib/Bitcode/Reader/BitcodeReader.h @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -14,116 +14,362 @@ #ifndef BITCODE_READER_H #define BITCODE_READER_H -#include "llvm/ModuleProvider.h" -#include "llvm/Type.h" -#include "llvm/User.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/LLVMBitCodes.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/GVMaterializer.h" +#include "llvm/IR/OperandTraits.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/system_error.h" #include namespace llvm { class MemoryBuffer; - -class BitcodeReaderValueList : public User { - std::vector Uses; + class LLVMContext; + +//===----------------------------------------------------------------------===// +// BitcodeReaderValueList Class +//===----------------------------------------------------------------------===// + +class BitcodeReaderValueList { + std::vector ValuePtrs; + + /// ResolveConstants - As we resolve forward-referenced constants, we add + /// information about them to this vector. This allows us to resolve them in + /// bulk instead of resolving each reference at a time. See the code in + /// ResolveConstantForwardRefs for more information about this. + /// + /// The key of this vector is the placeholder constant, the value is the slot + /// number that holds the resolved value. + typedef std::vector > ResolveConstantsTy; + ResolveConstantsTy ResolveConstants; + LLVMContext &Context; public: - BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0) {} - + BitcodeReaderValueList(LLVMContext &C) : Context(C) {} + ~BitcodeReaderValueList() { + assert(ResolveConstants.empty() && "Constants not resolved?"); + } + // vector compatibility methods - unsigned size() const { return getNumOperands(); } + unsigned size() const { return ValuePtrs.size(); } + void resize(unsigned N) { ValuePtrs.resize(N); } void push_back(Value *V) { - Uses.push_back(Use(V, this)); - OperandList = &Uses[0]; - ++NumOperands; - } - - Value *operator[](unsigned i) const { return getOperand(i); } - - Value *back() const { return Uses.back(); } - void pop_back() { Uses.pop_back(); --NumOperands; } - bool empty() const { return NumOperands == 0; } + ValuePtrs.push_back(V); + } + + void clear() { + assert(ResolveConstants.empty() && "Constants not resolved?"); + ValuePtrs.clear(); + } + + Value *operator[](unsigned i) const { + assert(i < ValuePtrs.size()); + return ValuePtrs[i]; + } + + Value *back() const { return ValuePtrs.back(); } + void pop_back() { ValuePtrs.pop_back(); } + bool empty() const { return ValuePtrs.empty(); } void shrinkTo(unsigned N) { - assert(N <= NumOperands && "Invalid shrinkTo request!"); - Uses.resize(N); - NumOperands = N; + assert(N <= size() && "Invalid shrinkTo request!"); + ValuePtrs.resize(N); + } + + Constant *getConstantFwdRef(unsigned Idx, Type *Ty); + Value *getValueFwdRef(unsigned Idx, Type *Ty); + + void AssignValue(Value *V, unsigned Idx); + + /// ResolveConstantForwardRefs - Once all constants are read, this method bulk + /// resolves any forward references. + void ResolveConstantForwardRefs(); +}; + + +//===----------------------------------------------------------------------===// +// BitcodeReaderMDValueList Class +//===----------------------------------------------------------------------===// + +class BitcodeReaderMDValueList { + std::vector MDValuePtrs; + + LLVMContext &Context; +public: + BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {} + + // vector compatibility methods + unsigned size() const { return MDValuePtrs.size(); } + void resize(unsigned N) { MDValuePtrs.resize(N); } + void push_back(Value *V) { MDValuePtrs.push_back(V); } + void clear() { MDValuePtrs.clear(); } + Value *back() const { return MDValuePtrs.back(); } + void pop_back() { MDValuePtrs.pop_back(); } + bool empty() const { return MDValuePtrs.empty(); } + + Value *operator[](unsigned i) const { + assert(i < MDValuePtrs.size()); + return MDValuePtrs[i]; } - virtual void print(std::ostream&) const {} - - Constant *getConstantFwdRef(unsigned Idx, const Type *Ty); - void initVal(unsigned Idx, Value *V) { - assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!"); - Uses[Idx].init(V, this); + + void shrinkTo(unsigned N) { + assert(N <= size() && "Invalid shrinkTo request!"); + MDValuePtrs.resize(N); } + + Value *getValueFwdRef(unsigned Idx); + void AssignValue(Value *V, unsigned Idx); }; - -class BitcodeReader : public ModuleProvider { +class BitcodeReader : public GVMaterializer { + LLVMContext &Context; + Module *TheModule; MemoryBuffer *Buffer; - BitstreamReader Stream; - - const char *ErrorString; - - std::vector TypeList; + bool BufferOwned; + std::unique_ptr StreamFile; + BitstreamCursor Stream; + DataStreamer *LazyStreamer; + uint64_t NextUnreadBit; + bool SeenValueSymbolTable; + + std::vector TypeList; BitcodeReaderValueList ValueList; + BitcodeReaderMDValueList MDValueList; + SmallVector InstructionList; + SmallVector, 64> UseListRecords; + std::vector > GlobalInits; std::vector > AliasInits; - + std::vector > FunctionPrefixes; + + SmallVector InstsWithTBAATag; + + /// MAttributes - The set of attributes by index. Index zero in the + /// file is for null, and is thus not represented here. As such all indices + /// are off by one. + std::vector MAttributes; + + /// \brief The set of attribute groups. + std::map MAttributeGroups; + /// FunctionBBs - While parsing a function body, this is a list of the basic /// blocks for the function. std::vector FunctionBBs; - + // When reading the module header, this list is populated with functions that // have bodies later in the file. std::vector FunctionsWithBodies; - - // After the module header has been read, the FunctionsWithBodies list is - // reversed. This keeps track of whether we've done this yet. - bool HasReversedFunctionsWithBodies; - + + // When intrinsic functions are encountered which require upgrading they are + // stored here with their replacement function. + typedef std::vector > UpgradedIntrinsicMap; + UpgradedIntrinsicMap UpgradedIntrinsics; + + // Map the bitcode's custom MDKind ID to the Module's MDKind ID. + DenseMap MDKindMap; + + // Several operations happen after the module header has been read, but + // before function bodies are processed. This keeps track of whether + // we've done this yet. + bool SeenFirstFunctionBody; + /// DeferredFunctionInfo - When function bodies are initially scanned, this - /// map contains info about where to find deferred function body (in the - /// stream) and what linkage the original function had. - DenseMap > DeferredFunctionInfo; + /// map contains info about where to find deferred function body in the + /// stream. + DenseMap DeferredFunctionInfo; + + /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These + /// are resolved lazily when functions are loaded. + typedef std::pair BlockAddrRefTy; + DenseMap > BlockAddrFwdRefs; + + /// UseRelativeIDs - Indicates that we are using a new encoding for + /// instruction operands where most operands in the current + /// FUNCTION_BLOCK are encoded relative to the instruction number, + /// for a more compact encoding. Some instruction operands are not + /// relative to the instruction ID: basic block numbers, and types. + /// Once the old style function blocks have been phased out, we would + /// not need this flag. + bool UseRelativeIDs; + + static const error_category &BitcodeErrorCategory(); + public: - BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) { - HasReversedFunctionsWithBodies = false; - } - ~BitcodeReader(); - - - /// releaseMemoryBuffer - This causes the reader to completely forget about - /// the memory buffer it contains, which prevents the buffer from being - /// destroyed when it is deleted. - void releaseMemoryBuffer() { - Buffer = 0; - } - - virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0); - virtual Module *materializeModule(std::string *ErrInfo = 0); - - bool Error(const char *Str) { - ErrorString = Str; - return true; - } - const char *getErrorString() const { return ErrorString; } - + enum ErrorType { + BitcodeStreamInvalidSize, + ConflictingMETADATA_KINDRecords, + CouldNotFindFunctionInStream, + ExpectedConstant, + InsufficientFunctionProtos, + InvalidBitcodeSignature, + InvalidBitcodeWrapperHeader, + InvalidConstantReference, + InvalidID, // A read identifier is not found in the table it should be in. + InvalidInstructionWithNoBB, + InvalidRecord, // A read record doesn't have the expected size or structure + InvalidTypeForValue, // Type read OK, but is invalid for its use + InvalidTYPETable, + InvalidType, // We were unable to read a type + MalformedBlock, // We are unable to advance in the stream. + MalformedGlobalInitializerSet, + InvalidMultipleBlocks, // We found multiple blocks of a kind that should + // have only one + NeverResolvedValueFoundInFunction, + InvalidValue // Invalid version, inst number, attr number, etc + }; + + error_code Error(ErrorType E) { + return error_code(E, BitcodeErrorCategory()); + } + + explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C) + : Context(C), TheModule(nullptr), Buffer(buffer), BufferOwned(false), + LazyStreamer(nullptr), NextUnreadBit(0), SeenValueSymbolTable(false), + ValueList(C), MDValueList(C), + SeenFirstFunctionBody(false), UseRelativeIDs(false) { + } + explicit BitcodeReader(DataStreamer *streamer, LLVMContext &C) + : Context(C), TheModule(nullptr), Buffer(nullptr), BufferOwned(false), + LazyStreamer(streamer), NextUnreadBit(0), SeenValueSymbolTable(false), + ValueList(C), MDValueList(C), + SeenFirstFunctionBody(false), UseRelativeIDs(false) { + } + ~BitcodeReader() { + FreeState(); + } + + void materializeForwardReferencedFunctions(); + + void FreeState(); + + /// setBufferOwned - If this is true, the reader will destroy the MemoryBuffer + /// when the reader is destroyed. + void setBufferOwned(bool Owned) { BufferOwned = Owned; } + + bool isMaterializable(const GlobalValue *GV) const override; + bool isDematerializable(const GlobalValue *GV) const override; + error_code Materialize(GlobalValue *GV) override; + error_code MaterializeModule(Module *M) override; + void Dematerialize(GlobalValue *GV) override; + /// @brief Main interface to parsing a bitcode buffer. /// @returns true if an error occurred. - bool ParseBitcode(); + error_code ParseBitcodeInto(Module *M); + + /// @brief Cheap mechanism to just extract module triple + /// @returns true if an error occurred. + error_code ParseTriple(std::string &Triple); + + static uint64_t decodeSignRotatedValue(uint64_t V); + private: - const Type *getTypeByID(unsigned ID, bool isTypeTable = false); - - bool ParseModule(const std::string &ModuleID); - bool ParseTypeTable(); - bool ParseTypeSymbolTable(); - bool ParseValueSymbolTable(); - bool ParseConstants(); - bool RememberAndSkipFunctionBody(); - bool ParseFunctionBody(Function *F); - bool ResolveGlobalAndAliasInits(); + Type *getTypeByID(unsigned ID); + Value *getFnValueByID(unsigned ID, Type *Ty) { + if (Ty && Ty->isMetadataTy()) + return MDValueList.getValueFwdRef(ID); + return ValueList.getValueFwdRef(ID, Ty); + } + BasicBlock *getBasicBlock(unsigned ID) const { + if (ID >= FunctionBBs.size()) return nullptr; // Invalid ID + return FunctionBBs[ID]; + } + AttributeSet getAttributes(unsigned i) const { + if (i-1 < MAttributes.size()) + return MAttributes[i-1]; + return AttributeSet(); + } + + /// getValueTypePair - Read a value/type pair out of the specified record from + /// slot 'Slot'. Increment Slot past the number of slots used in the record. + /// Return true on failure. + bool getValueTypePair(SmallVectorImpl &Record, unsigned &Slot, + unsigned InstNum, Value *&ResVal) { + if (Slot == Record.size()) return true; + unsigned ValNo = (unsigned)Record[Slot++]; + // Adjust the ValNo, if it was encoded relative to the InstNum. + if (UseRelativeIDs) + ValNo = InstNum - ValNo; + if (ValNo < InstNum) { + // If this is not a forward reference, just return the value we already + // have. + ResVal = getFnValueByID(ValNo, nullptr); + return ResVal == nullptr; + } else if (Slot == Record.size()) { + return true; + } + + unsigned TypeNo = (unsigned)Record[Slot++]; + ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo)); + return ResVal == nullptr; + } + + /// popValue - Read a value out of the specified record from slot 'Slot'. + /// Increment Slot past the number of slots used by the value in the record. + /// Return true if there is an error. + bool popValue(SmallVectorImpl &Record, unsigned &Slot, + unsigned InstNum, Type *Ty, Value *&ResVal) { + if (getValue(Record, Slot, InstNum, Ty, ResVal)) + return true; + // All values currently take a single record slot. + ++Slot; + return false; + } + + /// getValue -- Like popValue, but does not increment the Slot number. + bool getValue(SmallVectorImpl &Record, unsigned Slot, + unsigned InstNum, Type *Ty, Value *&ResVal) { + ResVal = getValue(Record, Slot, InstNum, Ty); + return ResVal == nullptr; + } + + /// getValue -- Version of getValue that returns ResVal directly, + /// or 0 if there is an error. + Value *getValue(SmallVectorImpl &Record, unsigned Slot, + unsigned InstNum, Type *Ty) { + if (Slot == Record.size()) return nullptr; + unsigned ValNo = (unsigned)Record[Slot]; + // Adjust the ValNo, if it was encoded relative to the InstNum. + if (UseRelativeIDs) + ValNo = InstNum - ValNo; + return getFnValueByID(ValNo, Ty); + } + + /// getValueSigned -- Like getValue, but decodes signed VBRs. + Value *getValueSigned(SmallVectorImpl &Record, unsigned Slot, + unsigned InstNum, Type *Ty) { + if (Slot == Record.size()) return nullptr; + unsigned ValNo = (unsigned)decodeSignRotatedValue(Record[Slot]); + // Adjust the ValNo, if it was encoded relative to the InstNum. + if (UseRelativeIDs) + ValNo = InstNum - ValNo; + return getFnValueByID(ValNo, Ty); + } + + error_code ParseAttrKind(uint64_t Code, Attribute::AttrKind *Kind); + error_code ParseModule(bool Resume); + error_code ParseAttributeBlock(); + error_code ParseAttributeGroupBlock(); + error_code ParseTypeTable(); + error_code ParseTypeTableBody(); + + error_code ParseValueSymbolTable(); + error_code ParseConstants(); + error_code RememberAndSkipFunctionBody(); + error_code ParseFunctionBody(Function *F); + error_code GlobalCleanup(); + error_code ResolveGlobalAndAliasInits(); + error_code ParseMetadata(); + error_code ParseMetadataAttachment(); + error_code ParseModuleTriple(std::string &Triple); + error_code ParseUseLists(); + error_code InitStream(); + error_code InitStreamFromBuffer(); + error_code InitLazyStream(); + error_code FindFunctionInStream(Function *F, + DenseMap::iterator DeferredFunctionInfoIterator); }; - + } // End llvm namespace #endif