Index: llvm/include/llvm/Bitcode/BitCodes.h =================================================================== --- llvm/include/llvm/Bitcode/BitCodes.h +++ llvm/include/llvm/Bitcode/BitCodes.h @@ -73,8 +73,9 @@ BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name] - BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME: + BLOCKINFO_CODE_SETRECORDNAME = 3, // BLOCKINFO_CODE_SETRECORDNAME: // [id, name] + BLOCKINFO_CODE_DEPENDENCY = 4, // DEPENDENCY: [bitno] }; } // End bitc namespace Index: llvm/include/llvm/Bitcode/BitstreamReader.h =================================================================== --- llvm/include/llvm/Bitcode/BitstreamReader.h +++ llvm/include/llvm/Bitcode/BitstreamReader.h @@ -58,6 +58,11 @@ /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. bool IgnoreBlockInfoNames; + /// Tracks the bit number of the most recently read block info block. This is + /// used to interpret the BLOCKINFO_CODE_DEPENDENCY record which helps ensure + /// that block info blocks are read in dependency order. + uint64_t BlockInfoDependency = 0; + public: BitstreamReader() : IgnoreBlockInfoNames(true) { } @@ -114,6 +119,9 @@ return BlockInfoRecords.back(); } + uint64_t getBlockInfoDependency() const { return BlockInfoDependency; } + void setBlockInfoDependency(uint64_t B) { BlockInfoDependency = B; } + /// Takes block info from the other bitstream reader. /// /// This is a "take" operation because BlockInfo records are non-trivial, and Index: llvm/include/llvm/Bitcode/BitstreamWriter.h =================================================================== --- llvm/include/llvm/Bitcode/BitstreamWriter.h +++ llvm/include/llvm/Bitcode/BitstreamWriter.h @@ -42,6 +42,11 @@ /// selected BLOCK ID. unsigned BlockInfoCurBID; + /// Tracks the bit number of the most recently written block info block. This + /// is used to write the BLOCKINFO_CODE_DEPENDENCY record which helps ensure + /// that block info blocks are read in dependency order. + uint64_t BlockInfoDependency = 0; + /// CurAbbrevs - Abbrevs installed at in this block. std::vector> CurAbbrevs; @@ -509,8 +514,14 @@ /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. void EnterBlockInfoBlock(unsigned CodeWidth) { + uint64_t LastBlockInfoDependency = BlockInfoDependency; + BlockInfoDependency = GetCurrentBitNo(); + EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth); BlockInfoCurBID = ~0U; + if (LastBlockInfoDependency) + EmitRecord(bitc::BLOCKINFO_CODE_DEPENDENCY, + ArrayRef{LastBlockInfoDependency}); } private: /// SwitchToBlockID - If we aren't already talking about the specified block Index: llvm/lib/Bitcode/Reader/BitstreamReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitstreamReader.cpp +++ llvm/lib/Bitcode/Reader/BitstreamReader.cpp @@ -319,13 +319,12 @@ } 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"); + uint64_t BlockInfoDependency = GetCurrentBitNo(); if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; SmallVector Record; + uint64_t LastBlockInfoDependency = 0; BitstreamReader::BlockInfo *CurBlockInfo = nullptr; // Read all the records for this module. @@ -337,6 +336,12 @@ case llvm::BitstreamEntry::Error: return true; case llvm::BitstreamEntry::EndBlock: + // We expect the client to read block info blocks in dependency order. + if (getBitStreamReader()->getBlockInfoDependency() != + LastBlockInfoDependency) + report_fatal_error( + "Duplicate or out of order read of block info block"); + getBitStreamReader()->setBlockInfoDependency(BlockInfoDependency); return false; case llvm::BitstreamEntry::Record: // The interesting case. @@ -359,6 +364,9 @@ Record.clear(); switch (readRecord(Entry.ID, Record)) { default: break; // Default behavior, ignore unknown content. + case bitc::BLOCKINFO_CODE_DEPENDENCY: + LastBlockInfoDependency = Record[0]; + break; case bitc::BLOCKINFO_CODE_SETBID: if (Record.size() < 1) return true; CurBlockInfo =