31d180ff32e297a6b41273acea4ec7694e763d9f
[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 using namespace llvm;
17
18 Deserializer::Deserializer(BitstreamReader& stream)
19   : Stream(stream), RecIdx(0), FreeList(NULL) {
20 }
21
22 Deserializer::~Deserializer() {
23   assert (RecIdx >= Record.size() && 
24           "Still scanning bitcode record when deserialization completed.");
25  
26 #ifdef NDEBUG
27   for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
28     assert (I->first.hasFinalPtr() &&
29             "Some pointers were not backpatched.");
30 #endif
31 }
32
33
34 bool 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;
44 }
45
46 void Deserializer::ReadRecord() {
47   // FIXME: Check if we haven't run off the edge of the stream.
48   // FIXME: Handle abbreviations.
49
50   unsigned Code;
51
52   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   
72   assert (Record.size() == 0);  
73   Stream.ReadRecord(Code,Record);  
74   assert (Record.size() > 0);
75 }
76
77 uint64_t Deserializer::ReadInt() {
78   // FIXME: Any error recovery/handling with incomplete or bad files?
79   if (!inRecord())
80     ReadRecord();
81
82   return Record[RecIdx++];
83 }
84
85 char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
86   if (cstr == NULL)
87     MaxLen = 0; // Zero this just in case someone does something funny.
88   
89   unsigned len = ReadInt();
90
91   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)
99     cstr[i] = (char) ReadInt();
100   
101   if (isNullTerm)
102     cstr[len+1] = '\0';
103   
104   return cstr;
105 }
106
107 void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
108   unsigned len = ReadInt();
109
110   buff.clear();  
111   buff.reserve(len);
112   
113   for (unsigned i = 0; i < len; ++i)
114     buff.push_back((char) ReadInt());
115   
116   if (isNullTerm)
117     buff.push_back('\0');
118 }
119
120 void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
121   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
122   
123   assert (!HasFinalPtr(E) && "Pointer already registered.");
124
125   SetPtr(E,Ptr);
126 }
127
128 void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
129   unsigned PtrId = ReadInt();
130   
131   if (PtrId == 0) {
132     PtrRef = 0;
133     return;
134   }  
135
136   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
137   
138   if (HasFinalPtr(E))
139     PtrRef = GetFinalPtr(E);
140   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     
151     new (N) BPNode(GetBPNode(E),PtrRef);
152     SetBPNode(E,N);
153   }
154 }
155
156 uintptr_t Deserializer::ReadInternalRefPtr() {
157   unsigned PtrId = ReadInt();
158   
159   assert (PtrId != 0 && "References cannot refer the NULL address.");
160
161   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
162   
163   assert (HasFinalPtr(E) &&
164           "Cannot backpatch references.  Object must be already deserialized.");
165   
166   return GetFinalPtr(E);
167 }
168
169 void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
170   BPNode* Last = NULL;
171   
172   for (BPNode* N = Head; N != NULL; N=N->Next) {
173     Last = N;
174     N->PtrRef |= reinterpret_cast<uintptr_t>(P);
175   }
176   
177   if (Last) {
178     Last->Next = FreeList;
179     FreeList = Head;
180   }
181   
182   Ptr = const_cast<void*>(P);
183 }
184
185
186 #define INT_READ(TYPE)\
187 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
188   X = (TYPE) D.ReadInt(); }
189
190 INT_READ(bool)
191 INT_READ(unsigned char)
192 INT_READ(unsigned short)
193 INT_READ(unsigned int)
194 INT_READ(unsigned long)