llvm.org GIT mirror llvm / 1a8a08a
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43973 91177308-0d34-0410-b5e6-96231b3b80d8 Ted Kremenek 12 years ago
2 changed file(s) with 153 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
7979 //===----------------------------------------------------------===//
8080
8181 public:
82 typedef uint64_t Location;
82 struct Location {
83 uint64_t BitNo;
84 unsigned BlockID;
85 unsigned NumWords;
86
87 Location(uint64_t bit, unsigned bid, unsigned words)
88 : BitNo(bit), BlockID(bid), NumWords(words) {}
89
90 Location() : BitNo(0), BlockID(0), NumWords(0) {}
91
92 Location& operator=(Location& RHS) {
93 BitNo = RHS.BitNo;
94 BlockID = RHS.BlockID;
95 NumWords = RHS.NumWords;
96 return *this;
97 }
98
99 bool operator==(const Location& RHS) const { return BitNo == RHS.BitNo; }
100 bool operator!=(const Location& RHS) const { return BitNo != RHS.BitNo; }
101
102 bool contains(const Location& RHS) const {
103 if (RHS.BitNo < BitNo)
104 return false;
105
106 if ((RHS.BitNo - BitNo) >> 5 < NumWords)
107 return true;
108
109 return false;
110 }
111 };
83112
84113 //===----------------------------------------------------------===//
85114 // Internal data members.
92121 BumpPtrAllocator Allocator;
93122 BPNode* FreeList;
94123 MapTy BPatchMap;
95 llvm::SmallVector<std::pair,5> BlockStack;
124 llvm::SmallVector<Location,8> BlockStack;
96125 unsigned AbbrevNo;
97126 unsigned RecordCode;
127 Location StreamStart;
98128
99129 //===----------------------------------------------------------===//
100130 // Public Interface.
237267 unsigned getAbbrevNo();
238268
239269 bool FinishedBlock(Location BlockLoc);
270 bool JumpTo(const Location& BlockLoc);
271 void Rewind() { JumpTo(StreamStart); }
240272
241273 bool AtEnd();
242274 bool inRecord();
243275 void SkipBlock();
276 bool SkipToBlock(unsigned BlockID);
244277
245278 unsigned getRecordCode();
279
280 BitstreamReader& getStream() { return Stream; }
246281
247282 private:
248283 bool AdvanceStream();
2020
2121 Deserializer::Deserializer(BitstreamReader& stream)
2222 : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
23
24 AdvanceStream();
25 if (!AtEnd()) StreamStart = BlockStack.back();
2326 }
2427
2528 Deserializer::~Deserializer() {
5962
6063 while (!Stream.AtEndOfStream()) {
6164
65 uint64_t Pos = Stream.GetCurrentBitNo();
6266 AbbrevNo = Stream.ReadCode();
6367
6468 switch (AbbrevNo) {
6569 case bitc::ENTER_SUBBLOCK: {
6670 unsigned id = Stream.ReadSubBlockID();
67 BlockStack.push_back(std::make_pair(Stream.GetCurrentBitNo(),id));
71
72 // Determine the extent of the block. This is useful for jumping around
73 // the stream. This is hack: we read the header of the block, save
74 // the length, and then revert the bitstream to a location just before
75 // the block is entered.
76 uint64_t BPos = Stream.GetCurrentBitNo();
77 Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
78 Stream.SkipToWord();
79 unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
80 Stream.JumpToBit(BPos);
81
82 BlockStack.push_back(Location(Pos,id,NumWords));
6883 break;
6984 }
7085
90105 }
91106
92107 void Deserializer::ReadRecord() {
93
108
94109 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
95110 assert (!BlockStack.empty());
96 Stream.EnterSubBlock(BlockStack.back().second);
111 Stream.EnterSubBlock(BlockStack.back().BlockID);
97112 AbbrevNo = 0;
98113 }
99114
108123
109124 void Deserializer::SkipBlock() {
110125 assert (!inRecord());
111 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
126
127 if (AtEnd())
128 return;
129
130 AdvanceStream();
131
132 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
133 BlockStack.pop_back();
112134 Stream.SkipBlock();
135
113136 AbbrevNo = 0;
137 AdvanceStream();
138 }
139
140 bool Deserializer::SkipToBlock(unsigned BlockID) {
141 assert (!inRecord());
142
143 AdvanceStream();
144 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
145
146 unsigned BlockLevel = BlockStack.size();
147
148 while (!AtEnd() &&
149 BlockLevel == BlockStack.size() &&
150 getCurrentBlockID() != BlockID)
151 SkipBlock();
152
153 return !(AtEnd() || BlockLevel != BlockStack.size());
114154 }
115155
116156 Deserializer::Location Deserializer::getCurrentBlockLocation() {
117157 if (!inRecord())
118158 AdvanceStream();
119159
120 return BlockStack.back().first;
160 return BlockStack.back();
161 }
162
163 bool Deserializer::JumpTo(const Location& Loc) {
164
165 assert (!inRecord());
166
167 // AdvanceStream();
168
169 // assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
170 assert (!BlockStack.empty());
171
172 uint64_t LastBPos = StreamStart.BitNo;
173
174 while (!BlockStack.empty()) {
175
176 LastBPos = BlockStack.back().BitNo;
177
178 // Determine of the current block contains the location of the block
179 // we are looking for.
180 if (BlockStack.back().contains(Loc)) {
181 // We found the enclosing block. We must first POP it off to
182 // destroy any accumulated context within the block scope. We then
183 // jump to the position of the block and enter it.
184 Stream.JumpToBit(LastBPos);
185 BlockStack.pop_back();
186 Stream.PopBlockScope();
187
188 AbbrevNo = 0;
189 AdvanceStream();
190 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
191
192 Stream.EnterSubBlock(BlockStack.back().BlockID);
193 break;
194 }
195
196 // This block does not contain the block we are looking for. Pop it.
197 BlockStack.pop_back();
198 Stream.PopBlockScope();
199 }
200
201 // Check if we have popped our way to the outermost scope. If so,
202 // we need to adjust our position.
203 if (BlockStack.empty()) {
204 Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart.BitNo : LastBPos);
205 AbbrevNo = 0;
206 AdvanceStream();
207 }
208
209 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
210 assert (!BlockStack.empty());
211
212 while (!AtEnd() && BlockStack.back() != Loc) {
213 if (BlockStack.back().contains(Loc)) {
214 Stream.EnterSubBlock(BlockStack.back().BlockID);
215 AbbrevNo = 0;
216 AdvanceStream();
217 continue;
218 }
219 else
220 SkipBlock();
221 }
222
223 if (AtEnd())
224 return false;
225
226 assert (BlockStack.back() == Loc);
227
228 return true;
121229 }
122230
123231 unsigned Deserializer::getCurrentBlockID() {
124232 if (!inRecord())
125233 AdvanceStream();
126234
127 return BlockStack.back().second;
235 return BlockStack.back().BlockID;
128236 }
129237
130238 unsigned Deserializer::getRecordCode() {
141249 if (!inRecord())
142250 AdvanceStream();
143251
144 for (llvm::SmallVector<std::pair,5>::reverse_iterator
252 for (llvm::SmallVector<Location,8>::reverse_iterator
145253 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
146 if (I->first == BlockLoc)
254 if (*I == BlockLoc)
147255 return false;
148256
149257 return true;