blob: 67607efae08a5e1f6376ca991279374890eea15f [file] [log] [blame]
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +00001//==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the internal methods used for object serialization.
11//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek6e9b4962007-10-24 19:06:40 +000014#include "llvm/Bitcode/Deserialize.h"
Chris Lattnerb515d752009-08-23 07:49:08 +000015#include "llvm/Support/raw_ostream.h"
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000016using namespace llvm;
17
18Deserializer::Deserializer(BitstreamReader& stream)
Ted Kremenek48a39692007-11-09 00:43:51 +000019 : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
Ted Kremenekf64903b2007-11-30 22:45:05 +000020
Chris Lattner962dde32009-04-26 20:59:02 +000021 StreamStart = Stream.GetCurrentBitNo();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000022}
23
24Deserializer::~Deserializer() {
25 assert (RecIdx >= Record.size() &&
26 "Still scanning bitcode record when deserialization completed.");
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000027
Ted Kremenek48a39692007-11-09 00:43:51 +000028#ifdef DEBUG_BACKPATCH
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000029 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek066ff5b2007-11-01 00:57:37 +000030 assert (I->first.hasFinalPtr() &&
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000031 "Some pointers were not backpatched.");
32#endif
Ted Kremenekfe2a0122007-10-25 00:10:21 +000033}
34
35
36bool Deserializer::inRecord() {
37 if (Record.size() > 0) {
38 if (RecIdx >= Record.size()) {
39 RecIdx = 0;
40 Record.clear();
Ted Kremenek48a39692007-11-09 00:43:51 +000041 AbbrevNo = 0;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000042 return false;
43 }
Ted Kremenek48a39692007-11-09 00:43:51 +000044 else
45 return true;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000046 }
Ted Kremenek48a39692007-11-09 00:43:51 +000047
48 return false;
49}
50
51bool Deserializer::AdvanceStream() {
52 assert (!inRecord() &&
53 "Cannot advance stream. Still processing a record.");
54
55 if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
56 AbbrevNo >= bitc::UNABBREV_RECORD)
57 return true;
58
59 while (!Stream.AtEndOfStream()) {
60
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000061 uint64_t Pos = Stream.GetCurrentBitNo();
Ted Kremenek48a39692007-11-09 00:43:51 +000062 AbbrevNo = Stream.ReadCode();
63
64 switch (AbbrevNo) {
65 case bitc::ENTER_SUBBLOCK: {
66 unsigned id = Stream.ReadSubBlockID();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000067
68 // Determine the extent of the block. This is useful for jumping around
69 // the stream. This is hack: we read the header of the block, save
70 // the length, and then revert the bitstream to a location just before
71 // the block is entered.
72 uint64_t BPos = Stream.GetCurrentBitNo();
73 Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
74 Stream.SkipToWord();
75 unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
76 Stream.JumpToBit(BPos);
77
78 BlockStack.push_back(Location(Pos,id,NumWords));
Ted Kremenek48a39692007-11-09 00:43:51 +000079 break;
80 }
81
82 case bitc::END_BLOCK: {
83 bool x = Stream.ReadBlockEnd();
Zhongxing Xuf900f7b2008-12-23 05:43:56 +000084 assert(!x && "Error at block end."); x=x;
Ted Kremenek48a39692007-11-09 00:43:51 +000085 BlockStack.pop_back();
86 continue;
87 }
88
89 case bitc::DEFINE_ABBREV:
90 Stream.ReadAbbrevRecord();
91 continue;
92
93 default:
94 break;
95 }
96
97 return true;
98 }
99
100 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000101}
102
103void Deserializer::ReadRecord() {
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000104
Ted Kremenek48a39692007-11-09 00:43:51 +0000105 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
106 assert (!BlockStack.empty());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000107 Stream.EnterSubBlock(BlockStack.back().BlockID);
Ted Kremenek48a39692007-11-09 00:43:51 +0000108 AbbrevNo = 0;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000109 }
Ted Kremenek48a39692007-11-09 00:43:51 +0000110
111 if (Stream.AtEndOfStream())
112 return;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000113
Dan Gohman30359592008-01-29 13:02:09 +0000114 assert (Record.empty());
Ted Kremenek48a39692007-11-09 00:43:51 +0000115 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
116 RecordCode = Stream.ReadRecord(AbbrevNo,Record);
117 assert (Record.size() > 0);
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000118}
119
Ted Kremenek48a39692007-11-09 00:43:51 +0000120void Deserializer::SkipBlock() {
121 assert (!inRecord());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000122
123 if (AtEnd())
124 return;
125
126 AdvanceStream();
127
128 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
129 BlockStack.pop_back();
Ted Kremenek48a39692007-11-09 00:43:51 +0000130 Stream.SkipBlock();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000131
Ted Kremenek48a39692007-11-09 00:43:51 +0000132 AbbrevNo = 0;
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000133 AdvanceStream();
134}
135
136bool Deserializer::SkipToBlock(unsigned BlockID) {
137 assert (!inRecord());
138
139 AdvanceStream();
140 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
141
142 unsigned BlockLevel = BlockStack.size();
143
144 while (!AtEnd() &&
145 BlockLevel == BlockStack.size() &&
146 getCurrentBlockID() != BlockID)
147 SkipBlock();
148
149 return !(AtEnd() || BlockLevel != BlockStack.size());
Ted Kremenek48a39692007-11-09 00:43:51 +0000150}
151
152Deserializer::Location Deserializer::getCurrentBlockLocation() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000153 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000154 AdvanceStream();
Ted Kremenekec8cd062007-11-08 19:50:46 +0000155
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000156 return BlockStack.back();
157}
158
159bool Deserializer::JumpTo(const Location& Loc) {
160
161 assert (!inRecord());
162
Ted Kremenekf64903b2007-11-30 22:45:05 +0000163 AdvanceStream();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000164
Ted Kremenek233b60e2007-11-14 17:42:09 +0000165 assert (!BlockStack.empty() || AtEnd());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000166
Ted Kremenekf64903b2007-11-30 22:45:05 +0000167 uint64_t LastBPos = StreamStart;
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000168
169 while (!BlockStack.empty()) {
170
171 LastBPos = BlockStack.back().BitNo;
172
173 // Determine of the current block contains the location of the block
174 // we are looking for.
175 if (BlockStack.back().contains(Loc)) {
176 // We found the enclosing block. We must first POP it off to
177 // destroy any accumulated context within the block scope. We then
178 // jump to the position of the block and enter it.
179 Stream.JumpToBit(LastBPos);
Ted Kremenekf64903b2007-11-30 22:45:05 +0000180
181 if (BlockStack.size() == Stream.BlockScope.size())
182 Stream.PopBlockScope();
183
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000184 BlockStack.pop_back();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000185
186 AbbrevNo = 0;
187 AdvanceStream();
188 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
189
190 Stream.EnterSubBlock(BlockStack.back().BlockID);
191 break;
192 }
193
194 // This block does not contain the block we are looking for. Pop it.
Ted Kremenekf64903b2007-11-30 22:45:05 +0000195 if (BlockStack.size() == Stream.BlockScope.size())
196 Stream.PopBlockScope();
197
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000198 BlockStack.pop_back();
Ted Kremenekf64903b2007-11-30 22:45:05 +0000199
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000200 }
201
202 // Check if we have popped our way to the outermost scope. If so,
203 // we need to adjust our position.
204 if (BlockStack.empty()) {
Ted Kremenekf64903b2007-11-30 22:45:05 +0000205 assert (Stream.BlockScope.empty());
206
207 Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart : LastBPos);
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000208 AbbrevNo = 0;
209 AdvanceStream();
210 }
211
212 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
213 assert (!BlockStack.empty());
214
215 while (!AtEnd() && BlockStack.back() != Loc) {
216 if (BlockStack.back().contains(Loc)) {
217 Stream.EnterSubBlock(BlockStack.back().BlockID);
218 AbbrevNo = 0;
219 AdvanceStream();
220 continue;
221 }
222 else
223 SkipBlock();
224 }
225
226 if (AtEnd())
227 return false;
228
229 assert (BlockStack.back() == Loc);
230
231 return true;
Ted Kremenek48a39692007-11-09 00:43:51 +0000232}
233
Ted Kremenekf64903b2007-11-30 22:45:05 +0000234void Deserializer::Rewind() {
235 while (!Stream.BlockScope.empty())
236 Stream.PopBlockScope();
237
238 while (!BlockStack.empty())
239 BlockStack.pop_back();
240
241 Stream.JumpToBit(StreamStart);
242 AbbrevNo = 0;
243}
244
245
Ted Kremenek48a39692007-11-09 00:43:51 +0000246unsigned Deserializer::getCurrentBlockID() {
247 if (!inRecord())
248 AdvanceStream();
249
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000250 return BlockStack.back().BlockID;
Ted Kremenek48a39692007-11-09 00:43:51 +0000251}
252
253unsigned Deserializer::getRecordCode() {
254 if (!inRecord()) {
255 AdvanceStream();
256 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
257 ReadRecord();
258 }
259
260 return RecordCode;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000261}
262
263bool Deserializer::FinishedBlock(Location BlockLoc) {
264 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000265 AdvanceStream();
266
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000267 for (llvm::SmallVector<Location,8>::reverse_iterator
Ted Kremenek48a39692007-11-09 00:43:51 +0000268 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000269 if (*I == BlockLoc)
Ted Kremenek48a39692007-11-09 00:43:51 +0000270 return false;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000271
272 return true;
273}
274
Ted Kremenek48a39692007-11-09 00:43:51 +0000275unsigned Deserializer::getAbbrevNo() {
276 if (!inRecord())
277 AdvanceStream();
278
279 return AbbrevNo;
280}
281
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000282bool Deserializer::AtEnd() {
283 if (inRecord())
284 return false;
285
Ted Kremenek48a39692007-11-09 00:43:51 +0000286 if (!AdvanceStream())
287 return true;
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000288
Ted Kremenek48a39692007-11-09 00:43:51 +0000289 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000290}
291
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000292uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000293 // FIXME: Any error recovery/handling with incomplete or bad files?
294 if (!inRecord())
295 ReadRecord();
296
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000297 return Record[RecIdx++];
298}
299
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000300int64_t Deserializer::ReadSInt() {
301 uint64_t x = ReadInt();
302 int64_t magnitude = x >> 1;
303 return x & 0x1 ? -magnitude : magnitude;
304}
305
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000306char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000307 if (cstr == NULL)
308 MaxLen = 0; // Zero this just in case someone does something funny.
309
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000310 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000311
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000312 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
313
314 if (!cstr)
315 cstr = new char[len + (isNullTerm ? 1 : 0)];
316
317 assert (cstr != NULL);
318
319 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000320 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000321
322 if (isNullTerm)
Ted Kremenek57daefa2008-02-23 01:11:40 +0000323 cstr[len] = '\0';
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000324
325 return cstr;
326}
327
Ted Kremenek8f559ef2007-12-17 22:25:12 +0000328void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm,
329 unsigned Idx) {
330
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000331 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000332
Ted Kremenek8f559ef2007-12-17 22:25:12 +0000333 // If Idx is beyond the current before size, reduce Idx to refer to the
334 // element after the last element.
335 if (Idx > buff.size())
336 Idx = buff.size();
337
338 buff.reserve(len+Idx);
339 buff.resize(Idx);
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000340
341 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000342 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000343
344 if (isNullTerm)
345 buff.push_back('\0');
346}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000347
Ted Kremenek62724da2007-11-12 19:11:15 +0000348void Deserializer::RegisterPtr(const SerializedPtrID& PtrId,
349 const void* Ptr) {
350
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000351 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
352
353 assert (!HasFinalPtr(E) && "Pointer already registered.");
354
Ted Kremenek26e25b32007-11-06 19:49:16 +0000355#ifdef DEBUG_BACKPATCH
Chris Lattnerb515d752009-08-23 07:49:08 +0000356 errs() << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
Ted Kremenek26e25b32007-11-06 19:49:16 +0000357#endif
358
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000359 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000360}
361
Ted Kremenek62724da2007-11-12 19:11:15 +0000362void Deserializer::ReadUIntPtr(uintptr_t& PtrRef,
363 const SerializedPtrID& PtrId,
364 bool AllowBackpatch) {
Ted Kremenek2423e032007-10-25 18:42:52 +0000365 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000366 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000367 return;
Ted Kremenek26e25b32007-11-06 19:49:16 +0000368 }
369
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000370 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000371
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000372 if (HasFinalPtr(E)) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000373 PtrRef = GetFinalPtr(E);
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000374
375#ifdef DEBUG_BACKPATCH
Chris Lattnerb515d752009-08-23 07:49:08 +0000376 errs() << "ReadUintPtr: " << PtrId
377 << " <-- " << (void*) GetFinalPtr(E) << '\n';
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000378#endif
379 }
Ted Kremenek5973ef42007-10-28 21:17:59 +0000380 else {
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000381 assert (AllowBackpatch &&
382 "Client forbids backpatching for this pointer.");
383
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000384#ifdef DEBUG_BACKPATCH
Chris Lattnerb515d752009-08-23 07:49:08 +0000385 errs() << "ReadUintPtr: " << PtrId << " (NO PTR YET)\n";
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000386#endif
387
Ted Kremenek5973ef42007-10-28 21:17:59 +0000388 // Register backpatch. Check the freelist for a BPNode.
389 BPNode* N;
390
391 if (FreeList) {
392 N = FreeList;
393 FreeList = FreeList->Next;
394 }
395 else // No available BPNode. Allocate one.
396 N = (BPNode*) Allocator.Allocate<BPNode>();
397
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000398 new (N) BPNode(GetBPNode(E),PtrRef);
399 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000400 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000401}
402
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000403uintptr_t Deserializer::ReadInternalRefPtr() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000404 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000405
406 assert (PtrId != 0 && "References cannot refer the NULL address.");
407
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000408 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000409
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000410 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000411 "Cannot backpatch references. Object must be already deserialized.");
412
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000413 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000414}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000415
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000416void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000417 BPNode* Last = NULL;
418
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000419 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000420 Last = N;
421 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000422 }
423
Ted Kremenek5973ef42007-10-28 21:17:59 +0000424 if (Last) {
425 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000426 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000427 }
428
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000429 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000430}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000431
Ted Kremenek5973ef42007-10-28 21:17:59 +0000432
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000433#define INT_READ(TYPE)\
434void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000435 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000436
437INT_READ(bool)
438INT_READ(unsigned char)
439INT_READ(unsigned short)
440INT_READ(unsigned int)
441INT_READ(unsigned long)
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000442
443#define SINT_READ(TYPE)\
444void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
445 X = (TYPE) D.ReadSInt(); }
446
447INT_READ(signed char)
448INT_READ(signed short)
449INT_READ(signed int)
450INT_READ(signed long)