blob: 965ff708a2c99393c5e43923f0ed1b9431f0265a [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//
5// This file was developed by Ted Kremenek and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
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"
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000015
Ted Kremenek38afd9e2007-11-14 08:05:03 +000016#define DEBUG_BACKPATCH
17
Ted Kremenek26e25b32007-11-06 19:49:16 +000018#ifdef DEBUG_BACKPATCH
19#include "llvm/Support/Streams.h"
20#endif
21
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000022using namespace llvm;
23
24Deserializer::Deserializer(BitstreamReader& stream)
Ted Kremenek48a39692007-11-09 00:43:51 +000025 : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000026
27 AdvanceStream();
28 if (!AtEnd()) StreamStart = BlockStack.back();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000029}
30
31Deserializer::~Deserializer() {
32 assert (RecIdx >= Record.size() &&
33 "Still scanning bitcode record when deserialization completed.");
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000034
Ted Kremenek48a39692007-11-09 00:43:51 +000035#ifdef DEBUG_BACKPATCH
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000036 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek066ff5b2007-11-01 00:57:37 +000037 assert (I->first.hasFinalPtr() &&
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000038 "Some pointers were not backpatched.");
39#endif
Ted Kremenekfe2a0122007-10-25 00:10:21 +000040}
41
42
43bool Deserializer::inRecord() {
44 if (Record.size() > 0) {
45 if (RecIdx >= Record.size()) {
46 RecIdx = 0;
47 Record.clear();
Ted Kremenek48a39692007-11-09 00:43:51 +000048 AbbrevNo = 0;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000049 return false;
50 }
Ted Kremenek48a39692007-11-09 00:43:51 +000051 else
52 return true;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000053 }
Ted Kremenek48a39692007-11-09 00:43:51 +000054
55 return false;
56}
57
58bool Deserializer::AdvanceStream() {
59 assert (!inRecord() &&
60 "Cannot advance stream. Still processing a record.");
61
62 if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
63 AbbrevNo >= bitc::UNABBREV_RECORD)
64 return true;
65
66 while (!Stream.AtEndOfStream()) {
67
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000068 uint64_t Pos = Stream.GetCurrentBitNo();
Ted Kremenek48a39692007-11-09 00:43:51 +000069 AbbrevNo = Stream.ReadCode();
70
71 switch (AbbrevNo) {
72 case bitc::ENTER_SUBBLOCK: {
73 unsigned id = Stream.ReadSubBlockID();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000074
75 // Determine the extent of the block. This is useful for jumping around
76 // the stream. This is hack: we read the header of the block, save
77 // the length, and then revert the bitstream to a location just before
78 // the block is entered.
79 uint64_t BPos = Stream.GetCurrentBitNo();
80 Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
81 Stream.SkipToWord();
82 unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
83 Stream.JumpToBit(BPos);
84
85 BlockStack.push_back(Location(Pos,id,NumWords));
Ted Kremenek48a39692007-11-09 00:43:51 +000086 break;
87 }
88
89 case bitc::END_BLOCK: {
90 bool x = Stream.ReadBlockEnd();
91 assert (!x && "Error at block end.");
92 BlockStack.pop_back();
93 continue;
94 }
95
96 case bitc::DEFINE_ABBREV:
97 Stream.ReadAbbrevRecord();
98 continue;
99
100 default:
101 break;
102 }
103
104 return true;
105 }
106
107 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000108}
109
110void Deserializer::ReadRecord() {
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000111
Ted Kremenek48a39692007-11-09 00:43:51 +0000112 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
113 assert (!BlockStack.empty());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000114 Stream.EnterSubBlock(BlockStack.back().BlockID);
Ted Kremenek48a39692007-11-09 00:43:51 +0000115 AbbrevNo = 0;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000116 }
Ted Kremenek48a39692007-11-09 00:43:51 +0000117
118 if (Stream.AtEndOfStream())
119 return;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000120
Ted Kremenek48a39692007-11-09 00:43:51 +0000121 assert (Record.size() == 0);
122 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
123 RecordCode = Stream.ReadRecord(AbbrevNo,Record);
124 assert (Record.size() > 0);
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000125}
126
Ted Kremenek48a39692007-11-09 00:43:51 +0000127void Deserializer::SkipBlock() {
128 assert (!inRecord());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000129
130 if (AtEnd())
131 return;
132
133 AdvanceStream();
134
135 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
136 BlockStack.pop_back();
Ted Kremenek48a39692007-11-09 00:43:51 +0000137 Stream.SkipBlock();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000138
Ted Kremenek48a39692007-11-09 00:43:51 +0000139 AbbrevNo = 0;
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000140 AdvanceStream();
141}
142
143bool Deserializer::SkipToBlock(unsigned BlockID) {
144 assert (!inRecord());
145
146 AdvanceStream();
147 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
148
149 unsigned BlockLevel = BlockStack.size();
150
151 while (!AtEnd() &&
152 BlockLevel == BlockStack.size() &&
153 getCurrentBlockID() != BlockID)
154 SkipBlock();
155
156 return !(AtEnd() || BlockLevel != BlockStack.size());
Ted Kremenek48a39692007-11-09 00:43:51 +0000157}
158
159Deserializer::Location Deserializer::getCurrentBlockLocation() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000160 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000161 AdvanceStream();
Ted Kremenekec8cd062007-11-08 19:50:46 +0000162
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000163 return BlockStack.back();
164}
165
166bool Deserializer::JumpTo(const Location& Loc) {
167
168 assert (!inRecord());
169
170// AdvanceStream();
171
172// assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
173 assert (!BlockStack.empty());
174
175 uint64_t LastBPos = StreamStart.BitNo;
176
177 while (!BlockStack.empty()) {
178
179 LastBPos = BlockStack.back().BitNo;
180
181 // Determine of the current block contains the location of the block
182 // we are looking for.
183 if (BlockStack.back().contains(Loc)) {
184 // We found the enclosing block. We must first POP it off to
185 // destroy any accumulated context within the block scope. We then
186 // jump to the position of the block and enter it.
187 Stream.JumpToBit(LastBPos);
188 BlockStack.pop_back();
189 Stream.PopBlockScope();
190
191 AbbrevNo = 0;
192 AdvanceStream();
193 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
194
195 Stream.EnterSubBlock(BlockStack.back().BlockID);
196 break;
197 }
198
199 // This block does not contain the block we are looking for. Pop it.
200 BlockStack.pop_back();
201 Stream.PopBlockScope();
202 }
203
204 // Check if we have popped our way to the outermost scope. If so,
205 // we need to adjust our position.
206 if (BlockStack.empty()) {
207 Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart.BitNo : LastBPos);
208 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
234unsigned Deserializer::getCurrentBlockID() {
235 if (!inRecord())
236 AdvanceStream();
237
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000238 return BlockStack.back().BlockID;
Ted Kremenek48a39692007-11-09 00:43:51 +0000239}
240
241unsigned Deserializer::getRecordCode() {
242 if (!inRecord()) {
243 AdvanceStream();
244 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
245 ReadRecord();
246 }
247
248 return RecordCode;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000249}
250
251bool Deserializer::FinishedBlock(Location BlockLoc) {
252 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000253 AdvanceStream();
254
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000255 for (llvm::SmallVector<Location,8>::reverse_iterator
Ted Kremenek48a39692007-11-09 00:43:51 +0000256 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000257 if (*I == BlockLoc)
Ted Kremenek48a39692007-11-09 00:43:51 +0000258 return false;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000259
260 return true;
261}
262
Ted Kremenek48a39692007-11-09 00:43:51 +0000263unsigned Deserializer::getAbbrevNo() {
264 if (!inRecord())
265 AdvanceStream();
266
267 return AbbrevNo;
268}
269
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000270bool Deserializer::AtEnd() {
271 if (inRecord())
272 return false;
273
Ted Kremenek48a39692007-11-09 00:43:51 +0000274 if (!AdvanceStream())
275 return true;
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000276
Ted Kremenek48a39692007-11-09 00:43:51 +0000277 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000278}
279
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000280uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000281 // FIXME: Any error recovery/handling with incomplete or bad files?
282 if (!inRecord())
283 ReadRecord();
284
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000285 return Record[RecIdx++];
286}
287
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000288int64_t Deserializer::ReadSInt() {
289 uint64_t x = ReadInt();
290 int64_t magnitude = x >> 1;
291 return x & 0x1 ? -magnitude : magnitude;
292}
293
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000294char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000295 if (cstr == NULL)
296 MaxLen = 0; // Zero this just in case someone does something funny.
297
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000298 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000299
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000300 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
301
302 if (!cstr)
303 cstr = new char[len + (isNullTerm ? 1 : 0)];
304
305 assert (cstr != NULL);
306
307 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000308 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000309
310 if (isNullTerm)
311 cstr[len+1] = '\0';
312
313 return cstr;
314}
315
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000316void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
317 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000318
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000319 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000320 buff.reserve(len);
321
322 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000323 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000324
325 if (isNullTerm)
326 buff.push_back('\0');
327}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000328
Ted Kremenek62724da2007-11-12 19:11:15 +0000329void Deserializer::RegisterPtr(const SerializedPtrID& PtrId,
330 const void* Ptr) {
331
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000332 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
333
334 assert (!HasFinalPtr(E) && "Pointer already registered.");
335
Ted Kremenek26e25b32007-11-06 19:49:16 +0000336#ifdef DEBUG_BACKPATCH
337 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
338#endif
339
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000340 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000341}
342
Ted Kremenek62724da2007-11-12 19:11:15 +0000343void Deserializer::ReadUIntPtr(uintptr_t& PtrRef,
344 const SerializedPtrID& PtrId,
345 bool AllowBackpatch) {
Ted Kremenek2423e032007-10-25 18:42:52 +0000346 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000347 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000348 return;
Ted Kremenek26e25b32007-11-06 19:49:16 +0000349 }
350
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000351 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000352
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000353 if (HasFinalPtr(E)) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000354 PtrRef = GetFinalPtr(E);
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000355
356#ifdef DEBUG_BACKPATCH
357 llvm::cerr << "ReadUintPtr: " << PtrId
358 << " <-- " << (void*) GetFinalPtr(E) << '\n';
359#endif
360 }
Ted Kremenek5973ef42007-10-28 21:17:59 +0000361 else {
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000362 assert (AllowBackpatch &&
363 "Client forbids backpatching for this pointer.");
364
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000365#ifdef DEBUG_BACKPATCH
366 llvm::cerr << "ReadUintPtr: " << PtrId << " (NO PTR YET)\n";
367#endif
368
Ted Kremenek5973ef42007-10-28 21:17:59 +0000369 // Register backpatch. Check the freelist for a BPNode.
370 BPNode* N;
371
372 if (FreeList) {
373 N = FreeList;
374 FreeList = FreeList->Next;
375 }
376 else // No available BPNode. Allocate one.
377 N = (BPNode*) Allocator.Allocate<BPNode>();
378
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000379 new (N) BPNode(GetBPNode(E),PtrRef);
380 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000381 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000382}
383
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000384uintptr_t Deserializer::ReadInternalRefPtr() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000385 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000386
387 assert (PtrId != 0 && "References cannot refer the NULL address.");
388
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000389 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000390
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000391 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000392 "Cannot backpatch references. Object must be already deserialized.");
393
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000394 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000395}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000396
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000397void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000398 BPNode* Last = NULL;
399
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000400 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000401 Last = N;
402 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000403 }
404
Ted Kremenek5973ef42007-10-28 21:17:59 +0000405 if (Last) {
406 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000407 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000408 }
409
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000410 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000411}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000412
Ted Kremenek5973ef42007-10-28 21:17:59 +0000413
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000414#define INT_READ(TYPE)\
415void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000416 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000417
418INT_READ(bool)
419INT_READ(unsigned char)
420INT_READ(unsigned short)
421INT_READ(unsigned int)
422INT_READ(unsigned long)
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000423
424#define SINT_READ(TYPE)\
425void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
426 X = (TYPE) D.ReadSInt(); }
427
428INT_READ(signed char)
429INT_READ(signed short)
430INT_READ(signed int)
431INT_READ(signed long)