Index: clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h =================================================================== --- clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h +++ clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h @@ -35,10 +35,8 @@ class ObjectFilePCHContainerReader : public PCHContainerReader { StringRef getFormat() const override { return "obj"; } - /// Initialize an llvm::BitstreamReader with the serialized - /// AST inside the PCH container Buffer. - void ExtractPCH(llvm::MemoryBufferRef Buffer, - llvm::BitstreamReader &StreamFile) const override; + /// Returns the serialized AST inside the PCH container Buffer. + StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override; }; } Index: clang/include/clang/Frontend/PCHContainerOperations.h =================================================================== --- clang/include/clang/Frontend/PCHContainerOperations.h +++ clang/include/clang/Frontend/PCHContainerOperations.h @@ -17,7 +17,6 @@ namespace llvm { class raw_pwrite_stream; -class BitstreamReader; } using llvm::StringRef; @@ -63,10 +62,8 @@ /// Equivalent to the format passed to -fmodule-format= virtual StringRef getFormat() const = 0; - /// Initialize an llvm::BitstreamReader with the serialized AST inside - /// the PCH container Buffer. - virtual void ExtractPCH(llvm::MemoryBufferRef Buffer, - llvm::BitstreamReader &StreamFile) const = 0; + /// Returns the serialized AST inside the PCH container Buffer. + virtual StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0; }; /// Implements write operations for a raw pass-through PCH container. @@ -87,9 +84,8 @@ class RawPCHContainerReader : public PCHContainerReader { StringRef getFormat() const override { return "raw"; } - /// Initialize an llvm::BitstreamReader with Buffer. - void ExtractPCH(llvm::MemoryBufferRef Buffer, - llvm::BitstreamReader &StreamFile) const override; + /// Simply returns the buffer contained in Buffer. + StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override; }; /// A registry of PCHContainerWriter and -Reader objects for different formats. Index: clang/include/clang/Serialization/Module.h =================================================================== --- clang/include/clang/Serialization/Module.h +++ clang/include/clang/Serialization/Module.h @@ -173,8 +173,8 @@ /// \brief The global bit offset (or base) of this module uint64_t GlobalBitOffset; - /// \brief The bitstream reader from which we'll read the AST file. - llvm::BitstreamReader StreamFile; + /// \brief The serialized bitstream data for this file. + StringRef Data; /// \brief The main bitstream cursor for the main block. llvm::BitstreamCursor Stream; Index: clang/include/clang/Serialization/ModuleManager.h =================================================================== --- clang/include/clang/Serialization/ModuleManager.h +++ clang/include/clang/Serialization/ModuleManager.h @@ -175,7 +175,7 @@ OutOfDate }; - typedef ASTFileSignature(*ASTFileSignatureReader)(llvm::BitstreamReader &); + typedef ASTFileSignature(*ASTFileSignatureReader)(StringRef); /// \brief Attempts to create a new module and add it to the list of known /// modules. Index: clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp =================================================================== --- clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -312,8 +312,9 @@ CI, MainFileName, OutputFileName, std::move(OS), Buffer); } -void ObjectFilePCHContainerReader::ExtractPCH( - llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { +StringRef +ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { + StringRef PCH; auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer); if (OFOrErr) { auto &OF = OFOrErr.get(); @@ -323,10 +324,8 @@ StringRef Name; Section.getName(Name); if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) { - StringRef Buf; - Section.getContents(Buf); - StreamFile = llvm::BitstreamReader(Buf); - return; + Section.getContents(PCH); + return PCH; } } } @@ -334,8 +333,9 @@ if (EIB.convertToErrorCode() == llvm::object::object_error::invalid_file_type) // As a fallback, treat the buffer as a raw AST. - StreamFile = llvm::BitstreamReader(Buffer); + PCH = Buffer.getBuffer(); else EIB.log(llvm::errs()); }); + return PCH; } Index: clang/lib/Frontend/PCHContainerOperations.cpp =================================================================== --- clang/lib/Frontend/PCHContainerOperations.cpp +++ clang/lib/Frontend/PCHContainerOperations.cpp @@ -58,9 +58,9 @@ return llvm::make_unique(std::move(OS), Buffer); } -void RawPCHContainerReader::ExtractPCH( - llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { - StreamFile = llvm::BitstreamReader(Buffer); +StringRef +RawPCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { + return Buffer.getBuffer(); } PCHContainerOperations::PCHContainerOperations() { Index: clang/lib/Frontend/SerializedDiagnosticReader.cpp =================================================================== --- clang/lib/Frontend/SerializedDiagnosticReader.cpp +++ clang/lib/Frontend/SerializedDiagnosticReader.cpp @@ -24,8 +24,8 @@ if (!Buffer) return SDError::CouldNotLoad; - llvm::BitstreamReader StreamFile(**Buffer); - llvm::BitstreamCursor Stream(StreamFile); + llvm::BitstreamCursor Stream(**Buffer); + Optional BlockInfo; // Sniff for the signature. if (Stream.Read(8) != 'D' || @@ -41,10 +41,13 @@ std::error_code EC; switch (Stream.ReadSubBlockID()) { - case llvm::bitc::BLOCKINFO_BLOCK_ID: - if (Stream.ReadBlockInfoBlock()) + case llvm::bitc::BLOCKINFO_BLOCK_ID: { + BlockInfo = Stream.ReadBlockInfoBlock(); + if (!BlockInfo) return SDError::MalformedBlockInfoBlock; + Stream.setBlockInfo(&*BlockInfo); continue; + } case BLOCK_META: if ((EC = readMetaBlock(Stream))) return EC; Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1711,7 +1711,7 @@ BitstreamCursor &MacroCursor = I->MacroCursor; // If there was no preprocessor block, skip this file. - if (!MacroCursor.getBitStreamReader()) + if (MacroCursor.getBitcodeBytes().empty()) continue; BitstreamCursor Cursor = MacroCursor; @@ -3798,7 +3798,7 @@ return Success; } -static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile); +static ASTFileSignature readASTFileSignature(StringRef PCH); /// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'. static bool startsWithASTFileMagic(BitstreamCursor &Stream) { @@ -3885,8 +3885,8 @@ ModuleFile &F = *M; BitstreamCursor &Stream = F.Stream; - PCHContainerRdr.ExtractPCH(F.Buffer->getMemBufferRef(), F.StreamFile); - Stream.init(&F.StreamFile); + Stream = + BitstreamCursor(PCHContainerRdr.ExtractPCH(F.Buffer->getMemBufferRef())); F.SizeInBits = F.Buffer->getBufferSize() * 8; // Sniff for the signature. @@ -4175,10 +4175,10 @@ // Nothing to do for now. } -/// \brief Reads and return the signature record from \p StreamFile's control -/// block, or else returns 0. -static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){ - BitstreamCursor Stream(StreamFile); +/// \brief Reads and return the signature record from \p PCH's control block, or +/// else returns 0. +static ASTFileSignature readASTFileSignature(StringRef PCH) { + BitstreamCursor Stream(PCH); if (!startsWithASTFileMagic(Stream)) return 0; @@ -4216,9 +4216,8 @@ } // Initialize the stream - llvm::BitstreamReader StreamFile; - PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile); - BitstreamCursor Stream(StreamFile); + BitstreamCursor Stream( + PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef())); // Sniff for the signature. if (!startsWithASTFileMagic(Stream)) { @@ -4318,9 +4317,8 @@ } // Initialize the stream - llvm::BitstreamReader StreamFile; - PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile); - BitstreamCursor Stream(StreamFile); + BitstreamCursor Stream( + PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef())); // Sniff for the signature. if (!startsWithASTFileMagic(Stream)) Index: clang/lib/Serialization/GlobalModuleIndex.cpp =================================================================== --- clang/lib/Serialization/GlobalModuleIndex.cpp +++ clang/lib/Serialization/GlobalModuleIndex.cpp @@ -245,11 +245,8 @@ return std::make_pair(nullptr, EC_NotFound); std::unique_ptr Buffer = std::move(BufferOrErr.get()); - /// \brief The bitstream reader from which we'll read the AST file. - llvm::BitstreamReader Reader(*Buffer); - /// \brief The main bitstream cursor for the main block. - llvm::BitstreamCursor Cursor(Reader); + llvm::BitstreamCursor Cursor(*Buffer); // Sniff for the signature. if (Cursor.Read(8) != 'B' || @@ -503,9 +500,8 @@ } // Initialize the input stream - llvm::BitstreamReader InStreamFile; - PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), InStreamFile); - llvm::BitstreamCursor InStream(InStreamFile); + llvm::BitstreamCursor InStream( + PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef())); // Sniff for the signature. if (InStream.Read(8) != 'C' || Index: clang/lib/Serialization/ModuleManager.cpp =================================================================== --- clang/lib/Serialization/ModuleManager.cpp +++ clang/lib/Serialization/ModuleManager.cpp @@ -135,15 +135,15 @@ } // Initialize the stream. - PCHContainerRdr.ExtractPCH(ModuleEntry->Buffer->getMemBufferRef(), - ModuleEntry->StreamFile); + ModuleEntry->Data = + PCHContainerRdr.ExtractPCH(ModuleEntry->Buffer->getMemBufferRef()); } if (ExpectedSignature) { // If we've not read the control block yet, read the signature eagerly now // so that we can check it. if (!ModuleEntry->Signature) - ModuleEntry->Signature = ReadSignature(ModuleEntry->StreamFile); + ModuleEntry->Signature = ReadSignature(ModuleEntry->Data); if (ModuleEntry->Signature != ExpectedSignature) { ErrorStr = ModuleEntry->Signature ? "signature mismatch" Index: llvm/include/llvm/Bitcode/BitstreamReader.h =================================================================== --- llvm/include/llvm/Bitcode/BitstreamReader.h +++ llvm/include/llvm/Bitcode/BitstreamReader.h @@ -35,11 +35,8 @@ namespace llvm { -/// This class is used to read from an LLVM bitcode stream, maintaining -/// information that is global to decoding the entire file. While a file is -/// being read, multiple cursors can be independently advanced or skipped around -/// within the file. These are represented by the BitstreamCursor class. -class BitstreamReader { +/// This class maintains the abbreviations read from a block info block. +class BitstreamBlockInfo { public: /// This contains information emitted to BLOCKINFO_BLOCK blocks. These /// describe abbreviations that all blocks of the specified ID inherit. @@ -51,39 +48,9 @@ }; private: - ArrayRef BitcodeBytes; - std::vector BlockInfoRecords; - /// This is set to true if we don't care about the block/record name - /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. - bool IgnoreBlockInfoNames = true; - public: - BitstreamReader() = default; - BitstreamReader(ArrayRef BitcodeBytes) - : BitcodeBytes(BitcodeBytes) {} - BitstreamReader(StringRef BitcodeBytes) - : BitcodeBytes(reinterpret_cast(BitcodeBytes.data()), - BitcodeBytes.size()) {} - BitstreamReader(MemoryBufferRef BitcodeBytes) - : BitstreamReader(BitcodeBytes.getBuffer()) {} - - ArrayRef getBitcodeBytes() { return BitcodeBytes; } - - /// This is called by clients that want block/record name information. - void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } - bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } - - //===--------------------------------------------------------------------===// - // Block Manipulation - //===--------------------------------------------------------------------===// - - /// Return true if we've already read and processed the block info block for - /// this Bitstream. We only process it for the first cursor that walks over - /// it. - bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } - /// If there is block info for the specified ID, return it, otherwise return /// null. const BlockInfo *getBlockInfo(unsigned BlockID) const { @@ -107,22 +74,13 @@ BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } - - /// Takes block info from the other bitstream reader. - /// - /// This is a "take" operation because BlockInfo records are non-trivial, and - /// indeed rather expensive. - void takeBlockInfo(BitstreamReader &&Other) { - assert(!hasBlockInfoRecords()); - BlockInfoRecords = std::move(Other.BlockInfoRecords); - } }; /// This represents a position within a bitstream. There may be multiple /// independent cursors reading within one bitstream, each maintaining their /// own local state. class SimpleBitstreamCursor { - BitstreamReader *R = nullptr; + ArrayRef BitcodeBytes; size_t NextChar = 0; public: @@ -144,17 +102,21 @@ static const size_t MaxChunkSize = sizeof(word_t) * 8; SimpleBitstreamCursor() = default; - - explicit SimpleBitstreamCursor(BitstreamReader &R) : R(&R) {} - explicit SimpleBitstreamCursor(BitstreamReader *R) : R(R) {} + explicit SimpleBitstreamCursor(ArrayRef BitcodeBytes) + : BitcodeBytes(BitcodeBytes) {} + explicit SimpleBitstreamCursor(StringRef BitcodeBytes) + : BitcodeBytes(reinterpret_cast(BitcodeBytes.data()), + BitcodeBytes.size()) {} + explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes) + : SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {} bool canSkipToPos(size_t pos) const { // pos can be skipped to if it is a valid address or one byte past the end. - return pos <= R->getBitcodeBytes().size(); + return pos <= BitcodeBytes.size(); } bool AtEndOfStream() { - return BitsInCurWord == 0 && R->getBitcodeBytes().size() <= NextChar; + return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar; } /// Return the bit # of the bit we are reading. @@ -165,8 +127,7 @@ // Return the byte # of the current bit. uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; } - BitstreamReader *getBitStreamReader() { return R; } - const BitstreamReader *getBitStreamReader() const { return R; } + ArrayRef getBitcodeBytes() const { return BitcodeBytes; } /// Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { @@ -183,27 +144,9 @@ Read(WordBitNo); } - /// Reset the stream to the bit pointed at by the specified pointer. - /// - /// The pointer must be a dereferenceable pointer into the bytes in the - /// underlying memory object. - void jumpToPointer(const uint8_t *Pointer) { - auto *Pointer0 = getPointerToByte(0, 1); - assert((intptr_t)Pointer0 <= (intptr_t)Pointer && - "Expected pointer into bitstream"); - - JumpToBit(8 * (Pointer - Pointer0)); - assert((intptr_t)getPointerToByte(getCurrentByteNo(), 1) == - (intptr_t)Pointer && - "Expected to reach pointer"); - } - void jumpToPointer(const char *Pointer) { - jumpToPointer((const uint8_t *)Pointer); - } - /// Get a pointer into the bitstream at the specified byte offset. const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) { - return R->getBitcodeBytes().data() + ByteNo; + return BitcodeBytes.data() + ByteNo; } /// Get a pointer into the bitstream at the specified bit offset. @@ -215,21 +158,20 @@ } void fillCurWord() { - ArrayRef Buf = R->getBitcodeBytes(); - if (NextChar >= Buf.size()) + if (NextChar >= BitcodeBytes.size()) report_fatal_error("Unexpected end of file"); // Read the next word from the stream. - const uint8_t *NextCharPtr = Buf.data() + NextChar; + const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar; unsigned BytesRead; - if (Buf.size() >= NextChar + sizeof(word_t)) { + if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) { BytesRead = sizeof(word_t); CurWord = support::endian::read( NextCharPtr); } else { // Short read. - BytesRead = Buf.size() - NextChar; + BytesRead = BitcodeBytes.size() - NextChar; CurWord = 0; for (unsigned B = 0; B != BytesRead; ++B) CurWord |= uint64_t(NextCharPtr[B]) << (B * 8); @@ -330,7 +272,7 @@ } /// Skip to the end of the file. - void skipToEnd() { NextChar = R->getBitcodeBytes().size(); } + void skipToEnd() { NextChar = BitcodeBytes.size(); } }; /// When advancing through a bitstream cursor, each advance can discover a few @@ -386,27 +328,25 @@ /// This tracks the codesize of parent blocks. SmallVector BlockScope; + BitstreamBlockInfo *BlockInfo = nullptr; + public: static const size_t MaxChunkSize = sizeof(word_t) * 8; BitstreamCursor() = default; - - explicit BitstreamCursor(BitstreamReader &R) { init(&R); } - - void init(BitstreamReader *R) { - freeState(); - SimpleBitstreamCursor::operator=(SimpleBitstreamCursor(R)); - CurCodeSize = 2; - } - - void freeState(); + explicit BitstreamCursor(ArrayRef BitcodeBytes) + : SimpleBitstreamCursor(BitcodeBytes) {} + explicit BitstreamCursor(StringRef BitcodeBytes) + : SimpleBitstreamCursor(BitcodeBytes) {} + explicit BitstreamCursor(MemoryBufferRef BitcodeBytes) + : SimpleBitstreamCursor(BitcodeBytes) {} using SimpleBitstreamCursor::canSkipToPos; using SimpleBitstreamCursor::AtEndOfStream; + using SimpleBitstreamCursor::getBitcodeBytes; using SimpleBitstreamCursor::GetCurrentBitNo; using SimpleBitstreamCursor::getCurrentByteNo; using SimpleBitstreamCursor::getPointerToByte; - using SimpleBitstreamCursor::getBitStreamReader; using SimpleBitstreamCursor::JumpToBit; using SimpleBitstreamCursor::fillCurWord; using SimpleBitstreamCursor::Read; @@ -549,7 +489,17 @@ //===--------------------------------------------------------------------===// void ReadAbbrevRecord(); - bool ReadBlockInfoBlock(); + /// Read and return a block info block from the bitstream. If an error was + /// encountered, return None. + /// + /// \param ReadBlockInfoNames Whether to read block/record name information in + /// the BlockInfo block. Only llvm-bcanalyzer uses this. + Optional + ReadBlockInfoBlock(bool ReadBlockInfoNames = false); + + /// Set the block info to be used by this BitstreamCursor to interpret + /// abbreviated records. + void setBlockInfo(BitstreamBlockInfo *BI) { BlockInfo = BI; } }; } // end llvm namespace Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -233,10 +233,11 @@ BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {} std::unique_ptr Buffer; - std::unique_ptr StreamFile; + BitstreamBlockInfo BlockInfo; BitstreamCursor Stream; std::error_code initStream(); + bool readBlockInfo(); virtual std::error_code error(const Twine &Message) = 0; virtual ~BitcodeReaderBase() = default; @@ -255,8 +256,8 @@ if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true)) return error("Invalid bitcode wrapper header"); - StreamFile.reset(new BitstreamReader(ArrayRef(BufPtr, BufEnd))); - Stream.init(&*StreamFile); + Stream = BitstreamCursor(ArrayRef(BufPtr, BufEnd)); + Stream.setBlockInfo(&BlockInfo); return std::error_code(); } @@ -2118,8 +2119,7 @@ return error("Invalid record: metadata strings corrupt offset"); StringRef Lengths = Blob.slice(0, StringsOffset); - SimpleBitstreamCursor R(*StreamFile); - R.jumpToPointer(Lengths.begin()); + SimpleBitstreamCursor R(Lengths); StringRef Strings = Blob.drop_front(StringsOffset); do { @@ -3664,6 +3664,14 @@ } } +bool BitcodeReaderBase::readBlockInfo() { + Optional NewBlockInfo = Stream.ReadBlockInfoBlock(); + if (!NewBlockInfo) + return true; + BlockInfo = std::move(*NewBlockInfo); + return false; +} + std::error_code BitcodeReader::parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata) { if (ResumeBit) @@ -3692,7 +3700,7 @@ return error("Invalid record"); break; case bitc::BLOCKINFO_BLOCK_ID: - if (Stream.ReadBlockInfoBlock()) + if (readBlockInfo()) return error("Malformed block"); break; case bitc::PARAMATTR_BLOCK_ID: @@ -6059,7 +6067,7 @@ break; case bitc::BLOCKINFO_BLOCK_ID: // Need to parse these to get abbrev ids (e.g. for VST) - if (Stream.ReadBlockInfoBlock()) + if (readBlockInfo()) return error("Malformed block"); break; case bitc::VALUE_SYMTAB_BLOCK_ID: Index: llvm/lib/Bitcode/Reader/BitstreamReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitstreamReader.cpp +++ llvm/lib/Bitcode/Reader/BitstreamReader.cpp @@ -18,14 +18,6 @@ // BitstreamCursor implementation //===----------------------------------------------------------------------===// -void BitstreamCursor::freeState() { - // Free all the Abbrevs. - CurAbbrevs.clear(); - - // Free all the Abbrevs in the block scope. - BlockScope.clear(); -} - /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter /// the block, and return true if the block has an error. bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { @@ -34,10 +26,12 @@ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); // Add the abbrevs specific to this block to the CurAbbrevs list. - if (const BitstreamReader::BlockInfo *Info = - getBitStreamReader()->getBlockInfo(BlockID)) { - CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(), - Info->Abbrevs.end()); + if (BlockInfo) { + if (const BitstreamBlockInfo::BlockInfo *Info = + BlockInfo->getBlockInfo(BlockID)) { + CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(), + Info->Abbrevs.end()); + } } // Get the codesize of this block. @@ -318,15 +312,14 @@ CurAbbrevs.push_back(Abbv); } -bool BitstreamCursor::ReadBlockInfoBlock() { - // We expect the client to read the block info block at most once. - if (getBitStreamReader()->hasBlockInfoRecords()) - report_fatal_error("Duplicate read of block info block"); +Optional +BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { + if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None; - if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; + BitstreamBlockInfo NewBlockInfo; SmallVector Record; - BitstreamReader::BlockInfo *CurBlockInfo = nullptr; + BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr; // Read all the records for this module. while (true) { @@ -335,9 +328,9 @@ switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: - return true; + return None; case llvm::BitstreamEntry::EndBlock: - return false; + return std::move(NewBlockInfo); case llvm::BitstreamEntry::Record: // The interesting case. break; @@ -345,7 +338,7 @@ // Read abbrev records, associate them with CurBID. if (Entry.ID == bitc::DEFINE_ABBREV) { - if (!CurBlockInfo) return true; + if (!CurBlockInfo) return None; ReadAbbrevRecord(); // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the @@ -360,13 +353,12 @@ switch (readRecord(Entry.ID, Record)) { default: break; // Default behavior, ignore unknown content. case bitc::BLOCKINFO_CODE_SETBID: - if (Record.size() < 1) return true; - CurBlockInfo = - &getBitStreamReader()->getOrCreateBlockInfo((unsigned)Record[0]); + if (Record.size() < 1) return None; + CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]); break; case bitc::BLOCKINFO_CODE_BLOCKNAME: { - if (!CurBlockInfo) return true; - if (getBitStreamReader()->isIgnoringBlockInfoNames()) + if (!CurBlockInfo) return None; + if (!ReadBlockInfoNames) break; // Ignore name. std::string Name; for (unsigned i = 0, e = Record.size(); i != e; ++i) @@ -375,8 +367,8 @@ break; } case bitc::BLOCKINFO_CODE_SETRECORDNAME: { - if (!CurBlockInfo) return true; - if (getBitStreamReader()->isIgnoringBlockInfoNames()) + if (!CurBlockInfo) return None; + if (!ReadBlockInfoNames) break; // Ignore name. std::string Name; for (unsigned i = 1, e = Record.size(); i != e; ++i) Index: llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp =================================================================== --- llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -84,7 +84,7 @@ /// GetBlockName - Return a symbolic block name if known, otherwise return /// null. static const char *GetBlockName(unsigned BlockID, - const BitstreamReader &StreamFile, + const BitstreamBlockInfo &BlockInfo, CurStreamTypeType CurStreamType) { // Standard blocks for all bitcode files. if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { @@ -94,8 +94,8 @@ } // Check to see if we have a blockinfo record for this block, with a name. - if (const BitstreamReader::BlockInfo *Info = - StreamFile.getBlockInfo(BlockID)) { + if (const BitstreamBlockInfo::BlockInfo *Info = + BlockInfo.getBlockInfo(BlockID)) { if (!Info->Name.empty()) return Info->Name.c_str(); } @@ -128,7 +128,7 @@ /// GetCodeName - Return a symbolic code name if known, otherwise return /// null. static const char *GetCodeName(unsigned CodeID, unsigned BlockID, - const BitstreamReader &StreamFile, + const BitstreamBlockInfo &BlockInfo, CurStreamTypeType CurStreamType) { // Standard blocks for all bitcode files. if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { @@ -144,8 +144,8 @@ } // Check to see if we have a blockinfo record for this record, with a name. - if (const BitstreamReader::BlockInfo *Info = - StreamFile.getBlockInfo(BlockID)) { + if (const BitstreamBlockInfo::BlockInfo *Info = + BlockInfo.getBlockInfo(BlockID)) { for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i) if (Info->RecordNames[i].first == CodeID) return Info->RecordNames[i].second.c_str(); @@ -419,7 +419,7 @@ return true; } -static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent, +static bool decodeMetadataStringsBlob(StringRef Indent, ArrayRef Record, StringRef Blob) { if (Blob.empty()) @@ -433,9 +433,7 @@ outs() << " num-strings = " << NumStrings << " {\n"; StringRef Lengths = Blob.slice(0, StringsOffset); - SimpleBitstreamCursor R(Reader); - R.jumpToPointer(Lengths.begin()); - + SimpleBitstreamCursor R(Lengths); StringRef Strings = Blob.drop_front(StringsOffset); do { if (R.AtEndOfStream()) @@ -455,20 +453,20 @@ return false; } -static bool decodeBlob(unsigned Code, unsigned BlockID, BitstreamReader &Reader, - StringRef Indent, ArrayRef Record, - StringRef Blob) { +static bool decodeBlob(unsigned Code, unsigned BlockID, StringRef Indent, + ArrayRef Record, StringRef Blob) { if (BlockID != bitc::METADATA_BLOCK_ID) return true; if (Code != bitc::METADATA_STRINGS) return true; - return decodeMetadataStringsBlob(Reader, Indent, Record, Blob); + return decodeMetadataStringsBlob(Indent, Record, Blob); } /// ParseBlock - Read a block, updating statistics, etc. -static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, - unsigned IndentLevel, CurStreamTypeType CurStreamType) { +static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo, + unsigned BlockID, unsigned IndentLevel, + CurStreamTypeType CurStreamType) { std::string Indent(IndentLevel*2, ' '); uint64_t BlockBitStart = Stream.GetCurrentBitNo(); @@ -481,8 +479,12 @@ bool DumpRecords = Dump; if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { if (Dump) outs() << Indent << "\n"; - if (BitstreamCursor(Stream).ReadBlockInfoBlock()) + Optional NewBlockInfo = + Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); + if (!NewBlockInfo) return ReportError("Malformed BlockInfoBlock"); + BlockInfo = std::move(*NewBlockInfo); + Stream.JumpToBit(BlockBitStart); // It's not really interesting to dump the contents of the blockinfo block. DumpRecords = false; } @@ -497,8 +499,7 @@ const char *BlockName = nullptr; if (DumpRecords) { outs() << Indent << "<"; - if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader(), - CurStreamType))) + if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType))) outs() << BlockName; else outs() << "UnknownBlock" << BlockID; @@ -540,7 +541,8 @@ case BitstreamEntry::SubBlock: { uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); - if (ParseBlock(Stream, Entry.ID, IndentLevel+1, CurStreamType)) + if (ParseBlock(Stream, BlockInfo, Entry.ID, IndentLevel + 1, + CurStreamType)) return true; ++BlockStats.NumSubBlocks; uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); @@ -582,14 +584,11 @@ if (DumpRecords) { outs() << Indent << " <"; if (const char *CodeName = - GetCodeName(Code, BlockID, *Stream.getBitStreamReader(), - CurStreamType)) + GetCodeName(Code, BlockID, BlockInfo, CurStreamType)) outs() << CodeName; else outs() << "UnknownCode" << Code; - if (NonSymbolic && - GetCodeName(Code, BlockID, *Stream.getBitStreamReader(), - CurStreamType)) + if (NonSymbolic && GetCodeName(Code, BlockID, BlockInfo, CurStreamType)) outs() << " codeid=" << Code; const BitCodeAbbrev *Abbv = nullptr; if (Entry.ID != bitc::UNABBREV_RECORD) { @@ -654,8 +653,7 @@ } } - if (Blob.data() && decodeBlob(Code, BlockID, *Stream.getBitStreamReader(), - Indent, Record, Blob)) { + if (Blob.data() && decodeBlob(Code, BlockID, Indent, Record, Blob)) { outs() << " blob data = "; if (ShowBinaryBlobs) { outs() << "'"; @@ -690,7 +688,6 @@ static bool openBitcodeFile(StringRef Path, std::unique_ptr &MemBuf, - BitstreamReader &StreamFile, BitstreamCursor &Stream, CurStreamTypeType &CurStreamType) { // Read the input file. @@ -731,9 +728,7 @@ return ReportError("Invalid bitcode wrapper header"); } - StreamFile = BitstreamReader(ArrayRef(BufPtr, EndBufPtr)); - Stream = BitstreamCursor(StreamFile); - StreamFile.CollectBlockInfoNames(); + Stream = BitstreamCursor(ArrayRef(BufPtr, EndBufPtr)); // Read the stream signature. char Signature[6]; @@ -757,22 +752,21 @@ /// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename. static int AnalyzeBitcode() { std::unique_ptr StreamBuffer; - BitstreamReader StreamFile; BitstreamCursor Stream; + BitstreamBlockInfo BlockInfo; CurStreamTypeType CurStreamType; - if (openBitcodeFile(InputFilename, StreamBuffer, StreamFile, Stream, - CurStreamType)) + if (openBitcodeFile(InputFilename, StreamBuffer, Stream, CurStreamType)) return true; + Stream.setBlockInfo(&BlockInfo); // Read block info from BlockInfoFilename, if specified. // The block info must be a top-level block. if (!BlockInfoFilename.empty()) { std::unique_ptr BlockInfoBuffer; - BitstreamReader BlockInfoFile; BitstreamCursor BlockInfoCursor; CurStreamTypeType BlockInfoStreamType; - if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoFile, - BlockInfoCursor, BlockInfoStreamType)) + if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoCursor, + BlockInfoStreamType)) return true; while (!BlockInfoCursor.AtEndOfStream()) { @@ -782,15 +776,16 @@ unsigned BlockID = BlockInfoCursor.ReadSubBlockID(); if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { - if (BlockInfoCursor.ReadBlockInfoBlock()) + Optional NewBlockInfo = + BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); + if (!NewBlockInfo) return ReportError("Malformed BlockInfoBlock in block info file"); + BlockInfo = std::move(*NewBlockInfo); break; } BlockInfoCursor.SkipBlock(); } - - StreamFile.takeBlockInfo(std::move(BlockInfoFile)); } unsigned NumTopBlocks = 0; @@ -803,14 +798,14 @@ unsigned BlockID = Stream.ReadSubBlockID(); - if (ParseBlock(Stream, BlockID, 0, CurStreamType)) + if (ParseBlock(Stream, BlockInfo, BlockID, 0, CurStreamType)) return true; ++NumTopBlocks; } if (Dump) outs() << "\n\n"; - uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().size() * CHAR_BIT; + uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT; // Print a summary of the read file. outs() << "Summary of " << InputFilename << ":\n"; outs() << " Total size: "; @@ -829,8 +824,8 @@ for (std::map::iterator I = BlockIDStats.begin(), E = BlockIDStats.end(); I != E; ++I) { outs() << " Block ID #" << I->first; - if (const char *BlockName = GetBlockName(I->first, StreamFile, - CurStreamType)) + if (const char *BlockName = + GetBlockName(I->first, BlockInfo, CurStreamType)) outs() << " (" << BlockName << ")"; outs() << ":\n"; @@ -894,9 +889,8 @@ outs() << " "; outs() << " "; - if (const char *CodeName = - GetCodeName(FreqPairs[i].second, I->first, StreamFile, - CurStreamType)) + if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first, + BlockInfo, CurStreamType)) outs() << CodeName << "\n"; else outs() << "UnknownCode" << FreqPairs[i].second << "\n"; Index: llvm/unittests/Bitcode/BitstreamReaderTest.cpp =================================================================== --- llvm/unittests/Bitcode/BitstreamReaderTest.cpp +++ llvm/unittests/Bitcode/BitstreamReaderTest.cpp @@ -20,8 +20,7 @@ uint8_t Bytes[4] = { 0x00, 0x01, 0x02, 0x03 }; - BitstreamReader Reader(Bytes); - BitstreamCursor Cursor(Reader); + BitstreamCursor Cursor(Bytes); EXPECT_FALSE(Cursor.AtEndOfStream()); (void)Cursor.Read(8); @@ -40,24 +39,21 @@ uint8_t Bytes[4] = { 0x00, 0x01, 0x02, 0x03 }; - BitstreamReader Reader(Bytes); - BitstreamCursor Cursor(Reader); + BitstreamCursor Cursor(Bytes); Cursor.JumpToBit(32); EXPECT_TRUE(Cursor.AtEndOfStream()); } TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { - BitstreamReader Reader(ArrayRef{}); - BitstreamCursor Cursor(Reader); + BitstreamCursor Cursor(ArrayRef{}); EXPECT_TRUE(Cursor.AtEndOfStream()); } TEST(BitstreamReaderTest, getCurrentByteNo) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03}; - BitstreamReader Reader(Bytes); - SimpleBitstreamCursor Cursor(Reader); + SimpleBitstreamCursor Cursor(Bytes); for (unsigned I = 0, E = 32; I != E; ++I) { EXPECT_EQ(I / 8, Cursor.getCurrentByteNo()); @@ -68,8 +64,7 @@ TEST(BitstreamReaderTest, getPointerToByte) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - BitstreamReader Reader(Bytes); - SimpleBitstreamCursor Cursor(Reader); + SimpleBitstreamCursor Cursor(Bytes); for (unsigned I = 0, E = 8; I != E; ++I) { EXPECT_EQ(Bytes + I, Cursor.getPointerToByte(I, 1)); @@ -78,25 +73,13 @@ TEST(BitstreamReaderTest, getPointerToBit) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - BitstreamReader Reader(Bytes); - SimpleBitstreamCursor Cursor(Reader); + SimpleBitstreamCursor Cursor(Bytes); for (unsigned I = 0, E = 8; I != E; ++I) { EXPECT_EQ(Bytes + I, Cursor.getPointerToBit(I * 8, 1)); } } -TEST(BitstreamReaderTest, jumpToPointer) { - uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - BitstreamReader Reader(Bytes); - SimpleBitstreamCursor Cursor(Reader); - - for (unsigned I : {0, 6, 2, 7}) { - Cursor.jumpToPointer(Bytes + I); - EXPECT_EQ(I, Cursor.getCurrentByteNo()); - } -} - TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) { SmallVector BlobData; for (unsigned I = 0, E = 1024; I != E; ++I) @@ -129,9 +112,8 @@ } // Stream the buffer into the reader. - BitstreamReader R( + BitstreamCursor Stream( ArrayRef((const uint8_t *)Buffer.begin(), Buffer.size())); - BitstreamCursor Stream(R); // Header. Included in test so that we can run llvm-bcanalyzer to debug // when there are problems. @@ -161,8 +143,7 @@ TEST(BitstreamReaderTest, shortRead) { uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1}; for (unsigned I = 1; I != 8; ++I) { - BitstreamReader Reader(ArrayRef(Bytes, I)); - SimpleBitstreamCursor Cursor(Reader); + SimpleBitstreamCursor Cursor(ArrayRef(Bytes, I)); EXPECT_EQ(8ull, Cursor.Read(8)); } }