From 8fc9b4d314c49fa3e20f1f91d09d6160502a8e1e Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 8 Nov 2016 04:17:11 +0000 Subject: [PATCH] Bitcode: Decouple block info block state from reader. As proposed on llvm-dev: http://lists.llvm.org/pipermail/llvm-dev/2016-October/106630.html Move block info block state to a new class, BitstreamBlockInfo. Clients may set the block info for a particular cursor with the BitstreamCursor::setBlockInfo() method. At this point BitstreamReader is not much more than a container for an ArrayRef, so remove it and replace all uses with direct uses of memory buffers. Differential Revision: https://reviews.llvm.org/D26259 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286207 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 128 +++++++--------------- lib/Bitcode/Reader/BitcodeReader.cpp | 16 +-- lib/Bitcode/Reader/BitstreamReader.cpp | 48 ++++---- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 88 +++++++-------- unittests/Bitcode/BitstreamReaderTest.cpp | 35 ++---- 5 files changed, 117 insertions(+), 198 deletions(-) diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index b258e806e67..4d95a6ce8a1 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/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 @@ public: }; 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 @@ public: 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 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: } 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 @@ public: } /// 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 @@ class BitstreamCursor : SimpleBitstreamCursor { /// 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 @@ public: //===--------------------------------------------------------------------===// 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 diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 658e6d227e5..a5f040bfa36 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -233,7 +233,7 @@ protected: BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {} std::unique_ptr Buffer; - std::unique_ptr StreamFile; + BitstreamBlockInfo BlockInfo; BitstreamCursor Stream; std::error_code initStream(); @@ -256,8 +256,8 @@ std::error_code BitcodeReaderBase::initStream() { 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(); } @@ -2211,8 +2211,7 @@ std::error_code BitcodeReader::parseMetadataStrings(ArrayRef Record, 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 { @@ -3759,9 +3758,12 @@ std::error_code BitcodeReader::parseBitcodeVersion() { } } - bool BitcodeReaderBase::readBlockInfo() { - return Stream.ReadBlockInfoBlock(); + Optional NewBlockInfo = Stream.ReadBlockInfoBlock(); + if (!NewBlockInfo) + return true; + BlockInfo = std::move(*NewBlockInfo); + return false; } std::error_code BitcodeReader::parseModule(uint64_t ResumeBit, diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 0b549f7550f..f1237069f7b 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -18,14 +18,6 @@ using namespace llvm; // 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 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { 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 @@ void BitstreamCursor::ReadAbbrevRecord() { 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 @@ bool BitstreamCursor::ReadBlockInfoBlock() { 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 @@ bool BitstreamCursor::ReadBlockInfoBlock() { // 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 @@ bool BitstreamCursor::ReadBlockInfoBlock() { 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 @@ bool BitstreamCursor::ReadBlockInfoBlock() { 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) diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index fec11e35d50..e4ca893cc2b 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -84,7 +84,7 @@ enum CurStreamTypeType { /// 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 @@ static const char *GetBlockName(unsigned BlockID, } // 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 @@ static const char *GetBlockName(unsigned BlockID, /// 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 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, } // 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 @@ static bool ReportError(const Twine &Err) { 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 @@ static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent, 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 @@ static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent, 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 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, 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 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, 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 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, 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 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, 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 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, } } - 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 void PrintSize(uint64_t Bits) { static bool openBitcodeFile(StringRef Path, std::unique_ptr &MemBuf, - BitstreamReader &StreamFile, BitstreamCursor &Stream, CurStreamTypeType &CurStreamType) { // Read the input file. @@ -731,9 +728,7 @@ static bool openBitcodeFile(StringRef Path, 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 @@ static bool openBitcodeFile(StringRef Path, /// 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 @@ static int AnalyzeBitcode() { 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 @@ static int AnalyzeBitcode() { 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 @@ static int AnalyzeBitcode() { 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 @@ static int AnalyzeBitcode() { 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"; diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp index 986023ee3e9..704eb803f9c 100644 --- a/unittests/Bitcode/BitstreamReaderTest.cpp +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -20,8 +20,7 @@ TEST(BitstreamReaderTest, AtEndOfStream) { 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 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) { 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, getCurrentByteNo) { 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, getPointerToByte) { 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 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) { } // 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, readRecordWithBlobWhileStreaming) { 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)); } } -- 2.40.0