blob: 99cb5d2e3abe1af8ce53834f2d8b418dc55c75b3 [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 Kremenek5973ef42007-10-28 21:17:59 +000023 : Stream(stream), RecIdx(0), FreeList(NULL) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000024}
25
26Deserializer::~Deserializer() {
27 assert (RecIdx >= Record.size() &&
28 "Still scanning bitcode record when deserialization completed.");
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000029
30#ifdef NDEBUG
31 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek066ff5b2007-11-01 00:57:37 +000032 assert (I->first.hasFinalPtr() &&
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000033 "Some pointers were not backpatched.");
34#endif
Ted Kremenekfe2a0122007-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();
43 return false;
44 }
45 else return true;
46 }
47 else return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000048}
49
50void Deserializer::ReadRecord() {
51 // FIXME: Check if we haven't run off the edge of the stream.
52 // FIXME: Handle abbreviations.
Ted Kremenek6e9b4962007-10-24 19:06:40 +000053
Ted Kremenek0a6d98e2007-11-05 21:36:35 +000054 assert (Record.size() == 0);
55
Ted Kremenek14ac17e2007-11-05 20:47:27 +000056 unsigned Code;
Ted Kremenek6e9b4962007-10-24 19:06:40 +000057
Ted Kremenek14ac17e2007-11-05 20:47:27 +000058 while (true) {
59
Ted Kremenek0a6d98e2007-11-05 21:36:35 +000060 if (Stream.AtEndOfStream())
61 return;
62
Ted Kremenek14ac17e2007-11-05 20:47:27 +000063 Code = Stream.ReadCode();
64
65 if (Code == bitc::ENTER_SUBBLOCK) {
66 // No known subblocks, always skip them.
67 unsigned id = Stream.ReadSubBlockID();
68 Stream.EnterSubBlock(id);
69 continue;
70 }
71
72 if (Code == bitc::END_BLOCK) {
73 bool x = Stream.ReadBlockEnd();
74 assert (!x && "Error at block end.");
75 continue;
76 }
77
Ted Kremenek26e25b32007-11-06 19:49:16 +000078 if (Code == bitc::DEFINE_ABBREV) {
79 Stream.ReadAbbrevRecord();
80 continue;
81 }
82
Ted Kremenek14ac17e2007-11-05 20:47:27 +000083 break;
84 }
85
Ted Kremenek6e9b4962007-10-24 19:06:40 +000086 assert (Record.size() == 0);
87 Stream.ReadRecord(Code,Record);
Ted Kremenek0a6d98e2007-11-05 21:36:35 +000088 assert (Record.size() > 0 || Stream.AtEndOfStream());
89}
90
91bool Deserializer::AtEnd() {
92 if (inRecord())
93 return false;
94
95 ReadRecord();
96
97 return Stream.AtEndOfStream();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000098}
99
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000100uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000101 // FIXME: Any error recovery/handling with incomplete or bad files?
102 if (!inRecord())
103 ReadRecord();
104
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000105 return Record[RecIdx++];
106}
107
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000108int64_t Deserializer::ReadSInt() {
109 uint64_t x = ReadInt();
110 int64_t magnitude = x >> 1;
111 return x & 0x1 ? -magnitude : magnitude;
112}
113
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000114char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000115 if (cstr == NULL)
116 MaxLen = 0; // Zero this just in case someone does something funny.
117
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000118 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000119
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000120 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
121
122 if (!cstr)
123 cstr = new char[len + (isNullTerm ? 1 : 0)];
124
125 assert (cstr != NULL);
126
127 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000128 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000129
130 if (isNullTerm)
131 cstr[len+1] = '\0';
132
133 return cstr;
134}
135
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000136void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
137 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000138
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000139 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000140 buff.reserve(len);
141
142 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000143 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000144
145 if (isNullTerm)
146 buff.push_back('\0');
147}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000148
Ted Kremeneka7963a52007-10-31 22:42:03 +0000149void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000150 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
151
152 assert (!HasFinalPtr(E) && "Pointer already registered.");
153
Ted Kremenek26e25b32007-11-06 19:49:16 +0000154#ifdef DEBUG_BACKPATCH
155 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
156#endif
157
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000158 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000159}
160
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000161void Deserializer::ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch) {
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000162 unsigned PtrId = ReadInt();
163
Ted Kremenek2423e032007-10-25 18:42:52 +0000164 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000165 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000166 return;
Ted Kremenek26e25b32007-11-06 19:49:16 +0000167 }
168
169#ifdef DEBUG_BACKPATCH
170 llvm::cerr << "ReadUintPtr: " << PtrId << "\n";
171#endif
172
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000173 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000174
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000175 if (HasFinalPtr(E))
176 PtrRef = GetFinalPtr(E);
Ted Kremenek5973ef42007-10-28 21:17:59 +0000177 else {
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000178 assert (AllowBackpatch &&
179 "Client forbids backpatching for this pointer.");
180
Ted Kremenek5973ef42007-10-28 21:17:59 +0000181 // Register backpatch. Check the freelist for a BPNode.
182 BPNode* N;
183
184 if (FreeList) {
185 N = FreeList;
186 FreeList = FreeList->Next;
187 }
188 else // No available BPNode. Allocate one.
189 N = (BPNode*) Allocator.Allocate<BPNode>();
190
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000191 new (N) BPNode(GetBPNode(E),PtrRef);
192 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000193 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000194}
195
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000196uintptr_t Deserializer::ReadInternalRefPtr() {
197 unsigned PtrId = ReadInt();
198
199 assert (PtrId != 0 && "References cannot refer the NULL address.");
200
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000201 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000202
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000203 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000204 "Cannot backpatch references. Object must be already deserialized.");
205
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000206 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000207}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000208
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000209void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000210 BPNode* Last = NULL;
211
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000212 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000213 Last = N;
214 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000215 }
216
Ted Kremenek5973ef42007-10-28 21:17:59 +0000217 if (Last) {
218 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000219 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000220 }
221
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000222 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000223}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000224
Ted Kremenek5973ef42007-10-28 21:17:59 +0000225
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000226#define INT_READ(TYPE)\
227void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000228 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000229
230INT_READ(bool)
231INT_READ(unsigned char)
232INT_READ(unsigned short)
233INT_READ(unsigned int)
234INT_READ(unsigned long)
Ted Kremenek2e6452c2007-11-07 18:24:34 +0000235
236#define SINT_READ(TYPE)\
237void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
238 X = (TYPE) D.ReadSInt(); }
239
240INT_READ(signed char)
241INT_READ(signed short)
242INT_READ(signed int)
243INT_READ(signed long)