[llvm-commits] [llvm] r43973 - in /llvm/trunk: include/llvm/Bitcode/Deserialize.h lib/Bitcode/Reader/Deserialize.cpp

Ted Kremenek kremenek at apple.com
Fri Nov 9 18:02:36 PST 2007


Author: kremenek
Date: Fri Nov  9 20:02:34 2007
New Revision: 43973

URL: http://llvm.org/viewvc/llvm-project?rev=43973&view=rev
Log:
Added "random access" to the Deserializer to allow a client to jump to any
serialized block in the bitstream, including a block in an entirely different
nesting than the current block. This is useful for deserializing objects from
a bitstream in an order different from the order that they were serialized.

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

Modified: llvm/trunk/include/llvm/Bitcode/Deserialize.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/Deserialize.h?rev=43973&r1=43972&r2=43973&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Bitcode/Deserialize.h (original)
+++ llvm/trunk/include/llvm/Bitcode/Deserialize.h Fri Nov  9 20:02:34 2007
@@ -80,7 +80,36 @@
   //===----------------------------------------------------------===//
   
 public:  
-  typedef uint64_t Location;
+  struct Location {
+    uint64_t BitNo;
+    unsigned BlockID;
+    unsigned NumWords;
+    
+    Location(uint64_t bit, unsigned bid, unsigned words) 
+    : BitNo(bit), BlockID(bid), NumWords(words) {}
+    
+    Location() : BitNo(0), BlockID(0), NumWords(0) {}
+
+    Location& operator=(Location& RHS) {
+      BitNo = RHS.BitNo;
+      BlockID = RHS.BlockID;
+      NumWords = RHS.NumWords;
+      return *this;
+    }
+    
+    bool operator==(const Location& RHS) const { return BitNo == RHS.BitNo; }    
+    bool operator!=(const Location& RHS) const { return BitNo != RHS.BitNo; }
+    
+    bool contains(const Location& RHS) const {
+      if (RHS.BitNo < BitNo)
+        return false;
+
+      if ((RHS.BitNo - BitNo) >> 5 < NumWords)
+        return true;
+      
+      return false;
+    }
+  };
   
   //===----------------------------------------------------------===//
   // Internal data members.
@@ -93,9 +122,10 @@
   BumpPtrAllocator Allocator;
   BPNode* FreeList;
   MapTy BPatchMap;
-  llvm::SmallVector<std::pair<Location,unsigned>,5> BlockStack;
+  llvm::SmallVector<Location,8> BlockStack;
   unsigned AbbrevNo;
   unsigned RecordCode;
+  Location StreamStart;
   
   //===----------------------------------------------------------===//
   // Public Interface.
@@ -238,13 +268,18 @@
   unsigned getAbbrevNo();
   
   bool FinishedBlock(Location BlockLoc);
+  bool JumpTo(const Location& BlockLoc);
+  void Rewind() { JumpTo(StreamStart); }
   
   bool AtEnd();
   bool inRecord();
   void SkipBlock();
+  bool SkipToBlock(unsigned BlockID);
   
   unsigned getRecordCode();
   
+  BitstreamReader& getStream() { return Stream; }
+  
 private:
   bool AdvanceStream();  
   void ReadRecord();

Modified: llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp?rev=43973&r1=43972&r2=43973&view=diff

==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp Fri Nov  9 20:02:34 2007
@@ -21,6 +21,9 @@
 
 Deserializer::Deserializer(BitstreamReader& stream)
   : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
