blob: 31d180ff32e297a6b41273acea4ec7694e763d9f [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 Kremenek14ac17e2007-11-05 20:47:27 +000050 unsigned Code;
Ted Kremenek6e9b4962007-10-24 19:06:40 +000051
Ted Kremenek14ac17e2007-11-05 20:47:27 +000052 while (true) {
53
54 Code = Stream.ReadCode();
55
56 if (Code == bitc::ENTER_SUBBLOCK) {
57 // No known subblocks, always skip them.
58 unsigned id = Stream.ReadSubBlockID();
59 Stream.EnterSubBlock(id);
60 continue;
61 }
62
63 if (Code == bitc::END_BLOCK) {
64 bool x = Stream.ReadBlockEnd();
65 assert (!x && "Error at block end.");
66 continue;
67 }
68
69 break;
70 }
71
Ted Kremenek6e9b4962007-10-24 19:06:40 +000072 assert (Record.size() == 0);
73 Stream.ReadRecord(Code,Record);
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000074 assert (Record.size() > 0);
75}
76
Ted Kremenek6e9b4962007-10-24 19:06:40 +000077uint64_t Deserializer::ReadInt() {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000078 // FIXME: Any error recovery/handling with incomplete or bad files?
79 if (!inRecord())
80 ReadRecord();
81
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000082 return Record[RecIdx++];
83}
84
Ted Kremenek6e9b4962007-10-24 19:06:40 +000085char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000086 if (cstr == NULL)
87 MaxLen = 0; // Zero this just in case someone does something funny.
88
Ted Kremenek6e9b4962007-10-24 19:06:40 +000089 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000090
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +000091 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
92
93 if (!cstr)
94 cstr = new char[len + (isNullTerm ? 1 : 0)];
95
96 assert (cstr != NULL);
97
98 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +000099 cstr[i] = (char) ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000100
101 if (isNullTerm)
102 cstr[len+1] = '\0';
103
104 return cstr;
105}
106
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000107void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
108 unsigned len = ReadInt();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000109
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000110 buff.clear();
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000111 buff.reserve(len);
112
113 for (unsigned i = 0; i < len; ++i)
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000114 buff.push_back((char) ReadInt());
Ted Kremenek0b2d7aa2007-10-23 21:29:33 +0000115
116 if (isNullTerm)
117 buff.push_back('\0');
118}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000119
Ted Kremeneka7963a52007-10-31 22:42:03 +0000120void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000121 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
122
123 assert (!HasFinalPtr(E) && "Pointer already registered.");
124
125 SetPtr(E,Ptr);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000126}
127
Ted Kremenek5973ef42007-10-28 21:17:59 +0000128void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000129 unsigned PtrId = ReadInt();
130
Ted Kremenek2423e032007-10-25 18:42:52 +0000131 if (PtrId == 0) {
Ted Kremenek8308a482007-10-29 18:43:39 +0000132 PtrRef = 0;
Ted Kremenek2423e032007-10-25 18:42:52 +0000133 return;
134 }
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000135
136 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenek2423e032007-10-25 18:42:52 +0000137
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000138 if (HasFinalPtr(E))
139 PtrRef = GetFinalPtr(E);
Ted Kremenek5973ef42007-10-28 21:17:59 +0000140 else {
141 // Register backpatch. Check the freelist for a BPNode.
142 BPNode* N;
143
144 if (FreeList) {
145 N = FreeList;
146 FreeList = FreeList->Next;
147 }
148 else // No available BPNode. Allocate one.
149 N = (BPNode*) Allocator.Allocate<BPNode>();
150
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000151 new (N) BPNode(GetBPNode(E),PtrRef);
152 SetBPNode(E,N);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000153 }
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000154}
155
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000156uintptr_t Deserializer::ReadInternalRefPtr() {
157 unsigned PtrId = ReadInt();
158
159 assert (PtrId != 0 && "References cannot refer the NULL address.");
160
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000161 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000162
Ted Kremenek14ac17e2007-11-05 20:47:27 +0000163 assert (HasFinalPtr(E) &&
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000164 "Cannot backpatch references. Object must be already deserialized.");
165
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000166 return GetFinalPtr(E);
Ted Kremenekeb9409d2007-10-31 19:58:32 +0000167}
Ted Kremenek5973ef42007-10-28 21:17:59 +0000168
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000169void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000170 BPNode* Last = NULL;
171
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000172 for (BPNode* N = Head; N != NULL; N=N->Next) {
Ted Kremenek5973ef42007-10-28 21:17:59 +0000173 Last = N;
174 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000175 }
176
Ted Kremenek5973ef42007-10-28 21:17:59 +0000177 if (Last) {
178 Last->Next = FreeList;
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000179 FreeList = Head;
Ted Kremenek5973ef42007-10-28 21:17:59 +0000180 }
181
Ted Kremenek066ff5b2007-11-01 00:57:37 +0000182 Ptr = const_cast<void*>(P);
Ted Kremenekfe2a0122007-10-25 00:10:21 +0000183}
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000184
Ted Kremenek5973ef42007-10-28 21:17:59 +0000185
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000186#define INT_READ(TYPE)\
187void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
Ted Kremenekff37ccc2007-11-01 22:23:34 +0000188 X = (TYPE) D.ReadInt(); }
Ted Kremenek6e9b4962007-10-24 19:06:40 +0000189
190INT_READ(bool)
191INT_READ(unsigned char)
192INT_READ(unsigned short)
193INT_READ(unsigned int)
194INT_READ(unsigned long)