[llvm] r264545 - Bitcode: Split out SimpleBitstreamCursor

Duncan P. N. Exon Smith via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 27 15:40:55 PDT 2016


Author: dexonsmith
Date: Sun Mar 27 17:40:55 2016
New Revision: 264545

URL: http://llvm.org/viewvc/llvm-project?rev=264545&view=rev
Log:
Bitcode: Split out SimpleBitstreamCursor

Split out SimpleBitstreamCursor from BitstreamCursor, which is a
lower-level cursor with no knowledge of bitcode blocks, abbreviations,
or records.  It just knows how to read bits and navigate the stream.

This is mainly organizational, to separate the API for manipulating raw
bits from that for bitcode concepts like Record and Block.

Modified:
    llvm/trunk/include/llvm/Bitcode/BitstreamReader.h
    llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp

Modified: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamReader.h?rev=264545&r1=264544&r2=264545&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitstreamReader.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitstreamReader.h Sun Mar 27 17:40:55 2016
@@ -128,98 +128,42 @@ public:
   }
 };
 
-/// 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;
+/// 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;
+  size_t NextChar = 0;
 
   // The size of the bicode. 0 if we don't know it yet.
-  size_t Size;
+  size_t Size = 0;
 
   /// 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.
+public:
   typedef size_t word_t;
-  word_t CurWord;
+
+private:
+  word_t CurWord = 0;
 
   /// This is the number of bits in CurWord that are valid. This is always from
   /// [0...bits_of(size_t)-1] inclusive.
-  unsigned BitsInCurWord;
-
-  // This is the declared size of code values used for the current block, in
-  // bits.
-  unsigned CurCodeSize;
-
-  /// Abbrevs installed at in this block.
-  std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
-
-  struct Block {
-    unsigned PrevCodeSize;
-    std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
-    explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
-  };
-
-  /// This tracks the codesize of parent blocks.
-  SmallVector<Block, 8> BlockScope;
-
+  unsigned BitsInCurWord = 0;
 
 public:
   static const size_t MaxChunkSize = sizeof(word_t) * 8;
 
-  BitstreamCursor() { init(nullptr); }
-
-  explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
-
-  void init(BitstreamReader *R) {
-    freeState();
+  SimpleBitstreamCursor() = default;
 
-    BitStream = R;
-    NextChar = 0;
-    Size = 0;
-    BitsInCurWord = 0;
-    CurCodeSize = 2;
-  }
-
-  void freeState();
+  explicit SimpleBitstreamCursor(BitstreamReader *R) : R(R) {}
 
   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 == 0 || BitStream->getBitcodeBytes().isValidAddress(
-        static_cast<uint64_t>(pos - 1));
+    return pos == 0 ||
+           R->getBitcodeBytes().isValidAddress(static_cast<uint64_t>(pos - 1));
   }
 
   bool AtEndOfStream() {
@@ -231,72 +175,13 @@ public:
     return BitsInCurWord == 0;
   }
 
-  /// Return the number of bits used to encode an abbrev #.
-  unsigned getAbbrevIDWidth() const { return CurCodeSize; }
-
   /// Return the bit # of the bit we are reading.
   uint64_t GetCurrentBitNo() const {
     return NextChar*CHAR_BIT - BitsInCurWord;
   }
 
