1 //==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
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.
8 //===----------------------------------------------------------------------===//
10 // This file defines the internal methods used for object serialization.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Bitcode/Deserialize.h"
16 #ifdef DEBUG_BACKPATCH
17 #include "llvm/Support/Streams.h"
22 Deserializer::Deserializer(BitstreamReader& stream)
23 : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
26 if (!AtEnd()) StreamStart = BlockStack.back();
29 Deserializer::~Deserializer() {
30 assert (RecIdx >= Record.size() &&
31 "Still scanning bitcode record when deserialization completed.");
33 #ifdef DEBUG_BACKPATCH
34 for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
35 assert (I->first.hasFinalPtr() &&
36 "Some pointers were not backpatched.");
41 bool Deserializer::inRecord() {
42 if (Record.size() > 0) {
43 if (RecIdx >= Record.size()) {
56 bool Deserializer::AdvanceStream() {
57 assert (!inRecord() &&
58 "Cannot advance stream. Still processing a record.");
60 if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
61 AbbrevNo >= bitc::UNABBREV_RECORD)
64 while (!Stream.AtEndOfStream()) {
66 uint64_t Pos = Stream.GetCurrentBitNo();
67 AbbrevNo = Stream.ReadCode();
70 case bitc::ENTER_SUBBLOCK: {
71 unsigned id = Stream.ReadSubBlockID();
73 // Determine the extent of the block. This is useful for jumping around
74 // the stream. This is hack: we read the header of the block, save
75 // the length, and then revert the bitstream to a location just before
76 // the block is entered.
77 uint64_t BPos = Stream.GetCurrentBitNo();
78 Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
80 unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
81 Stream.JumpToBit(BPos);
83 BlockStack.push_back(Location(Pos,id,NumWords));
87 case bitc::END_BLOCK: {
88 bool x = Stream.ReadBlockEnd();
89 assert (!x && "Error at block end.");
90 BlockStack.pop_back();
94 case bitc::DEFINE_ABBREV:
95 Stream.ReadAbbrevRecord();
108 void Deserializer::ReadRecord() {
110 while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
111 assert (!BlockStack.empty());
112 Stream.EnterSubBlock(BlockStack.back().BlockID);
116 if (Stream.AtEndOfStream())
119 assert (Record.size() == 0);
120 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
121 RecordCode = Stream.ReadRecord(AbbrevNo,Record);
122 assert (Record.size() > 0);
125 void Deserializer::SkipBlock() {
126 assert (!inRecord());
133 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
134 BlockStack.pop_back();
141 bool Deserializer::SkipToBlock(unsigned BlockID) {
142 assert (!inRecord());
145 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
147 unsigned BlockLevel = BlockStack.size();
150 BlockLevel == BlockStack.size() &&
151 getCurrentBlockID() != BlockID)
154 return !(AtEnd() || BlockLevel != BlockStack.size());
157 Deserializer::Location Deserializer::getCurrentBlockLocation() {
161 return BlockStack.back();
164 bool Deserializer::JumpTo(const Location& Loc) {
166 assert (!inRecord());
170 // assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
171 assert (!BlockStack.empty());
173 uint64_t LastBPos = StreamStart.BitNo;
175 while (!BlockStack.empty()) {
177 LastBPos = BlockStack.back().BitNo;
179 // Determine of the current block contains the location of the block
180 // we are looking for.
181 if (BlockStack.back().contains(Loc)) {
182 // We found the enclosing block. We must first POP it off to
183 // destroy any accumulated context within the block scope. We then
184 // jump to the position of the block and enter it.
185 Stream.JumpToBit(LastBPos);
186 BlockStack.pop_back();
187 Stream.PopBlockScope();
191 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
193 Stream.EnterSubBlock(BlockStack.back().BlockID);
197 // This block does not contain the block we are looking for. Pop it.
198 BlockStack.pop_back();
199 Stream.PopBlockScope();
202 // Check if we have popped our way to the outermost scope. If so,
203 // we need to adjust our position.
204 if (BlockStack.empty()) {
205 Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart.BitNo : LastBPos);
210 assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
211 assert (!BlockStack.empty());
213 while (!AtEnd() && BlockStack.back() != Loc) {
214 if (BlockStack.back().contains(Loc)) {
215 Stream.EnterSubBlock(BlockStack.back().BlockID);
227 assert (BlockStack.back() == Loc);
232 unsigned Deserializer::getCurrentBlockID() {
236 return BlockStack.back().BlockID;
239 unsigned Deserializer::getRecordCode() {
242 assert (AbbrevNo >= bitc::UNABBREV_RECORD);
249 bool Deserializer::FinishedBlock(Location BlockLoc) {
253 for (llvm::SmallVector<Location,8>::reverse_iterator
254 I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
261 unsigned Deserializer::getAbbrevNo() {
268 bool Deserializer::AtEnd() {
272 if (!AdvanceStream())
278 uint64_t Deserializer::ReadInt() {
279 // FIXME: Any error recovery/handling with incomplete or bad files?
283 return Record[RecIdx++];
286 int64_t Deserializer::ReadSInt() {
287 uint64_t x = ReadInt();
288 int64_t magnitude = x >> 1;
289 return x & 0x1 ? -magnitude : magnitude;
292 char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
294 MaxLen = 0; // Zero this just in case someone does something funny.
296 unsigned len = ReadInt();
298 assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
301 cstr = new char[len + (isNullTerm ? 1 : 0)];
303 assert (cstr != NULL);
305 for (unsigned i = 0; i < len; ++i)
306 cstr[i] = (char) ReadInt();
314 void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
315 unsigned len = ReadInt();
320 for (unsigned i = 0; i < len; ++i)
321 buff.push_back((char) ReadInt());
324 buff.push_back('\0');
327 void Deserializer::RegisterPtr(SerializedPtrID PtrId, const void* Ptr) {
328 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
330 assert (!HasFinalPtr(E) && "Pointer already registered.");
332 #ifdef DEBUG_BACKPATCH
333 llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
339 void Deserializer::ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch) {
340 SerializedPtrID PtrId = ReadPtrID();
347 #ifdef DEBUG_BACKPATCH
348 llvm::cerr << "ReadUintPtr: " << PtrId << "\n";
351 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
354 PtrRef = GetFinalPtr(E);
356 assert (AllowBackpatch &&
357 "Client forbids backpatching for this pointer.");
359 // Register backpatch. Check the freelist for a BPNode.
364 FreeList = FreeList->Next;
366 else // No available BPNode. Allocate one.
367 N = (BPNode*) Allocator.Allocate<BPNode>();
369 new (N) BPNode(GetBPNode(E),PtrRef);
374 uintptr_t Deserializer::ReadInternalRefPtr() {
375 SerializedPtrID PtrId = ReadPtrID();
377 assert (PtrId != 0 && "References cannot refer the NULL address.");
379 MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
381 assert (HasFinalPtr(E) &&
382 "Cannot backpatch references. Object must be already deserialized.");
384 return GetFinalPtr(E);
387 void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
390 for (BPNode* N = Head; N != NULL; N=N->Next) {
392 N->PtrRef |= reinterpret_cast<uintptr_t>(P);
396 Last->Next = FreeList;
400 Ptr = const_cast<void*>(P);
404 #define INT_READ(TYPE)\
405 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
406 X = (TYPE) D.ReadInt(); }
409 INT_READ(unsigned char)
410 INT_READ(unsigned short)
411 INT_READ(unsigned int)
412 INT_READ(unsigned long)
414 #define SINT_READ(TYPE)\
415 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
416 X = (TYPE) D.ReadSInt(); }
418 INT_READ(signed char)
419 INT_READ(signed short)
421 INT_READ(signed long)