mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-19 01:13:25 +00:00
066ff5b7f2
flag in the **key** of the backpatch map, as opposed to the mapped value which contains either the final pointer, or a pointer to a chain of pointers that need to be backpatched. The bit flag was moved to the key because we were erroneously assuming that the backpatched pointers would be at an alignment of >= 2 bytes, which obviously doesn't work for character strings. Now we just steal the bit from the key. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43595 91177308-0d34-0410-b5e6-96231b3b80d8
178 lines
4.2 KiB
C++
178 lines
4.2 KiB
C++
//==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- C++ -*-==//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by Ted Kremenek and is distributed under the
|
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the internal methods used for object serialization.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Bitcode/Deserialize.h"
|
|
|
|
using namespace llvm;
|
|
|
|
Deserializer::Deserializer(BitstreamReader& stream)
|
|
: Stream(stream), RecIdx(0), FreeList(NULL) {
|
|
}
|
|
|
|
Deserializer::~Deserializer() {
|
|
assert (RecIdx >= Record.size() &&
|
|
"Still scanning bitcode record when deserialization completed.");
|
|
|
|
#ifdef NDEBUG
|
|
for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
|
|
assert (I->first.hasFinalPtr() &&
|
|
"Some pointers were not backpatched.");
|
|
#endif
|
|
}
|
|
|
|
|
|
bool Deserializer::inRecord() {
|
|
if (Record.size() > 0) {
|
|
if (RecIdx >= Record.size()) {
|
|
RecIdx = 0;
|
|
Record.clear();
|
|
return false;
|
|
}
|
|
else return true;
|
|
}
|
|
else return false;
|
|
}
|
|
|
|
void Deserializer::ReadRecord() {
|
|
// FIXME: Check if we haven't run off the edge of the stream.
|
|
// FIXME: Handle abbreviations.
|
|
|
|
// FIXME: Check for the correct code.
|
|
unsigned Code = Stream.ReadCode();
|
|
|
|
assert (Record.size() == 0);
|
|
Stream.ReadRecord(Code,Record);
|
|
assert (Record.size() > 0);
|
|
}
|
|
|
|
uint64_t Deserializer::ReadInt() {
|
|
// FIXME: Any error recovery/handling with incomplete or bad files?
|
|
if (!inRecord())
|
|
ReadRecord();
|
|
|
|
return Record[RecIdx++];
|
|
}
|
|
|
|
char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
|
|
if (cstr == NULL)
|
|
MaxLen = 0; // Zero this just in case someone does something funny.
|
|
|
|
unsigned len = ReadInt();
|
|
|
|
assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);
|
|
|
|
if (!cstr)
|
|
cstr = new char[len + (isNullTerm ? 1 : 0)];
|
|
|
|
assert (cstr != NULL);
|
|
|
|
for (unsigned i = 0; i < len; ++i)
|
|
cstr[i] = (char) ReadInt();
|
|
|
|
if (isNullTerm)
|
|
cstr[len+1] = '\0';
|
|
|
|
return cstr;
|
|
}
|
|
|
|
void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
|
|
unsigned len = ReadInt();
|
|
|
|
buff.clear();
|
|
buff.reserve(len);
|
|
|
|
for (unsigned i = 0; i < len; ++i)
|
|
buff.push_back((char) ReadInt());
|
|
|
|
if (isNullTerm)
|
|
buff.push_back('\0');
|
|
}
|
|
|
|
void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
|
|
MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
|
|
|
|
assert (!HasFinalPtr(E) && "Pointer already registered.");
|
|
|
|
SetPtr(E,Ptr);
|
|
}
|
|
|
|
void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
|
|
unsigned PtrId = ReadInt();
|
|
|
|
if (PtrId == 0) {
|
|
PtrRef = 0;
|
|
return;
|
|
}
|
|
|
|
MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
|
|
|
|
if (HasFinalPtr(E))
|
|
PtrRef = GetFinalPtr(E);
|
|
else {
|
|
// Register backpatch. Check the freelist for a BPNode.
|
|
BPNode* N;
|
|
|
|
if (FreeList) {
|
|
N = FreeList;
|
|
FreeList = FreeList->Next;
|
|
}
|
|
else // No available BPNode. Allocate one.
|
|
N = (BPNode*) Allocator.Allocate<BPNode>();
|
|
|
|
new (N) BPNode(GetBPNode(E),PtrRef);
|
|
SetBPNode(E,N);
|
|
}
|
|
}
|
|
|
|
uintptr_t Deserializer::ReadInternalRefPtr() {
|
|
unsigned PtrId = ReadInt();
|
|
|
|
assert (PtrId != 0 && "References cannot refer the NULL address.");
|
|
|
|
MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
|
|
|
|
assert (!HasFinalPtr(E) &&
|
|
"Cannot backpatch references. Object must be already deserialized.");
|
|
|
|
return GetFinalPtr(E);
|
|
}
|
|
|
|
void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
|
|
BPNode* Last = NULL;
|
|
|
|
for (BPNode* N = Head; N != NULL; N=N->Next) {
|
|
Last = N;
|
|
N->PtrRef |= reinterpret_cast<uintptr_t>(P);
|
|
}
|
|
|
|
if (Last) {
|
|
Last->Next = FreeList;
|
|
FreeList = Head;
|
|
}
|
|
|
|
Ptr = const_cast<void*>(P);
|
|
}
|
|
|
|
|
|
#define INT_READ(TYPE)\
|
|
void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
|
|
X = (TYPE) D.ReadInt(); }\
|
|
TYPE SerializeTrait<TYPE>::ReadVal(Deserializer& D) {\
|
|
return (TYPE) D.ReadInt(); }
|
|
|
|
INT_READ(bool)
|
|
INT_READ(unsigned char)
|
|
INT_READ(unsigned short)
|
|
INT_READ(unsigned int)
|
|
INT_READ(unsigned long)
|