1 //==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // 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) {
25 StreamStart
= Stream
.GetCurrentBitNo();
28 Deserializer::~Deserializer() {
29 assert (RecIdx
>= Record
.size() &&
30 "Still scanning bitcode record when deserialization completed.");
32 #ifdef DEBUG_BACKPATCH
33 for (MapTy::iterator I
=BPatchMap
.begin(), E
=BPatchMap
.end(); I
!=E
; ++I
)
34 assert (I
->first
.hasFinalPtr() &&
35 "Some pointers were not backpatched.");
40 bool Deserializer::inRecord() {
41 if (Record
.size() > 0) {
42 if (RecIdx
>= Record
.size()) {
55 bool Deserializer::AdvanceStream() {
56 assert (!inRecord() &&
57 "Cannot advance stream. Still processing a record.");
59 if (AbbrevNo
== bitc::ENTER_SUBBLOCK
||
60 AbbrevNo
>= bitc::UNABBREV_RECORD
)
63 while (!Stream
.AtEndOfStream()) {
65 uint64_t Pos
= Stream
.GetCurrentBitNo();
66 AbbrevNo
= Stream
.ReadCode();
69 case bitc::ENTER_SUBBLOCK
: {
70 unsigned id
= Stream
.ReadSubBlockID();
72 // Determine the extent of the block. This is useful for jumping around
73 // the stream. This is hack: we read the header of the block, save
74 // the length, and then revert the bitstream to a location just before
75 // the block is entered.
76 uint64_t BPos
= Stream
.GetCurrentBitNo();
77 Stream
.ReadVBR(bitc::CodeLenWidth
); // Skip the code size.
79 unsigned NumWords
= Stream
.Read(bitc::BlockSizeWidth
);
80 Stream
.JumpToBit(BPos
);
82 BlockStack
.push_back(Location(Pos
,id
,NumWords
));
86 case bitc::END_BLOCK
: {
87 bool x
= Stream
.ReadBlockEnd();
88 assert(!x
&& "Error at block end."); x
=x
;
89 BlockStack
.pop_back();
93 case bitc::DEFINE_ABBREV
:
94 Stream
.ReadAbbrevRecord();
107 void Deserializer::ReadRecord() {
109 while (AdvanceStream() && AbbrevNo
== bitc::ENTER_SUBBLOCK
) {
110 assert (!BlockStack
.empty());
111 Stream
.EnterSubBlock(BlockStack
.back().BlockID
);
115 if (Stream
.AtEndOfStream())
118 assert (Record
.empty());
119 assert (AbbrevNo
>= bitc::UNABBREV_RECORD
);
120 RecordCode
= Stream
.ReadRecord(AbbrevNo
,Record
);
121 assert (Record
.size() > 0);
124 void Deserializer::SkipBlock() {
125 assert (!inRecord());
132 assert (AbbrevNo
== bitc::ENTER_SUBBLOCK
);
133 BlockStack
.pop_back();
140 bool Deserializer::SkipToBlock(unsigned BlockID
) {
141 assert (!inRecord());
144 assert (AbbrevNo
== bitc::ENTER_SUBBLOCK
);
146 unsigned BlockLevel
= BlockStack
.size();
149 BlockLevel
== BlockStack
.size() &&
150 getCurrentBlockID() != BlockID
)
153 return !(AtEnd() || BlockLevel
!= BlockStack
.size());
156 Deserializer::Location
Deserializer::getCurrentBlockLocation() {
160 return BlockStack
.back();
163 bool Deserializer::JumpTo(const Location
& Loc
) {
165 assert (!inRecord());
169 assert (!BlockStack
.empty() || AtEnd());
171 uint64_t LastBPos
= StreamStart
;
173 while (!BlockStack
.empty()) {
175 LastBPos
= BlockStack
.back().BitNo
;
177 // Determine of the current block contains the location of the block
178 // we are looking for.
179 if (BlockStack
.back().contains(Loc
)) {
180 // We found the enclosing block. We must first POP it off to
181 // destroy any accumulated context within the block scope. We then
182 // jump to the position of the block and enter it.
183 Stream
.JumpToBit(LastBPos
);
185 if (BlockStack
.size() == Stream
.BlockScope
.size())
186 Stream
.PopBlockScope();
188 BlockStack
.pop_back();
192 assert (AbbrevNo
== bitc::ENTER_SUBBLOCK
);
194 Stream
.EnterSubBlock(BlockStack
.back().BlockID
);
198 // This block does not contain the block we are looking for. Pop it.
199 if (BlockStack
.size() == Stream
.BlockScope
.size())
200 Stream
.PopBlockScope();
202 BlockStack
.pop_back();
206 // Check if we have popped our way to the outermost scope. If so,
207 // we need to adjust our position.
208 if (BlockStack
.empty()) {
209 assert (Stream
.BlockScope
.empty());
211 Stream
.JumpToBit(Loc
.BitNo
< LastBPos
? StreamStart
: LastBPos
);
216 assert (AbbrevNo
== bitc::ENTER_SUBBLOCK
);
217 assert (!BlockStack
.empty());
219 while (!AtEnd() && BlockStack
.back() != Loc
) {
220 if (BlockStack
.back().contains(Loc
)) {
221 Stream
.EnterSubBlock(BlockStack
.back().BlockID
);
233 assert (BlockStack
.back() == Loc
);
238 void Deserializer::Rewind() {
239 while (!Stream
.BlockScope
.empty())
240 Stream
.PopBlockScope();
242 while (!BlockStack
.empty())
243 BlockStack
.pop_back();
245 Stream
.JumpToBit(StreamStart
);
250 unsigned Deserializer::getCurrentBlockID() {
254 return BlockStack
.back().BlockID
;
257 unsigned Deserializer::getRecordCode() {
260 assert (AbbrevNo
>= bitc::UNABBREV_RECORD
);
267 bool Deserializer::FinishedBlock(Location BlockLoc
) {
271 for (llvm::SmallVector
<Location
,8>::reverse_iterator
272 I
=BlockStack
.rbegin(), E
=BlockStack
.rend(); I
!=E
; ++I
)
279 unsigned Deserializer::getAbbrevNo() {
286 bool Deserializer::AtEnd() {
290 if (!AdvanceStream())
296 uint64_t Deserializer::ReadInt() {
297 // FIXME: Any error recovery/handling with incomplete or bad files?
301 return Record
[RecIdx
++];
304 int64_t Deserializer::ReadSInt() {
305 uint64_t x
= ReadInt();
306 int64_t magnitude
= x
>> 1;
307 return x
& 0x1 ? -magnitude
: magnitude
;
310 char* Deserializer::ReadCStr(char* cstr
, unsigned MaxLen
, bool isNullTerm
) {
312 MaxLen
= 0; // Zero this just in case someone does something funny.
314 unsigned len
= ReadInt();
316 assert (MaxLen
== 0 || (len
+ (isNullTerm
? 1 : 0)) <= MaxLen
);
319 cstr
= new char[len
+ (isNullTerm
? 1 : 0)];
321 assert (cstr
!= NULL
);
323 for (unsigned i
= 0; i
< len
; ++i
)
324 cstr
[i
] = (char) ReadInt();
332 void Deserializer::ReadCStr(std::vector
<char>& buff
, bool isNullTerm
,
335 unsigned len
= ReadInt();
337 // If Idx is beyond the current before size, reduce Idx to refer to the
338 // element after the last element.
339 if (Idx
> buff
.size())
342 buff
.reserve(len
+Idx
);
345 for (unsigned i
= 0; i
< len
; ++i
)
346 buff
.push_back((char) ReadInt());
349 buff
.push_back('\0');
352 void Deserializer::RegisterPtr(const SerializedPtrID
& PtrId
,
355 MapTy::value_type
& E
= BPatchMap
.FindAndConstruct(BPKey(PtrId
));
357 assert (!HasFinalPtr(E
) && "Pointer already registered.");
359 #ifdef DEBUG_BACKPATCH
360 llvm::cerr
<< "RegisterPtr: " << PtrId
<< " => " << Ptr
<< "\n";
366 void Deserializer::ReadUIntPtr(uintptr_t& PtrRef
,
367 const SerializedPtrID
& PtrId
,
368 bool AllowBackpatch
) {
374 MapTy::value_type
& E
= BPatchMap
.FindAndConstruct(BPKey(PtrId
));
376 if (HasFinalPtr(E
)) {
377 PtrRef
= GetFinalPtr(E
);
379 #ifdef DEBUG_BACKPATCH
380 llvm::cerr
<< "ReadUintPtr: " << PtrId
381 << " <-- " << (void*) GetFinalPtr(E
) << '\n';
385 assert (AllowBackpatch
&&
386 "Client forbids backpatching for this pointer.");
388 #ifdef DEBUG_BACKPATCH
389 llvm::cerr
<< "ReadUintPtr: " << PtrId
<< " (NO PTR YET)\n";
392 // Register backpatch. Check the freelist for a BPNode.
397 FreeList
= FreeList
->Next
;
399 else // No available BPNode. Allocate one.
400 N
= (BPNode
*) Allocator
.Allocate
<BPNode
>();
402 new (N
) BPNode(GetBPNode(E
),PtrRef
);
407 uintptr_t Deserializer::ReadInternalRefPtr() {
408 SerializedPtrID PtrId
= ReadPtrID();
410 assert (PtrId
!= 0 && "References cannot refer the NULL address.");
412 MapTy::value_type
& E
= BPatchMap
.FindAndConstruct(BPKey(PtrId
));
414 assert (HasFinalPtr(E
) &&
415 "Cannot backpatch references. Object must be already deserialized.");
417 return GetFinalPtr(E
);
420 void Deserializer::BPEntry::SetPtr(BPNode
*& FreeList
, void* P
) {
423 for (BPNode
* N
= Head
; N
!= NULL
; N
=N
->Next
) {
425 N
->PtrRef
|= reinterpret_cast<uintptr_t>(P
);
429 Last
->Next
= FreeList
;
433 Ptr
= const_cast<void*>(P
);
437 #define INT_READ(TYPE)\
438 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
439 X = (TYPE) D.ReadInt(); }
442 INT_READ(unsigned char)
443 INT_READ(unsigned short)
444 INT_READ(unsigned int)
445 INT_READ(unsigned long)
447 #define SINT_READ(TYPE)\
448 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
449 X = (TYPE) D.ReadSInt(); }
451 INT_READ(signed char)
452 INT_READ(signed short)
454 INT_READ(signed long)