+    
+  AdvanceStream();
+  if (!AtEnd()) StreamStart = BlockStack.back();
 }
 
 Deserializer::~Deserializer() {
@@ -60,12 +63,24 @@
   
   while (!Stream.AtEndOfStream()) {
     
+    uint64_t Pos = Stream.GetCurrentBitNo();
     AbbrevNo = Stream.ReadCode();    
   
     switch (AbbrevNo) {        
       case bitc::ENTER_SUBBLOCK: {
         unsigned id = Stream.ReadSubBlockID();
-        BlockStack.push_back(std::make_pair(Stream.GetCurrentBitNo(),id));
+        
+        // Determine the extent of the block.  This is useful for jumping around
+        // the stream.  This is hack: we read the header of the block, save
+        // the length, and then revert the bitstream to a location just before
+        // the block is entered.
+        uint64_t BPos = Stream.GetCurrentBitNo();
+        Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
+        Stream.SkipToWord();
+        unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
+        Stream.JumpToBit(BPos);
+                
+        BlockStack.push_back(Location(Pos,id,NumWords));
         break;
       } 
         
@@ -91,10 +106,10 @@
 }
 
 void Deserializer::ReadRecord() {
-  
+
   while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
     assert (!BlockStack.empty());
-    Stream.EnterSubBlock(BlockStack.back().second);
+    Stream.EnterSubBlock(BlockStack.back().BlockID);
     AbbrevNo = 0;
   }
 
@@ -109,23 +124,116 @@
 
 void Deserializer::SkipBlock() {
   assert (!inRecord());
-  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);  
+
+  if (AtEnd())
+    return;
+
+  AdvanceStream();  
+
+  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
+  BlockStack.pop_back();
   Stream.SkipBlock();
+
   AbbrevNo = 0;
+  AdvanceStream();
+}
+
+bool Deserializer::SkipToBlock(unsigned BlockID) {
+  assert (!inRecord());
+  
+  AdvanceStream();
+  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
+  
+  unsigned BlockLevel = BlockStack.size();
+
+  while (!AtEnd() &&
+         BlockLevel == BlockStack.size() && 
+         getCurrentBlockID() != BlockID)
+    SkipBlock();
+
+  return !(AtEnd() || BlockLevel != BlockStack.size());
 }
 
 Deserializer::Location Deserializer::getCurrentBlockLocation() {
   if (!inRecord())
     AdvanceStream();
   
-  return BlockStack.back().first;
+  return BlockStack.back();
+}
+
+bool Deserializer::JumpTo(const Location& Loc) {
+    
+  assert (!inRecord());
+
+//  AdvanceStream();
+  
+//  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
+  assert (!BlockStack.empty());
+    
+  uint64_t LastBPos = StreamStart.BitNo;
+  
+  while (!BlockStack.empty()) {
+    
+    LastBPos = BlockStack.back().BitNo;
+    
+    // Determine of the current block contains the location of the block
+    // we are looking for.
+    if (BlockStack.back().contains(Loc)) {
+      // We found the enclosing block.  We must first POP it off to
+      // destroy any accumulated context within the block scope.  We then
+      // jump to the position of the block and enter it.
+      Stream.JumpToBit(LastBPos);
+      BlockStack.pop_back();
+      Stream.PopBlockScope();
+      
+      AbbrevNo = 0;
+      AdvanceStream();      
+      assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
+      
+      Stream.EnterSubBlock(BlockStack.back().BlockID);
+      break;
+    }
+
+    // This block does not contain the block we are looking for.  Pop it.
+    BlockStack.pop_back();
+    Stream.PopBlockScope();
+  }
+
+  // Check if we have popped our way to the outermost scope.  If so,
+  // we need to adjust our position.
+  if (BlockStack.empty()) {
+    Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart.BitNo : LastBPos);
+    AbbrevNo = 0;
+    AdvanceStream();
+  }
+
+  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
+  assert (!BlockStack.empty());
+  
+  while (!AtEnd() && BlockStack.back() != Loc) {
+    if (BlockStack.back().contains(Loc)) {
+      Stream.EnterSubBlock(BlockStack.back().BlockID);
+      AbbrevNo = 0;
+      AdvanceStream();
+      continue;
+    }
+    else
+      SkipBlock();
+  }
+  
+  if (AtEnd())
+    return false;
+  
+  assert (BlockStack.back() == Loc);
+
+  return true;
 }
 
 unsigned Deserializer::getCurrentBlockID() { 
   if (!inRecord())
     AdvanceStream();
   
-  return BlockStack.back().second;
+  return BlockStack.back().BlockID;
 }
 
 unsigned Deserializer::getRecordCode() {
@@ -142,9 +250,9 @@
   if (!inRecord())
     AdvanceStream();
 
-  for (llvm::SmallVector<std::pair<Location,unsigned>,5>::reverse_iterator
+  for (llvm::SmallVector<Location,8>::reverse_iterator
         I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
-      if (I->first == BlockLoc)
+      if (*I == BlockLoc)
         return false;
   
   return true;





More information about the llvm-commits mailing list