-  BitstreamReader *getBitStreamReader() {
-    return BitStream;
-  }
-  const BitstreamReader *getBitStreamReader() const {
-    return BitStream;
-  }
-
-  /// Flags that modify the behavior of advance().
-  enum {
-    /// If this flag is used, the advance() method does not automatically pop
-    /// the block scope when the end of a block is reached.
-    AF_DontPopBlockAtEnd = 1,
-
-    /// If this flag is used, abbrev entries are returned just like normal
-    /// records.
-    AF_DontAutoprocessAbbrevs = 2
-  };
-
-  /// Advance the current bitstream, returning the next entry in the stream.
-  BitstreamEntry advance(unsigned Flags = 0) {
-    while (1) {
-      unsigned Code = ReadCode();
-      if (Code == bitc::END_BLOCK) {
-        // Pop the end of the block unless Flags tells us not to.
-        if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
-          return BitstreamEntry::getError();
-        return BitstreamEntry::getEndBlock();
-      }
-
-      if (Code == bitc::ENTER_SUBBLOCK)
-        return BitstreamEntry::getSubBlock(ReadSubBlockID());
-
-      if (Code == bitc::DEFINE_ABBREV &&
-          !(Flags & AF_DontAutoprocessAbbrevs)) {
-        // We read and accumulate abbrev's, the client can't do anything with
-        // them anyway.
-        ReadAbbrevRecord();
-        continue;
-      }
-
-      return BitstreamEntry::getRecord(Code);
-    }
-  }
-
-  /// This is a convenience function for clients that don't expect any
-  /// subblocks. This just skips over them automatically.
-  BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
-    while (1) {
-      // If we found a normal entry, return it.
-      BitstreamEntry Entry = advance(Flags);
-      if (Entry.Kind != BitstreamEntry::SubBlock)
-        return Entry;
-
-      // If we found a sub-block, just skip over it and check the next entry.
-      if (SkipBlock())
-        return BitstreamEntry::getError();
-    }
-  }
+  BitstreamReader *getBitStreamReader() { return R; }
+  const BitstreamReader *getBitStreamReader() const { return R; }
 
   /// Reset the stream to the specified bit number.
   void JumpToBit(uint64_t BitNo) {
@@ -321,7 +206,7 @@ public:
     uint8_t Array[sizeof(word_t)] = {0};
 
     uint64_t BytesRead =
-        BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
+        R->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
 
     // If we run out of data, stop at the end of the stream.
     if (BytesRead == 0) {
@@ -416,7 +301,6 @@ public:
     }
   }
 
-private:
   void SkipToFourByteBoundary() {
     // If word_t is 64-bits and if we've read less than 32 bits, just dump
     // the bits we have up to the next 32-bit boundary.
@@ -429,7 +313,140 @@ private:
 
     BitsInCurWord = 0;
   }
