blob: cb32f7d5efefd83ee10ed342e63a68292d9a2e83 [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 Kremenekf64903b2007-11-30 22:45:05 +000024
25 StreamStart = Stream.GetCurrentBitNo();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000026}
27
28Deserializer::~Deserializer() {
29 assert (RecIdx >= Record.size() &&
30 "Still scanning bitcode record when deserialization completed.");
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000031
Ted Kremenek48a39692007-11-09 00:43:51 +000032#ifdef DEBUG_BACKPATCH
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000033 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek066ff5b2007-11-01 00:57:37 +000034 assert (I->first.hasFinalPtr() &&
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000035 "Some pointers were not backpatched.");
36#endif
Ted Kremenekfe2a0122007-10-25 00:10:21 +000037}
38
39
40bool Deserializer::inRecord() {
41 if (Record.size() > 0) {
42 if (RecIdx >= Record.size()) {
43 RecIdx = 0;
44 Record.clear();
Ted Kremenek48a39692007-11-09 00:43:51 +000045 AbbrevNo = 0;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000046 return false;
47 }
Ted Kremenek48a39692007-11-09 00:43:51 +000048 else
49 return true;
Ted Kremenekfe2a0122007-10-25 00:10:21 +000050 }
Ted Kremenek48a39692007-11-09 00:43:51 +000051
52 return false;
53}
54
55bool Deserializer::AdvanceStream() {
56 assert (!inRecord() &&
57 "Cannot advance stream. Still processing a record.");
58
59 if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
60 AbbrevNo >= bitc::UNABBREV_RECORD)
61 return true;
62
63 while (!Stream.AtEndOfStream()) {
64
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000065 uint64_t Pos = Stream.GetCurrentBitNo();
Ted Kremenek48a39692007-11-09 00:43:51 +000066 AbbrevNo = Stream.ReadCode();
67
68 switch (AbbrevNo) {
69 case bitc::ENTER_SUBBLOCK: {
70 unsigned id = Stream.ReadSubBlockID();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +000071
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));
Ted Kremenek48a39692007-11-09 00:43:51 +000083 break;
84 }
85
86 case bitc::END_BLOCK: {
87 bool x = Stream.ReadBlockEnd();
88 assert (!x && "Error at block end.");
89 BlockStack.pop_back();
90 continue;
91 }
92
93 case bitc::DEFINE_ABBREV:
94 Stream.ReadAbbrevRecord();
95 continue;
96
97 default:
98 break;
99 }
100
101 return true;
102 }
103
104 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000105}
106
107void Deserializer::ReadRecord() {
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000108
Ted Kremenek48a39692007-11-09 00:43:51 +0000109 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
110 assert (!BlockStack.empty());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000111 Stream.EnterSubBlock(BlockStack.back().BlockID);
Ted Kremenek48a39692007-11-09 00:43:51 +0000112 AbbrevNo = 0;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000113 }
Ted Kremenek48a39692007-11-09 00:43:51 +0000114
115 if (Stream.AtEndOfStream())
116 return;
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000117
Ted Kremenek48a39692007-11-09 00:43:51 +0000118 assert (Record.size() == 0);
119 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
120 RecordCode = Stream.ReadRecord(AbbrevNo,Record);
121 assert (Record.size() > 0);
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000122}
123
Ted Kremenek48a39692007-11-09 00:43:51 +0000124void Deserializer::SkipBlock() {
125 assert (!inRecord());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000126
127 if (AtEnd())
128 return;
129
130 AdvanceStream();
131
132 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
133 BlockStack.pop_back();
Ted Kremenek48a39692007-11-09 00:43:51 +0000134 Stream.SkipBlock();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000135
Ted Kremenek48a39692007-11-09 00:43:51 +0000136 AbbrevNo = 0;
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000137 AdvanceStream();
138}
139
140bool 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());
Ted Kremenek48a39692007-11-09 00:43:51 +0000154}
155
156Deserializer::Location Deserializer::getCurrentBlockLocation() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000157 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000158 AdvanceStream();
Ted Kremenekec8cd062007-11-08 19:50:46 +0000159
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000160 return BlockStack.back();
161}
162
163bool Deserializer::JumpTo(const Location& Loc) {
164
165 assert (!inRecord());
166
Ted Kremenekf64903b2007-11-30 22:45:05 +0000167 AdvanceStream();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000168
Ted Kremenek233b60e2007-11-14 17:42:09 +0000169 assert (!BlockStack.empty() || AtEnd());
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000170
Ted Kremenekf64903b2007-11-30 22:45:05 +0000171 uint64_t LastBPos = StreamStart;
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000172
173 while (!BlockStack.empty()) {
174
175 LastBPos = BlockStack.back().BitNo;
176
177 // Determine of the current block contains the location of the block
178 // we are looking for.
179 if (BlockStack.back().contains(Loc)) {
180 // We found the enclosing block. We must first POP it off to
181 // destroy any accumulated context within the block scope. We then
182 // jump to the position of the block and enter it.
183 Stream.JumpToBit(LastBPos);
Ted Kremenekf64903b2007-11-30 22:45:05 +0000184
185 if (BlockStack.size() == Stream.BlockScope.size())
186 Stream.PopBlockScope();
187
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000188 BlockStack.pop_back();
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000189
190 AbbrevNo = 0;
191 AdvanceStream();
192 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
193
194 Stream.EnterSubBlock(BlockStack.back().BlockID);
195 break;
196 }
197
198 // This block does not contain the block we are looking for. Pop it.
Ted Kremenekf64903b2007-11-30 22:45:05 +0000199 if (BlockStack.size() == Stream.BlockScope.size())
200 Stream.PopBlockScope();
201
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000202 BlockStack.pop_back();
Ted Kremenekf64903b2007-11-30 22:45:05 +0000203
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000204 }
205
206 // Check if we have popped our way to the outermost scope. If so,
207 // we need to adjust our position.
208 if (BlockStack.empty()) {
Ted Kremenekf64903b2007-11-30 22:45:05 +0000209 assert (Stream.BlockScope.empty());
210
211 Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart : LastBPos);
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000212 AbbrevNo = 0;
213 AdvanceStream();
214 }
215
216 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
217 assert (!BlockStack.empty());
218
219 while (!AtEnd() && BlockStack.back() != Loc) {
220 if (BlockStack.back().contains(Loc)) {
221 Stream.EnterSubBlock(BlockStack.back().BlockID);
222 AbbrevNo = 0;
223 AdvanceStream();
224 continue;
225 }
226 else
227 SkipBlock();
228 }
229
230 if (AtEnd())
231 return false;
232
233 assert (BlockStack.back() == Loc);
234
235 return true;
Ted Kremenek48a39692007-11-09 00:43:51 +0000236}
237
Ted Kremenekf64903b2007-11-30 22:45:05 +0000238void Deserializer::Rewind() {
239 while (!Stream.BlockScope.empty())
240 Stream.PopBlockScope();
241
242 while (!BlockStack.empty())
243 BlockStack.pop_back();
244
245 Stream.JumpToBit(StreamStart);
246 AbbrevNo = 0;
247}
248
249
Ted Kremenek48a39692007-11-09 00:43:51 +0000250unsigned Deserializer::getCurrentBlockID() {
251 if (!inRecord())
252 AdvanceStream();
253
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000254 return BlockStack.back().BlockID;
Ted Kremenek48a39692007-11-09 00:43:51 +0000255}
256
257unsigned Deserializer::getRecordCode() {
258 if (!inRecord()) {
259 AdvanceStream();
260 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
261 ReadRecord();
262 }
263
264 return RecordCode;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000265}
266
267bool Deserializer::FinishedBlock(Location BlockLoc) {
268 if (!inRecord())
Ted Kremenek48a39692007-11-09 00:43:51 +0000269 AdvanceStream();
270
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000271 for (llvm::SmallVector<Location,8>::reverse_iterator
Ted Kremenek48a39692007-11-09 00:43:51 +0000272 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
Ted Kremenek1a8a08a2007-11-10 02:02:34 +0000273 if (*I == BlockLoc)
Ted Kremenek48a39692007-11-09 00:43:51 +0000274 return false;
Ted Kremenekec8cd062007-11-08 19:50:46 +0000275
276 return true;
277}
278
Ted Kremenek48a39692007-11-09 00:43:51 +0000279unsigned Deserializer::getAbbrevNo() {
280 if (!inRecord())
281 AdvanceStream();
282
283 return AbbrevNo;
284}
285
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000286bool Deserializer::AtEnd() {
287 if (inRecord())
288 return false;
289
Ted Kremenek48a39692007-11-09 00:43:51 +0000290 if (!AdvanceStream())
291 return true;
Ted Kremenek0a6d98e2007-11-05 21:36:35 +0000292
Ted Kremenek48a39692007-11-09 00:43:51 +0000293 return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000294}
295
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000296uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000297 // FIXME: Any error recovery/handling with incomplete or bad files?
298 if (!inRecord())
299 ReadRecord();
300
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000301 return Record[RecIdx++];
302}
303
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000304int64_t Deserializer::ReadSInt() {
305 uint64_t x = ReadInt();
306 int64_t magnitude = x >> 1;
307 return x & 0x1 ? -magnitude : magnitude;
308}
309
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000310char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000311 if (cstr == NULL)
312 MaxLen = 0; // Zero this just in case someone does something funny.
313
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000314 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000315
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000316 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
317
318 if (!cstr)
319 cstr = new char[len + (isNullTerm ? 1 : 0)];
320
321 assert (cstr != NULL);
322
323 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000324 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000325
326 if (isNullTerm)
327 cstr[len+1] = '\0';
328
329 return cstr;
330}
331
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000332void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
333 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000334
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000335 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000336 buff.reserve(len);
337
338 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000339 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000340
341 if (isNullTerm)
342 buff.push_back('\0');
343}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000344
Ted Kremenek62724da2007-11-12 19:11:15 +0000345void Deserializer::RegisterPtr(const SerializedPtrID& PtrId,
346 const void* Ptr) {
347
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000348 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
349
350 assert (!HasFinalPtr(E) && "Pointer already registered.");
351
Ted Kremenek26e25b32007-11-06 19:49:16 +0000352#ifdef DEBUG_BACKPATCH
353 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
354#endif
355
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000356 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000357}
358
Ted Kremenek62724da2007-11-12 19:11:15 +0000359void Deserializer::ReadUIntPtr(uintptr_t& PtrRef,
360 const SerializedPtrID& PtrId,
361 bool AllowBackpatch) {
Ted Kremenek2423e032007-10-25 18:42:52 +0000362 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000363 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000364 return;
Ted Kremenek26e25b32007-11-06 19:49:16 +0000365 }
366
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000367 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000368
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000369 if (HasFinalPtr(E)) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000370 PtrRef = GetFinalPtr(E);
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000371
372#ifdef DEBUG_BACKPATCH
373 llvm::cerr << "ReadUintPtr: " << PtrId
374 << " <-- " << (void*) GetFinalPtr(E) << '\n';
375#endif
376 }
Ted Kremenek5973ef42007-10-28 21:17:59 +0000377 else {
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000378 assert (AllowBackpatch &&
379 "Client forbids backpatching for this pointer.");
380
Ted Kremenek38afd9e2007-11-14 08:05:03 +0000381#ifdef DEBUG_BACKPATCH
382 llvm::cerr << "ReadUintPtr: " << PtrId << " (NO PTR YET)\n";
383#endif
384
Ted Kremenek5973ef42007-10-28 21:17:59 +0000385 // Register backpatch. Check the freelist for a BPNode.
386 BPNode* N;
387
388 if (FreeList) {
389 N = FreeList;
390 FreeList = FreeList->Next;
391 }
392 else // No available BPNode. Allocate one.
393 N = (BPNode*) Allocator.Allocate<BPNode>();
394
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000395 new (N) BPNode(GetBPNode(E),PtrRef);
396 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000397 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000398}
399
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000400uintptr_t Deserializer::ReadInternalRefPtr() {
Ted Kremenekec8cd062007-11-08 19:50:46 +0000401 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000402
403 assert (PtrId != 0 && "References cannot refer the NULL address.");
404
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000405 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000406
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000407 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000408 "Cannot backpatch references. Object must be already deserialized.");
409
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000410 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000411}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000412
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000413void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000414 BPNode* Last = NULL;
415
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000416 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000417 Last = N;
418 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000419 }
420
Ted Kremenek5973ef42007-10-28 21:17:59 +0000421 if (Last) {
422 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000423 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000424 }
425
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000426 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000427}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000428
Ted Kremenek5973ef42007-10-28 21:17:59 +0000429
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000430#define INT_READ(TYPE)\
431void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000432 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000433
434INT_READ(bool)
435INT_READ(unsigned char)
436INT_READ(unsigned short)
437INT_READ(unsigned int)
438INT_READ(unsigned long)
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000439
440#define SINT_READ(TYPE)\
441void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
442 X = (TYPE) D.ReadSInt(); }
443
444INT_READ(signed char)
445INT_READ(signed short)
446INT_READ(signed int)
447INT_READ(signed long)