Added support in serializer and deserializer to create arbitrary blocks.
[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   assert (Record.size() == 0);
51   
52   unsigned Code;
53
54   while (true) {
55     
56     if (Stream.AtEndOfStream())
57       return;
58     
59     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   
77   assert (Record.size() == 0);  
78   Stream.ReadRecord(Code,Record);  
79   assert (Record.size() > 0 || Stream.AtEndOfStream());
80 }
81
82 bool Deserializer::AtEnd() {
83   if (inRecord())
84     return false;
85   
86   ReadRecord();
87   
88   return Stream.AtEndOfStream();
89 }
90
91 uint64_t Deserializer::ReadInt() {
92   // FIXME: Any error recovery/handling with incomplete or bad files?
93   if (!inRecord())
94     ReadRecord();
95
96   return Record[RecIdx++];
97 }
98
99 char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
100   if (cstr == NULL)
101     MaxLen = 0; // Zero this just in case someone does something funny.
102   
103   unsigned len = ReadInt();
104
105   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)
113     cstr[i] = (char) ReadInt();
114   
115   if (isNullTerm)
116     cstr[len+1] = '\0';
117   
118   return cstr;
119 }
120
121 void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
122   unsigned len = ReadInt();
123
124   buff.clear();  
125   buff.reserve(len);
126   
127   for (unsigned i = 0; i < len; ++i)
128     buff.push_back((char) ReadInt());
129   
130   if (isNullTerm)
131     buff.push_back('\0');
132 }
133
134 void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
135   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
136   
137   assert (!HasFinalPtr(E) && "Pointer already registered.");
138
139   SetPtr(E,Ptr);
140 }
141
142 void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
143   unsigned PtrId = ReadInt();
144   
145   if (PtrId == 0) {
146     PtrRef = 0;
147     return;
148   }  
149
150   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
151   
152   if (HasFinalPtr(E))
153     PtrRef = GetFinalPtr(E);
154   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     
165     new (N) BPNode(GetBPNode(E),PtrRef);
166     SetBPNode(E,N);
167   }
168 }
169
170 uintptr_t Deserializer::ReadInternalRefPtr() {
171   unsigned PtrId = ReadInt();
172   
173   assert (PtrId != 0 && "References cannot refer the NULL address.");
174
175   MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
176   
177   assert (HasFinalPtr(E) &&
178           "Cannot backpatch references.  Object must be already deserialized.");
179   
180   return GetFinalPtr(E);
181 }
182
183 void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
184   BPNode* Last = NULL;
185   
186   for (BPNode* N = Head; N != NULL; N=N->Next) {
187     Last = N;
188     N->PtrRef |= reinterpret_cast<uintptr_t>(P);
189   }
190   
191   if (Last) {
192     Last->Next = FreeList;
193     FreeList = Head;
194   }
195   
196   Ptr = const_cast<void*>(P);
197 }
198
199
200 #define INT_READ(TYPE)\
201 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
202   X = (TYPE) D.ReadInt(); }
203
204 INT_READ(bool)
205 INT_READ(unsigned char)
206 INT_READ(unsigned short)
207 INT_READ(unsigned int)
208 INT_READ(unsigned long)