blob: 012c815b435103e48a6afffcd7a1e7321d7b12e1 [file] [log] [blame]
Ted Kremenekbe1a0262007-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 Kremenek03a89f82007-10-24 19:06:40 +000014#include "llvm/Bitcode/Deserialize.h"
Ted Kremenekbe1a0262007-10-23 21:29:33 +000015
Ted Kremenekfd2f7e72007-11-06 19:49:16 +000016#ifdef DEBUG_BACKPATCH
17#include "llvm/Support/Streams.h"
18#endif
19
Ted Kremenekbe1a0262007-10-23 21:29:33 +000020using namespace llvm;
21
22Deserializer::Deserializer(BitstreamReader& stream)
Ted Kremenek9493bb32007-11-09 00:43:51 +000023 : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
Ted Kremenekbe1a0262007-10-23 21:29:33 +000024}
25
26Deserializer::~Deserializer() {
27 assert (RecIdx >= Record.size() &&
28 "Still scanning bitcode record when deserialization completed.");
Ted Kremenek44a871e2007-10-28 23:38:38 +000029
Ted Kremenek9493bb32007-11-09 00:43:51 +000030#ifdef DEBUG_BACKPATCH
Ted Kremenek44a871e2007-10-28 23:38:38 +000031 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek9eeccd92007-11-01 00:57:37 +000032 assert (I->first.hasFinalPtr() &&
Ted Kremenek44a871e2007-10-28 23:38:38 +000033 "Some pointers were not backpatched.");
34#endif
Ted Kremenekfd635912007-10-25 00:10:21 +000035}
36
37
38bool Deserializer::inRecord() {
39 if (Record.size() > 0) {
40 if (RecIdx >= Record.size()) {
41 RecIdx = 0;
42 Record.clear();
Ted Kremenek9493bb32007-11-09 00:43:51 +000043 AbbrevNo = 0;
Ted Kremenekfd635912007-10-25 00:10:21 +000044 return false;
45 }
Ted Kremenek9493bb32007-11-09 00:43:51 +000046 else
47 return true;
Ted Kremenekfd635912007-10-25 00:10:21 +000048 }
Ted Kremenek9493bb32007-11-09 00:43:51 +000049
50 return false;
51}
52
53bool Deserializer::AdvanceStream() {
54 assert (!inRecord() &&
55 "Cannot advance stream. Still processing a record.");
56
57 if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
58 AbbrevNo >= bitc::UNABBREV_RECORD)
59 return true;
60
61 while (!Stream.AtEndOfStream()) {
62
63 AbbrevNo = Stream.ReadCode();
64
65 switch (AbbrevNo) {
66 case bitc::ENTER_SUBBLOCK: {
67 unsigned id = Stream.ReadSubBlockID();
68 BlockStack.push_back(std::make_pair(Stream.GetCurrentBitNo(),id));
69 break;
70 }
71
72 case bitc::END_BLOCK: {
73 bool x = Stream.ReadBlockEnd();
74 assert (!x && "Error at block end.");
75 BlockStack.pop_back();
76 continue;
77 }
78
79 case bitc::DEFINE_ABBREV:
80 Stream.ReadAbbrevRecord();
81 continue;
82
83 default:
84 break;
85 }
86
87 return true;
88 }
89
90 return false;
Ted Kremenekbe1a0262007-10-23 21:29:33 +000091}
92
93void Deserializer::ReadRecord() {
Ted Kremenek6fcfdf52007-11-05 21:36:35 +000094
Ted Kremenek9493bb32007-11-09 00:43:51 +000095 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
96 assert (!BlockStack.empty());
97 Stream.EnterSubBlock(BlockStack.back().second);
98 AbbrevNo = 0;
Ted Kremeneka23f9db2007-11-05 20:47:27 +000099 }
Ted Kremenek9493bb32007-11-09 00:43:51 +0000100
101 if (Stream.AtEndOfStream())
102 return;
Ted Kremeneka23f9db2007-11-05 20:47:27 +0000103
Ted Kremenek9493bb32007-11-09 00:43:51 +0000104 assert (Record.size() == 0);
105 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
106 RecordCode = Stream.ReadRecord(AbbrevNo,Record);
107 assert (Record.size() > 0);
Ted Kremenek6fcfdf52007-11-05 21:36:35 +0000108}
109
Ted Kremenek9493bb32007-11-09 00:43:51 +0000110void Deserializer::SkipBlock() {
111 assert (!inRecord());
112 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
113 Stream.SkipBlock();
114 AbbrevNo = 0;
115}
116
117Deserializer::Location Deserializer::getCurrentBlockLocation() {
Ted Kremenekebfbcaa2007-11-08 19:50:46 +0000118 if (!inRecord())
Ted Kremenek9493bb32007-11-09 00:43:51 +0000119 AdvanceStream();
Ted Kremenekebfbcaa2007-11-08 19:50:46 +0000120
Ted Kremenek9493bb32007-11-09 00:43:51 +0000121 return BlockStack.back().first;
122}
123
124unsigned Deserializer::getCurrentBlockID() {
125 if (!inRecord())
126 AdvanceStream();
127
128 return BlockStack.back().second;
129}
130
131unsigned Deserializer::getRecordCode() {
132 if (!inRecord()) {
133 AdvanceStream();
134 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
135 ReadRecord();
136 }
137
138 return RecordCode;
Ted Kremenekebfbcaa2007-11-08 19:50:46 +0000139}
140
141bool Deserializer::FinishedBlock(Location BlockLoc) {
142 if (!inRecord())
Ted Kremenek9493bb32007-11-09 00:43:51 +0000143 AdvanceStream();
144
145 for (llvm::SmallVector<std::pair<Location,unsigned>,5>::reverse_iterator
146 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
147 if (I->first == BlockLoc)
148 return false;
Ted Kremenekebfbcaa2007-11-08 19:50:46 +0000149
150 return true;
151}
152
Ted Kremenek9493bb32007-11-09 00:43:51 +0000153unsigned Deserializer::getAbbrevNo() {
154 if (!inRecord())
155 AdvanceStream();
156
157 return AbbrevNo;
158}
159
Ted Kremenek6fcfdf52007-11-05 21:36:35 +0000160bool Deserializer::AtEnd() {
161 if (inRecord())
162 return false;
163
Ted Kremenek9493bb32007-11-09 00:43:51 +0000164 if (!AdvanceStream())
165 return true;
Ted Kremenek6fcfdf52007-11-05 21:36:35 +0000166
Ted Kremenek9493bb32007-11-09 00:43:51 +0000167 return false;
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000168}
169
Ted Kremenek03a89f82007-10-24 19:06:40 +0000170uint64_t Deserializer::ReadInt() {
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000171 // FIXME: Any error recovery/handling with incomplete or bad files?
172 if (!inRecord())
173 ReadRecord();
174
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000175 return Record[RecIdx++];
176}
177
Ted Kremenekcd0c3202007-11-07 18:24:34 +0000178int64_t Deserializer::ReadSInt() {
179 uint64_t x = ReadInt();
180 int64_t magnitude = x >> 1;
181 return x & 0x1 ? -magnitude : magnitude;
182}
183
Ted Kremenek03a89f82007-10-24 19:06:40 +0000184char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000185 if (cstr == NULL)
186 MaxLen = 0; // Zero this just in case someone does something funny.
187
Ted Kremenek03a89f82007-10-24 19:06:40 +0000188 unsigned len = ReadInt();
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000189
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000190 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
191
192 if (!cstr)
193 cstr = new char[len + (isNullTerm ? 1 : 0)];
194
195 assert (cstr != NULL);
196
197 for (unsigned i = 0; i < len; ++i)
Ted Kremenek03a89f82007-10-24 19:06:40 +0000198 cstr[i] = (char) ReadInt();
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000199
200 if (isNullTerm)
201 cstr[len+1] = '\0';
202
203 return cstr;
204}
205
Ted Kremenek03a89f82007-10-24 19:06:40 +0000206void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
207 unsigned len = ReadInt();
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000208
Ted Kremenek03a89f82007-10-24 19:06:40 +0000209 buff.clear();
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000210 buff.reserve(len);
211
212 for (unsigned i = 0; i < len; ++i)
Ted Kremenek03a89f82007-10-24 19:06:40 +0000213 buff.push_back((char) ReadInt());
Ted Kremenekbe1a0262007-10-23 21:29:33 +0000214
215 if (isNullTerm)
216 buff.push_back('\0');
217}
Ted Kremenek03a89f82007-10-24 19:06:40 +0000218
Ted Kremenekaa059b12007-10-31 22:42:03 +0000219void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000220 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
221
222 assert (!HasFinalPtr(E) && "Pointer already registered.");
223
Ted Kremenekfd2f7e72007-11-06 19:49:16 +0000224#ifdef DEBUG_BACKPATCH
225 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
226#endif
227
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000228 SetPtr(E,Ptr);
Ted Kremenekfd635912007-10-25 00:10:21 +0000229}
230
Ted Kremenekb4d87192007-11-06 22:21:14 +0000231void Deserializer::ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch) {
Ted Kremenekebfbcaa2007-11-08 19:50:46 +0000232 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenekfd635912007-10-25 00:10:21 +0000233
Ted Kremenekf40b6032007-10-25 18:42:52 +0000234 if (PtrId == 0) {
Ted Kremenek33ca2342007-10-29 18:43:39 +0000235 PtrRef = 0;
Ted Kremenekf40b6032007-10-25 18:42:52 +0000236 return;
Ted Kremenekfd2f7e72007-11-06 19:49:16 +0000237 }
238
239#ifdef DEBUG_BACKPATCH
240 llvm::cerr << "ReadUintPtr: " << PtrId << "\n";
241#endif
242
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000243 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekf40b6032007-10-25 18:42:52 +0000244
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000245 if (HasFinalPtr(E))
246 PtrRef = GetFinalPtr(E);
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000247 else {
Ted Kremenekb4d87192007-11-06 22:21:14 +0000248 assert (AllowBackpatch &&
249 "Client forbids backpatching for this pointer.");
250
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000251 // Register backpatch. Check the freelist for a BPNode.
252 BPNode* N;
253
254 if (FreeList) {
255 N = FreeList;
256 FreeList = FreeList->Next;
257 }
258 else // No available BPNode. Allocate one.
259 N = (BPNode*) Allocator.Allocate<BPNode>();
260
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000261 new (N) BPNode(GetBPNode(E),PtrRef);
262 SetBPNode(E,N);
Ted Kremenekfd635912007-10-25 00:10:21 +0000263 }
Ted Kremenekfd635912007-10-25 00:10:21 +0000264}
265
Ted Kremenek0fb10e42007-10-31 19:58:32 +0000266uintptr_t Deserializer::ReadInternalRefPtr() {
Ted Kremenekebfbcaa2007-11-08 19:50:46 +0000267 SerializedPtrID PtrId = ReadPtrID();
Ted Kremenek0fb10e42007-10-31 19:58:32 +0000268
269 assert (PtrId != 0 && "References cannot refer the NULL address.");
270
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000271 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek0fb10e42007-10-31 19:58:32 +0000272
Ted Kremeneka23f9db2007-11-05 20:47:27 +0000273 assert (HasFinalPtr(E) &&
Ted Kremenek0fb10e42007-10-31 19:58:32 +0000274 "Cannot backpatch references. Object must be already deserialized.");
275
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000276 return GetFinalPtr(E);
Ted Kremenek0fb10e42007-10-31 19:58:32 +0000277}
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000278
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000279void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000280 BPNode* Last = NULL;
281
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000282 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000283 Last = N;
284 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfd635912007-10-25 00:10:21 +0000285 }
286
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000287 if (Last) {
288 Last->Next = FreeList;
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000289 FreeList = Head;
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000290 }
291
Ted Kremenek9eeccd92007-11-01 00:57:37 +0000292 Ptr = const_cast<void*>(P);
Ted Kremenekfd635912007-10-25 00:10:21 +0000293}
Ted Kremenek03a89f82007-10-24 19:06:40 +0000294
Ted Kremenek1ad8ec32007-10-28 21:17:59 +0000295
Ted Kremenek03a89f82007-10-24 19:06:40 +0000296#define INT_READ(TYPE)\
297void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekdb74f8e2007-11-01 22:23:34 +0000298 X = (TYPE) D.ReadInt(); }
Ted Kremenek03a89f82007-10-24 19:06:40 +0000299
300INT_READ(bool)
301INT_READ(unsigned char)
302INT_READ(unsigned short)
303INT_READ(unsigned int)
304INT_READ(unsigned long)
Ted Kremenekcd0c3202007-11-07 18:24:34 +0000305
306#define SINT_READ(TYPE)\
307void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
308 X = (TYPE) D.ReadSInt(); }
309
310INT_READ(signed char)
311INT_READ(signed short)
312INT_READ(signed int)
313INT_READ(signed long)