+public:
+ /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
+ /// These describe abbreviations that all blocks of the specified ID inherit.
+ struct BlockInfo {
+ unsigned BlockID;
+ std::vector<BitCodeAbbrev*> Abbrevs;
+ std::string Name;
+
+ std::vector<std::pair<unsigned, std::string> > RecordNames;
+ };
+private:
+ /// FirstChar/LastChar - This remembers the first and last bytes of the
+ /// stream.
+ const unsigned char *FirstChar, *LastChar;
+
+ std::vector<BlockInfo> BlockInfoRecords;
+
+ /// IgnoreBlockInfoNames - 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;
+
+ BitstreamReader(const BitstreamReader&); // NOT IMPLEMENTED
+ void operator=(const BitstreamReader&); // NOT IMPLEMENTED
+public:
+ BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) {
+ }
+
+ BitstreamReader(const unsigned char *Start, const unsigned char *End) {
+ IgnoreBlockInfoNames = true;
+ init(Start, End);
+ }
+
+ void init(const unsigned char *Start, const unsigned char *End) {
+ FirstChar = Start;
+ LastChar = End;
+ assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
+ }
+
+ ~BitstreamReader() {
+ // Free the BlockInfoRecords.
+ while (!BlockInfoRecords.empty()) {
+ BlockInfo &Info = BlockInfoRecords.back();
+ // Free blockinfo abbrev info.
+ for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
+ i != e; ++i)
+ Info.Abbrevs[i]->dropRef();
+ BlockInfoRecords.pop_back();
+ }
+ }
+
+ const unsigned char *getFirstChar() const { return FirstChar; }
+ const unsigned char *getLastChar() const { return LastChar; }
+
+ /// CollectBlockInfoNames - This is called by clients that want block/record
+ /// name information.
+ void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
+ bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
+
+ //===--------------------------------------------------------------------===//
+ // Block Manipulation
+ //===--------------------------------------------------------------------===//
+
+ /// hasBlockInfoRecords - 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(); }
+
+ /// getBlockInfo - 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 0;
+ }
+
+ BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
+ if (const BlockInfo *BI = getBlockInfo(BlockID))
+ return *const_cast<BlockInfo*>(BI);
+
+ // Otherwise, add a new record.
+ BlockInfoRecords.push_back(BlockInfo());
+ BlockInfoRecords.back().BlockID = BlockID;
+ return BlockInfoRecords.back();
+ }
+
+};
+
+class BitstreamCursor {
+ friend class Deserializer;
+ BitstreamReader *BitStream;