+ /// 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 {
+ // Common case, the most recent entry matches BlockID.
+ if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
+ return &BlockInfoRecords.back();
+
+ for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
+ i != e; ++i)
+ if (BlockInfoRecords[i].BlockID == BlockID)
+ return &BlockInfoRecords[i];
+ return nullptr;
+ }
+
+ BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
+ if (const BlockInfo *BI = getBlockInfo(BlockID))
+ return *const_cast<BlockInfo*>(BI);
+
+ // Otherwise, add a new record.
+ BlockInfoRecords.emplace_back();
+ 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);
+ }
+};
+
+/// When advancing through a bitstream cursor, each advance can discover a few
+/// different kinds of entries:
+struct BitstreamEntry {
+ enum {
+ Error, // Malformed bitcode was found.
+ EndBlock, // We've reached the end of the current block, (or the end of the
+ // file, which is treated like a series of EndBlock records.
+ SubBlock, // This is the start of a new subblock of a specific ID.
+ Record // This is a record with a specific AbbrevID.
+ } Kind;
+
+ unsigned ID;
+
+ static BitstreamEntry getError() {
+ BitstreamEntry E; E.Kind = Error; return E;
+ }
+ static BitstreamEntry getEndBlock() {
+ BitstreamEntry E; E.Kind = EndBlock; return E;
+ }
+ static BitstreamEntry getSubBlock(unsigned ID) {
+ BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
+ }
+ static BitstreamEntry getRecord(unsigned AbbrevID) {
+ BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
+ }
+};
+
+/// This represents a position within a bitcode file. There may be multiple
+/// independent cursors reading within one bitstream, each maintaining their own
+/// local state.
+///
+/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
+/// be passed by value.
+class BitstreamCursor {
+ BitstreamReader *BitStream;
+ size_t NextChar;
+
+ // The size of the bicode. 0 if we don't know it yet.
+ size_t Size;
+
+ /// This is the current data we have pulled from the stream but have not
+ /// returned to the client. This is specifically and intentionally defined to
+ /// follow the word size of the host machine for efficiency. We use word_t in
+ /// places that are aware of this to make it perfectly explicit what is going
+ /// on.
+ typedef size_t word_t;
+ word_t CurWord;
+
+ /// This is the number of bits in CurWord that are valid. This is always from
+ /// [0...bits_of(size_t)-1] inclusive.