+
+  /// Skip to the end of the file.
+  void skipToEnd() { NextChar = R->getBitcodeBytes().getExtent(); }
+};
+
+/// 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, implemented on top of a
+/// SimpleBitstreamCursor.
+///
+/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
+/// be passed by value.
+class BitstreamCursor : SimpleBitstreamCursor {
+  // This is the declared size of code values used for the current block, in
+  // bits.
+  unsigned CurCodeSize = 2;
+
+  /// Abbrevs installed at in this block.
+  std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
+
+  struct Block {
+    unsigned PrevCodeSize;
+    std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
+    explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
+  };
+
+  /// This tracks the codesize of parent blocks.
+  SmallVector<Block, 8> BlockScope;
+
+
 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();
+
+  using SimpleBitstreamCursor::canSkipToPos;
+  using SimpleBitstreamCursor::AtEndOfStream;
+  using SimpleBitstreamCursor::GetCurrentBitNo;
+  using SimpleBitstreamCursor::getBitStreamReader;
+  using SimpleBitstreamCursor::JumpToBit;
+  using SimpleBitstreamCursor::fillCurWord;
+  using SimpleBitstreamCursor::Read;
+  using SimpleBitstreamCursor::ReadVBR;
+  using SimpleBitstreamCursor::ReadVBR64;
+
+  /// Return the number of bits used to encode an abbrev #.
+  unsigned getAbbrevIDWidth() const { return CurCodeSize; }
+
+  /// Flags that modify the behavior of advance().
+  enum {
+    /// If this flag is used, the advance() method does not automatically pop
+    /// the block scope when the end of a block is reached.
+    AF_DontPopBlockAtEnd = 1,
+
+    /// If this flag is used, abbrev entries are returned just like normal
+    /// records.
+    AF_DontAutoprocessAbbrevs = 2
+  };
+
+  /// Advance the current bitstream, returning the next entry in the stream.
+  BitstreamEntry advance(unsigned Flags = 0) {
+    while (1) {
+      unsigned Code = ReadCode();
+      if (Code == bitc::END_BLOCK) {
+        // Pop the end of the block unless Flags tells us not to.
+        if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
+          return BitstreamEntry::getError();
+        return BitstreamEntry::getEndBlock();
+      }
+
+      if (Code == bitc::ENTER_SUBBLOCK)
+        return BitstreamEntry::getSubBlock(ReadSubBlockID());
+
+      if (Code == bitc::DEFINE_ABBREV &&
+          !(Flags & AF_DontAutoprocessAbbrevs)) {
+        // We read and accumulate abbrev's, the client can't do anything with
+        // them anyway.
+        ReadAbbrevRecord();
+        continue;
+      }
+
+      return BitstreamEntry::getRecord(Code);
+    }
+  }
+
+  /// This is a convenience function for clients that don't expect any
+  /// subblocks. This just skips over them automatically.
+  BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
+    while (1) {
+      // If we found a normal entry, return it.
+      BitstreamEntry Entry = advance(Flags);
+      if (Entry.Kind != BitstreamEntry::SubBlock)
+        return Entry;
+
+      // If we found a sub-block, just skip over it and check the next entry.
+      if (SkipBlock())
+        return BitstreamEntry::getError();
+    }
+  }
 
   unsigned ReadCode() {
     return Read(CurCodeSize);

Modified: llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp?rev=264545&r1=264544&r2=264545&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp Sun Mar 27 17:40:55 2016
@@ -32,7 +32,7 @@ bool BitstreamCursor::EnterSubBlock(unsi
 
   // Add the abbrevs specific to this block to the CurAbbrevs list.
   if (const BitstreamReader::BlockInfo *Info =
-      BitStream->getBlockInfo(BlockID)) {
+          getBitStreamReader()->getBlockInfo(BlockID)) {
     CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
                       Info->Abbrevs.end());
   }
@@ -164,7 +164,7 @@ void BitstreamCursor::skipRecord(unsigne
     // If this would read off the end of the bitcode file, just set the
     // record to empty and return.
     if (!canSkipToPos(NewEnd/8)) {
-      NextChar = BitStream->getBitcodeBytes().getExtent();
+      skipToEnd();
       break;
     }
 
@@ -256,13 +256,14 @@ unsigned BitstreamCursor::readRecord(uns
     // record to empty and return.
     if (!canSkipToPos(NewEnd/8)) {
       Vals.append(NumElts, 0);
-      NextChar = BitStream->getBitcodeBytes().getExtent();
+      skipToEnd();
       break;
     }
 
     // Otherwise, inform the streamer that we need these bytes in memory.
-    const char *Ptr = (const char*)
-      BitStream->getBitcodeBytes().getPointer(CurBitPos/8, NumElts);
+    const char *Ptr =
+        (const char *)getBitStreamReader()->getBitcodeBytes().getPointer(
+            CurBitPos / 8, NumElts);
 
     // If we can return a reference to the data, do so to avoid copying it.
     if (Blob) {
@@ -320,7 +321,7 @@ void BitstreamCursor::ReadAbbrevRecord()
 
 bool BitstreamCursor::ReadBlockInfoBlock() {
   // If this is the second stream to get to the block info block, skip it.
-  if (BitStream->hasBlockInfoRecords())
+  if (getBitStreamReader()->hasBlockInfoRecords())
     return SkipBlock();
 
   if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true;
@@ -361,11 +362,13 @@ bool BitstreamCursor::ReadBlockInfoBlock
       default: break;  // Default behavior, ignore unknown content.
       case bitc::BLOCKINFO_CODE_SETBID:
         if (Record.size() < 1) return true;
-        CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]);
+        CurBlockInfo =
+            &getBitStreamReader()->getOrCreateBlockInfo((unsigned)Record[0]);
         break;
       case bitc::BLOCKINFO_CODE_BLOCKNAME: {
         if (!CurBlockInfo) return true;
-        if (BitStream->isIgnoringBlockInfoNames()) break;  // Ignore name.
+        if (getBitStreamReader()->isIgnoringBlockInfoNames())
+          break; // Ignore name.
         std::string Name;
         for (unsigned i = 0, e = Record.size(); i != e; ++i)
           Name += (char)Record[i];
@@ -374,7 +377,8 @@ bool BitstreamCursor::ReadBlockInfoBlock
       }
       case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
         if (!CurBlockInfo) return true;
-        if (BitStream->isIgnoringBlockInfoNames()) break;  // Ignore name.
+        if (getBitStreamReader()->isIgnoringBlockInfoNames())
+          break; // Ignore name.
         std::string Name;
         for (unsigned i = 1, e = Record.size(); i != e; ++i)
           Name += (char)Record[i];




More information about the llvm-commits mailing list