Implemented prototype serialization of pointers, including support
[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) {
20 }
21
22 Deserializer::~Deserializer() {
23   assert (RecIdx >= Record.size() && 
24           "Still scanning bitcode record when deserialization completed.");
25   
26   BackpatchPointers();
27 }
28
29
30 bool Deserializer::inRecord() {
31   if (Record.size() > 0) {
32     if (RecIdx >= Record.size()) {
33       RecIdx = 0;
34       Record.clear();
35       return false;
36     }
37     else return true;
38   }
39   else return false;
40 }
41
42 void Deserializer::ReadRecord() {
43   // FIXME: Check if we haven't run off the edge of the stream.
44   // FIXME: Handle abbreviations.
45
46   // FIXME: Check for the correct code.
47   unsigned Code = Stream.ReadCode();
48
49   assert (Record.size() == 0);  
50   Stream.ReadRecord(Code,Record);  
51   assert (Record.size() > 0);
52 }
53
54 uint64_t Deserializer::ReadInt() {
55   // FIXME: Any error recovery/handling with incomplete or bad files?
56   if (!inRecord())
57     ReadRecord();
58
59   return Record[RecIdx++];
60 }
61
62 char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
63   if (cstr == NULL)
64     MaxLen = 0; // Zero this just in case someone does something funny.
65   
66   unsigned len = ReadInt();
67
68   assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
69
70   if (!cstr)
71     cstr = new char[len + (isNullTerm ? 1 : 0)];
72   
73   assert (cstr != NULL);
74   
75   for (unsigned i = 0; i < len; ++i)
76     cstr[i] = (char) ReadInt();
77   
78   if (isNullTerm)
79     cstr[len+1] = '\0';
80   
81   return cstr;
82 }
83
84 void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
85   unsigned len = ReadInt();
86
87   buff.clear();  
88   buff.reserve(len);
89   
90   for (unsigned i = 0; i < len; ++i)
91     buff.push_back((char) ReadInt());
92   
93   if (isNullTerm)
94     buff.push_back('\0');
95 }
96
97 void Deserializer::RegisterPtr(unsigned PtrId,void* Ptr) {
98   BPatchEntry& E = BPatchMap[PtrId];
99   assert (E.Ptr == NULL && "Pointer already registered.");
100   E.Ptr = Ptr;
101 }
102
103 void Deserializer::ReadPtr(void*& PtrRef) {
104   unsigned PtrId = ReadInt();
105   
106   BPatchEntry& E = BPatchMap[PtrId];
107   
108   if (E.Ptr == NULL) {
109     // Register backpatch.
110     void* P = Allocator.Allocate<BPatchNode>();    
111     E.Head = new (P) BPatchNode(E.Head,PtrRef);
112   }
113   else
114     PtrRef = E.Ptr;
115 }
116
117 void Deserializer::BackpatchPointers() {
118   for (MapTy::iterator I=BPatchMap.begin(),E=BPatchMap.end(); I!=E; ++I) {
119     
120     BPatchEntry& E = I->second;
121     assert (E.Ptr && "No pointer found for backpatch.");
122     
123     for (BPatchNode* N = E.Head; N != NULL; N = N->Next)
124       N->PtrRef = E.Ptr;
125     
126     E.Head = NULL;
127   }
128   
129   Allocator.Reset();
130 }
131
132 #define INT_READ(TYPE)\
133 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
134   X = (TYPE) D.ReadInt(); }\
135 TYPE SerializeTrait<TYPE>::ReadVal(Deserializer& D) {\
136   return (TYPE) D.ReadInt(); }
137
138 INT_READ(bool)
139 INT_READ(unsigned char)
140 INT_READ(unsigned short)
141 INT_READ(unsigned int)
142 INT_READ(unsigned long)