5642f37fac5d2abb7777c82bd91d6f2dd468256e
[oota-llvm.git] / lib / Bitcode / Reader / Deserialize.cpp
1 //==- 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
14 #include "llvm/Bitcode/Deserialize.h"
15
16 #ifdef DEBUG_BACKPATCH
17 #include "llvm/Support/Streams.h"
18 #endif
19
20 using namespace llvm;
21
22 Deserializer::Deserializer(BitstreamReader& stream)
23   : Stream(stream), RecIdx(0), FreeList(NULL) {
24 }
25
26 Deserializer::~Deserializer() {
27   assert (RecIdx >= Record.size() && 
28           "Still scanning bitcode record when deserialization completed.");
29  
30 #ifdef NDEBUG
31   for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
32     assert (I->first.hasFinalPtr() &&
33             "Some pointers were not backpatched.");
34 #endif
35 }
36
37
38 bool 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;
48 }
49
50 void Deserializer::ReadRecord() {
51   // FIXME: Check if we haven't run off the edge of the stream.
52   // FIXME: Handle abbreviations.
53
54   assert (Record.size() == 0);
55   
56   unsigned Code;
57
58   while (true) {
59     
60     if (Stream.AtEndOfStream())
61       return;
62     
63     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     
78     if (Code == bitc::DEFINE_ABBREV) {
79       Stream.ReadAbbrevRecord();
80       continue;
81     }
82     
83     break;
84   }
85   
86   assert (Record.size() == 0);  
87   Stream.ReadRecord(Code,Record);  
88   assert (Record.size() > 0 || Stream.AtEndOfStream());
89 }
90
91 bool Deserializer::AtEnd() {
92   if (inRecord())
93     return false;
94   
95   ReadRecord();
96   
97   return Stream.AtEndOfStream();
98 }
99
100 uint64_t Deserializer::ReadInt() {
101   // FIXME: Any error recovery/handling with incomplete or bad files?
102   if (!inRecord())
103     ReadRecord();
104
105   return Record[RecIdx++];
106 }
107
108 char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
109   if (cstr == NULL)
110     MaxLen = 0; // Zero this just in case someone does something funny.
111   
112   unsigned len = ReadInt();
113
114   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)
122     cstr[i] = (char) ReadInt();
123   
124   if (isNullTerm)
125     cstr[len+1] = '\0';
126   
127   return cstr;
128 }
129
130 void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
131   unsigned len = ReadInt();
132
133   buff.clear();  
134   buff.reserve(len);
135   
136   for (unsigned i = 0; i < len; ++i)
137     buff.push_back((char) ReadInt());
138   
139   if (isNullTerm)
140     buff.push_back('\0');
141 }
142
143 void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
144   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
145   
146   assert (!HasFinalPtr(E) && "Pointer already registered.");
147
148 #ifdef DEBUG_BACKPATCH
149   llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
150 #endif 
151   
152   SetPtr(E,Ptr);
153 }
154
155 void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
156   unsigned PtrId = ReadInt();
157   
158   if (PtrId == 0) {
159     PtrRef = 0;
160     return;
161   }
162   
163 #ifdef DEBUG_BACKPATCH
164   llvm::cerr << "ReadUintPtr: " << PtrId << "\n";
165 #endif
166   
167   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
168   
169   if (HasFinalPtr(E))
170     PtrRef = GetFinalPtr(E);
171   else {
172     // Register backpatch.  Check the freelist for a BPNode.
173     BPNode* N;
174
175     if (FreeList) {
176       N = FreeList;
177       FreeList = FreeList->Next;
178     }
179     else // No available BPNode.  Allocate one.
180       N = (BPNode*) Allocator.Allocate<BPNode>();
181     
182     new (N) BPNode(GetBPNode(E),PtrRef);
183     SetBPNode(E,N);
184   }
185 }
186
187 uintptr_t Deserializer::ReadInternalRefPtr() {
188   unsigned PtrId = ReadInt();
189   
190   assert (PtrId != 0 && "References cannot refer the NULL address.");
191
192   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
193   
194   assert (HasFinalPtr(E) &&
195           "Cannot backpatch references.  Object must be already deserialized.");
196   
197   return GetFinalPtr(E);
198 }
199
200 void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
201   BPNode* Last = NULL;
202   
203   for (BPNode* N = Head; N != NULL; N=N->Next) {
204     Last = N;
205     N->PtrRef |= reinterpret_cast<uintptr_t>(P);
206   }
207   
208   if (Last) {
209     Last->Next = FreeList;
210     FreeList = Head;
211   }
212   
213   Ptr = const_cast<void*>(P);
214 }
215
216
217 #define INT_READ(TYPE)\
218 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
219   X = (TYPE) D.ReadInt(); }
220
221 INT_READ(bool)
222 INT_READ(unsigned char)
223 INT_READ(unsigned short)
224 INT_READ(unsigned int)
225 INT_READ(unsigned long)