blob: d4ed26b380a42143487a60635f54249a095fd570 [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 Kremenek6e9b4962007-10-24 19:06:40 +0000108char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000109 if (cstr == NULL)
110 MaxLen = 0; // Zero this just in case someone does something funny.
111
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000112 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000113
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000114 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
115
116 if (!cstr)
117 cstr = new char[len + (isNullTerm ? 1 : 0)];
118
119 assert (cstr != NULL);
120
121 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000122 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000123
124 if (isNullTerm)
125 cstr[len+1] = '\0';
126
127 return cstr;
128}
129
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000130void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
131 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000132
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000133 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000134 buff.reserve(len);
135
136 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000137 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000138
139 if (isNullTerm)
140 buff.push_back('\0');
141}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000142
Ted Kremeneka7963a52007-10-31 22:42:03 +0000143void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000144 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
145
146 assert (!HasFinalPtr(E) && "Pointer already registered.");
147
Ted Kremenek26e25b32007-11-06 19:49:16 +0000148#ifdef DEBUG_BACKPATCH
149 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
150#endif
151
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000152 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000153}
154
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000155void Deserializer::ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch) {
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000156 unsigned PtrId = ReadInt();
157
Ted Kremenek2423e032007-10-25 18:42:52 +0000158 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000159 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000160 return;
Ted Kremenek26e25b32007-11-06 19:49:16 +0000161 }
162
163#ifdef DEBUG_BACKPATCH
164 llvm::cerr << "ReadUintPtr: " << PtrId << "\n";
165#endif
166
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000167 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000168
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000169 if (HasFinalPtr(E))
170 PtrRef = GetFinalPtr(E);
Ted Kremenek5973ef42007-10-28 21:17:59 +0000171 else {
Ted Kremenekb12a82d2007-11-06 22:21:14 +0000172 assert (AllowBackpatch &&
173 "Client forbids backpatching for this pointer.");
174
Ted Kremenek5973ef42007-10-28 21:17:59 +0000175 // Register backpatch. Check the freelist for a BPNode.
176 BPNode* N;
177
178 if (FreeList) {
179 N = FreeList;
180 FreeList = FreeList->Next;
181 }
182 else // No available BPNode. Allocate one.
183 N = (BPNode*) Allocator.Allocate<BPNode>();
184
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000185 new (N) BPNode(GetBPNode(E),PtrRef);
186 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000187 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000188}
189
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000190uintptr_t Deserializer::ReadInternalRefPtr() {
191 unsigned PtrId = ReadInt();
192
193 assert (PtrId != 0 && "References cannot refer the NULL address.");
194
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000195 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000196
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000197 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000198 "Cannot backpatch references. Object must be already deserialized.");
199
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000200 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000201}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000202
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000203void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000204 BPNode* Last = NULL;
205
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000206 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000207 Last = N;
208 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000209 }
210
Ted Kremenek5973ef42007-10-28 21:17:59 +0000211 if (Last) {
212 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000213 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000214 }
215
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000216 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000217}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000218
Ted Kremenek5973ef42007-10-28 21:17:59 +0000219
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000220#define INT_READ(TYPE)\
221void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000222 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000223
224INT_READ(bool)
225INT_READ(unsigned char)
226INT_READ(unsigned short)
227INT_READ(unsigned int)
228INT_READ(unsigned long)