blob: 2e8b4ef08c4467a9f472ab76f60a27b332480542 [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 Kremenek26e25b32007-11-06 19:49:16 +000016#ifdef DEBUG_BACKPATCH
17#include "llvm/Support/Streams.h"
18#endif
19
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000020using namespace llvm;
21
22Deserializer::Deserializer(BitstreamReader& stream)
Ted Kremenek48a39692007-11-09 00:43:51 +000023 : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000024
25 AdvanceStream();
26 if (!AtEnd()) StreamStart = BlockStack.back();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000027}
28
29Deserializer::~Deserializer() {
30 assert (RecIdx >= Record.size() &&
31 "Still scanning bitcode record when deserialization completed.");
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000032
Ted Kremenek48a39692007-11-09 00:43:51 +000033#ifdef DEBUG_BACKPATCH
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000034 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek066ff5b2007-11-01 00:57:37 +000035 assert (I->first.hasFinalPtr() &&
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000036 "Some pointers were not backpatched.");
37#endif
Ted Kremenekfe2a0122007-10-25 00:10:21 +000038}
39
40
41bool Deserializer::inRecord() {
42 if (Record.size() > 0) {
43 if (RecIdx >= Record.size()) {
44 RecIdx = 0;
45 Record.clear();
Ted Kremenek48a39692007-11-09 00:43:51 +000046 AbbrevNo = 0;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000047 return false;
48 }
Ted Kremenek48a39692007-11-09 00:43:51 +000049 else
50 return true;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000051 }
Ted Kremenek48a39692007-11-09 00:43:51 +000052
53 return false;
54}
55
56bool Deserializer::AdvanceStream() {
57 assert (!inRecord() &&
58 "Cannot advance stream. Still processing a record.");
59
60 if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
61 AbbrevNo >= bitc::UNABBREV_RECORD)
62 return true;
63
64 while (!Stream.AtEndOfStream()) {
65
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000066 uint64_t Pos = Stream.GetCurrentBitNo();
Ted Kremenek48a39692007-11-09 00:43:51 +000067 AbbrevNo = Stream.ReadCode();
68
69 switch (AbbrevNo) {
70 case bitc::ENTER_SUBBLOCK: {
71 unsigned id = Stream.ReadSubBlockID();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000072
73 // Determine the extent of the block. This is useful for jumping around
74 // the stream. This is hack: we read the header of the block, save
75 // the length, and then revert the bitstream to a location just before
76 // the block is entered.
77 uint64_t BPos = Stream.GetCurrentBitNo();
78 Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
79 Stream.SkipToWord();
80 unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
81 Stream.JumpToBit(BPos);
82
83 BlockStack.push_back(Location(Pos,id,NumWords));
Ted Kremenek48a39692007-11-09 00:43:51 +000084 break;
85 }
86
87 case bitc::END_BLOCK: {
88 bool x = Stream.ReadBlockEnd();
89 assert (!x && "Error at block end.");
90 BlockStack.pop_back();
91 continue;
92 }
93
94 case bitc::DEFINE_ABBREV:
95 Stream.ReadAbbrevRecord();
96 continue;
97
98 default:
99 break;
100 }
101
102 return true;
103 }
104
105 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000106}
107
108void Deserializer::ReadRecord() {
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000109
Ted Kremenek48a39692007-11-09 00:43:51 +0000110 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
111 assert (!BlockStack.empty());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000112 Stream.EnterSubBlock(BlockStack.back().BlockID);
Ted Kremenek48a39692007-11-09 00:43:51 +0000113 AbbrevNo = 0;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000114 }
Ted Kremenek48a39692007-11-09 00:43:51 +0000115
116 if (Stream.AtEndOfStream())
117 return;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000118
Ted Kremenek48a39692007-11-09 00:43:51 +0000119 assert (Record.size() == 0);
120 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
121 RecordCode = Stream.ReadRecord(AbbrevNo,Record);
122 assert (Record.size() > 0);
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000123}
124
Ted Kremenek48a39692007-11-09 00:43:51 +0000125void Deserializer::SkipBlock() {
126 assert (!inRecord());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000127
128 if (AtEnd())
129 return;
130
131 AdvanceStream();
132
133 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
134 BlockStack.pop_back();
Ted Kremenek48a39692007-11-09 00:43:51 +0000135 Stream.SkipBlock();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000136
Ted Kremenek48a39692007-11-09 00:43:51 +0000137 AbbrevNo = 0;
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000138 AdvanceStream();
139}
140
141bool Deserializer::SkipToBlock(unsigned BlockID) {
142 assert (!inRecord());
143
144 AdvanceStream();
145 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
146
147 unsigned BlockLevel = BlockStack.size();
148
149 while (!AtEnd() &&
150 BlockLevel == BlockStack.size() &&
151 getCurrentBlockID() != BlockID)
152 SkipBlock();
153
154 return !(AtEnd() || BlockLevel != BlockStack.size());
Ted Kremenek48a39692007-11-09 00:43:51 +0000155}
156
157Deserializer::Location Deserializer::getCurrentBlockLocation() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000158 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000159 AdvanceStream();
Ted Kremenekec8cd062007-11-08 19:50:46 +0000160
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000161 return BlockStack.back();
162}
163
164bool Deserializer::JumpTo(const Location& Loc) {
165
166 assert (!inRecord());
167
168// AdvanceStream();
169
170// assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
171 assert (!BlockStack.empty());
172
173 uint64_t LastBPos = StreamStart.BitNo;
174
175 while (!BlockStack.empty()) {
176
177 LastBPos = BlockStack.back().BitNo;
178
179 // Determine of the current block contains the location of the block
180 // we are looking for.
181 if (BlockStack.back().contains(Loc)) {
182 // We found the enclosing block. We must first POP it off to
183 // destroy any accumulated context within the block scope. We then
184 // jump to the position of the block and enter it.
185 Stream.JumpToBit(LastBPos);
186 BlockStack.pop_back();
187 Stream.PopBlockScope();
188
189 AbbrevNo = 0;
190 AdvanceStream();
191 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
192
193 Stream.EnterSubBlock(BlockStack.back().BlockID);
194 break;
195 }
196
197 // This block does not contain the block we are looking for. Pop it.
198 BlockStack.pop_back();
199 Stream.PopBlockScope();
200 }
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()) {
205 Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart.BitNo : LastBPos);
206 AbbrevNo = 0;
207 AdvanceStream();
208 }
209
210 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
211 assert (!BlockStack.empty());
212
213 while (!AtEnd() && BlockStack.back() != Loc) {
214 if (BlockStack.back().contains(Loc)) {
215 Stream.EnterSubBlock(BlockStack.back().BlockID);
216 AbbrevNo = 0;
217 AdvanceStream();
218 continue;
219 }
220 else
221 SkipBlock();
222 }
223
224 if (AtEnd())
225 return false;
226
227 assert (BlockStack.back() == Loc);
228
229 return true;
Ted Kremenek48a39692007-11-09 00:43:51 +0000230}
231
232unsigned Deserializer::getCurrentBlockID() {
233 if (!inRecord())
234 AdvanceStream();
235
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000236 return BlockStack.back().BlockID;
Ted Kremenek48a39692007-11-09 00:43:51 +0000237}
238
239unsigned Deserializer::getRecordCode() {
240 if (!inRecord()) {
241 AdvanceStream();
242 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
243 ReadRecord();
244 }
245
246 return RecordCode;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000247}
248
249bool Deserializer::FinishedBlock(Location BlockLoc) {
250 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000251 AdvanceStream();
252
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000253 for (llvm::SmallVector<Location,8>::reverse_iterator
Ted Kremenek48a39692007-11-09 00:43:51 +0000254 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000255 if (*I == BlockLoc)
Ted Kremenek48a39692007-11-09 00:43:51 +0000256 return false;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000257
258 return true;
259}
260
Ted Kremenek48a39692007-11-09 00:43:51 +0000261unsigned Deserializer::getAbbrevNo() {
262 if (!inRecord())
263 AdvanceStream();
264
265 return AbbrevNo;
266}
267
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000268bool Deserializer::AtEnd() {
269 if (inRecord())
270 return false;
271
Ted Kremenek48a39692007-11-09 00:43:51 +0000272 if (!AdvanceStream())
273 return true;
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000274
Ted Kremenek48a39692007-11-09 00:43:51 +0000275 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000276}
277
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000278uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000279 // FIXME: Any error recovery/handling with incomplete or bad files?
280 if (!inRecord())
281 ReadRecord();
282
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000283 return Record[RecIdx++];
284}
285
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000286int64_t Deserializer::ReadSInt() {
287 uint64_t x = ReadInt();
288 int64_t magnitude = x >> 1;
289 return x & 0x1 ? -magnitude : magnitude;
290}
291
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000292char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000293 if (cstr == NULL)
294 MaxLen = 0; // Zero this just in case someone does something funny.
295
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000296 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000297
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000298 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
299
300 if (!cstr)
301 cstr = new char[len + (isNullTerm ? 1 : 0)];
302
303 assert (cstr != NULL);
304
305 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000306 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000307
308 if (isNullTerm)
309 cstr[len+1] = '\0';
310
311 return cstr;
312}
313
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000314void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
315 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000316
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000317 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000318 buff.reserve(len);
319
320 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000321 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000322
323 if (isNullTerm)
324 buff.push_back('\0');
325}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000326
Ted Kremenek5d1f2cc2007-11-10 19:19:32 +0000327void Deserializer::RegisterPtr(SerializedPtrID PtrId, const void* Ptr) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000328 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
329
330 assert (!HasFinalPtr(E) && "Pointer already registered.");
331
Ted Kremenek26e25b32007-11-06 19:49:16 +0000332#ifdef DEBUG_BACKPATCH
333 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
334#endif
335
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000336 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000337}
338
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000339void Deserializer::ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch) {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000340 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000341
Ted Kremenek2423e032007-10-25 18:42:52 +0000342 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000343 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000344 return;
Ted Kremenek26e25b32007-11-06 19:49:16 +0000345 }
346
347#ifdef DEBUG_BACKPATCH
348 llvm::cerr << "ReadUintPtr: " << PtrId << "\n";
349#endif
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 Kremenek066ff5b2007-11-01 00:57:37 +0000353 if (HasFinalPtr(E))
354 PtrRef = GetFinalPtr(E);
Ted Kremenek5973ef42007-10-28 21:17:59 +0000355 else {
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000356 assert (AllowBackpatch &&
357 "Client forbids backpatching for this pointer.");
358
Ted Kremenek5973ef42007-10-28 21:17:59 +0000359 // Register backpatch. Check the freelist for a BPNode.
360 BPNode* N;
361
362 if (FreeList) {
363 N = FreeList;
364 FreeList = FreeList->Next;
365 }
366 else // No available BPNode. Allocate one.
367 N = (BPNode*) Allocator.Allocate<BPNode>();
368
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000369 new (N) BPNode(GetBPNode(E),PtrRef);
370 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000371 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000372}
373
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000374uintptr_t Deserializer::ReadInternalRefPtr() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000375 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000376
377 assert (PtrId != 0 && "References cannot refer the NULL address.");
378
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000379 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000380
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000381 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000382 "Cannot backpatch references. Object must be already deserialized.");
383
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000384 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000385}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000386
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000387void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000388 BPNode* Last = NULL;
389
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000390 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000391 Last = N;
392 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000393 }
394
Ted Kremenek5973ef42007-10-28 21:17:59 +0000395 if (Last) {
396 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000397 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000398 }
399
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000400 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000401}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000402
Ted Kremenek5973ef42007-10-28 21:17:59 +0000403
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000404#define INT_READ(TYPE)\
405void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000406 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000407
408INT_READ(bool)
409INT_READ(unsigned char)
410INT_READ(unsigned short)
411INT_READ(unsigned int)
412INT_READ(unsigned long)
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000413
414#define SINT_READ(TYPE)\
415void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
416 X = (TYPE) D.ReadSInt(); }
417
418INT_READ(signed char)
419INT_READ(signed short)
420INT_READ(signed int)
421INT_READ(signed long)