blob: ef4e4f7e00004d5f4558a1667b7584a07fb15cd1 [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
16using namespace llvm;
17
18Deserializer::Deserializer(BitstreamReader& stream)
Ted Kremenek5973ef42007-10-28 21:17:59 +000019 : Stream(stream), RecIdx(0), FreeList(NULL) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000020}
21
22Deserializer::~Deserializer() {
23 assert (RecIdx >= Record.size() &&
24 "Still scanning bitcode record when deserialization completed.");
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000025
26#ifdef NDEBUG
27 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
Ted Kremenek066ff5b2007-11-01 00:57:37 +000028 assert (I->first.hasFinalPtr() &&
Ted Kremenekadc9b9c2007-10-28 23:38:38 +000029 "Some pointers were not backpatched.");
30#endif
Ted Kremenekfe2a0122007-10-25 00:10:21 +000031}
32
33
34bool Deserializer::inRecord() {
35 if (Record.size() > 0) {
36 if (RecIdx >= Record.size()) {
37 RecIdx = 0;
38 Record.clear();
39 return false;
40 }
41 else return true;
42 }
43 else return false;
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000044}
45
46void Deserializer::ReadRecord() {
47 // FIXME: Check if we haven't run off the edge of the stream.
48 // FIXME: Handle abbreviations.
Ted Kremenek6e9b4962007-10-24 19:06:40 +000049
Ted Kremenek0a6d98e2007-11-05 21:36:35 +000050 assert (Record.size() == 0);
51
Ted Kremenek14ac17e2007-11-05 20:47:27 +000052 unsigned Code;
Ted Kremenek6e9b4962007-10-24 19:06:40 +000053
Ted Kremenek14ac17e2007-11-05 20:47:27 +000054 while (true) {
55
Ted Kremenek0a6d98e2007-11-05 21:36:35 +000056 if (Stream.AtEndOfStream())
57 return;
58
Ted Kremenek14ac17e2007-11-05 20:47:27 +000059 Code = Stream.ReadCode();
60
61 if (Code == bitc::ENTER_SUBBLOCK) {
62 // No known subblocks, always skip them.
63 unsigned id = Stream.ReadSubBlockID();
64 Stream.EnterSubBlock(id);
65 continue;
66 }
67
68 if (Code == bitc::END_BLOCK) {
69 bool x = Stream.ReadBlockEnd();
70 assert (!x && "Error at block end.");
71 continue;
72 }
73
74 break;
75 }
76
Ted Kremenek6e9b4962007-10-24 19:06:40 +000077 assert (Record.size() == 0);
78 Stream.ReadRecord(Code,Record);
Ted Kremenek0a6d98e2007-11-05 21:36:35 +000079 assert (Record.size() > 0 || Stream.AtEndOfStream());
80}
81
82bool Deserializer::AtEnd() {
83 if (inRecord())
84 return false;
85
86 ReadRecord();
87
88 return Stream.AtEndOfStream();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000089}
90
Ted Kremenek6e9b4962007-10-24 19:06:40 +000091uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000092 // FIXME: Any error recovery/handling with incomplete or bad files?
93 if (!inRecord())
94 ReadRecord();
95
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000096 return Record[RecIdx++];
97}
98
Ted Kremenek6e9b4962007-10-24 19:06:40 +000099char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000100 if (cstr == NULL)
101 MaxLen = 0; // Zero this just in case someone does something funny.
102
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000103 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000104
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000105 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
106
107 if (!cstr)
108 cstr = new char[len + (isNullTerm ? 1 : 0)];
109
110 assert (cstr != NULL);
111
112 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000113 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000114
115 if (isNullTerm)
116 cstr[len+1] = '\0';
117
118 return cstr;
119}
120
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000121void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
122 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000123
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000124 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000125 buff.reserve(len);
126
127 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000128 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000129
130 if (isNullTerm)
131 buff.push_back('\0');
132}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000133
Ted Kremeneka7963a52007-10-31 22:42:03 +0000134void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000135 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
136
137 assert (!HasFinalPtr(E) && "Pointer already registered.");
138
139 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000140}
141
Ted Kremenek5973ef42007-10-28 21:17:59 +0000142void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000143 unsigned PtrId = ReadInt();
144
Ted Kremenek2423e032007-10-25 18:42:52 +0000145 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000146 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000147 return;
148 }
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000149
150 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000151
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000152 if (HasFinalPtr(E))
153 PtrRef = GetFinalPtr(E);
Ted Kremenek5973ef42007-10-28 21:17:59 +0000154 else {
155 // Register backpatch. Check the freelist for a BPNode.
156 BPNode* N;
157
158 if (FreeList) {
159 N = FreeList;
160 FreeList = FreeList->Next;
161 }
162 else // No available BPNode. Allocate one.
163 N = (BPNode*) Allocator.Allocate<BPNode>();
164
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000165 new (N) BPNode(GetBPNode(E),PtrRef);
166 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000167 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000168}
169
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000170uintptr_t Deserializer::ReadInternalRefPtr() {
171 unsigned PtrId = ReadInt();
172
173 assert (PtrId != 0 && "References cannot refer the NULL address.");
174
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000175 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000176
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000177 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000178 "Cannot backpatch references. Object must be already deserialized.");
179
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000180 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000181}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000182
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000183void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000184 BPNode* Last = NULL;
185
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000186 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000187 Last = N;
188 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000189 }
190
Ted Kremenek5973ef42007-10-28 21:17:59 +0000191 if (Last) {
192 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000193 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000194 }
195
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000196 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000197}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000198
Ted Kremenek5973ef42007-10-28 21:17:59 +0000199
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000200#define INT_READ(TYPE)\
201void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000202 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000203
204INT_READ(bool)
205INT_READ(unsigned char)
206INT_READ(unsigned short)
207INT_READ(unsigned int)
208INT_READ(unsigned long)