Implemented prototype serialization of pointers, including support

for backpatching.

Added Deserialize::ReadVal.

llvm-svn: 43319
This commit is contained in:
Ted Kremenek 2007-10-25 00:10:21 +00:00
parent ed763de6cb
commit d5cb7b055d
5 changed files with 139 additions and 33 deletions

View File

@ -17,6 +17,9 @@
#include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/Serialization.h" #include "llvm/Bitcode/Serialization.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include <vector> #include <vector>
namespace llvm { namespace llvm {
@ -25,50 +28,79 @@ class Deserializer {
BitstreamReader& Stream; BitstreamReader& Stream;
SmallVector<uint64_t,10> Record; SmallVector<uint64_t,10> Record;
unsigned RecIdx; unsigned RecIdx;
BumpPtrAllocator Allocator;
struct PtrIdInfo {
static inline unsigned getEmptyKey() { return ~((unsigned) 0x0); }
static inline unsigned getTombstoneKey() { return getEmptyKey()-1; }
static inline unsigned getHashValue(unsigned X) { return X; }
static inline bool isEqual(unsigned X, unsigned Y) { return X == Y; }
static inline bool isPod() { return true; }
};
struct BPatchNode {
BPatchNode* const Next;
void*& PtrRef;
BPatchNode(BPatchNode* n, void*& pref) : Next(n), PtrRef(pref) {}
};
struct BPatchEntry {
BPatchNode* Head;
void* Ptr;
BPatchEntry() : Head(NULL), Ptr(NULL) {}
static inline bool isPod() { return true; }
};
typedef llvm::DenseMap<unsigned,BPatchEntry,PtrIdInfo,BPatchEntry> MapTy;
MapTy BPatchMap;
public: public:
Deserializer(BitstreamReader& stream); Deserializer(BitstreamReader& stream);
~Deserializer(); ~Deserializer();
uint64_t ReadInt();
bool ReadBool() {
return ReadInt() ? true : false;
}
template <typename T> template <typename T>
inline T& Read(T& X) { inline T& Read(T& X) {
SerializeTrait<T>::Read(*this,X); SerializeTrait<T>::Read(*this,X);
return X; return X;
} }
template <typename T>
inline T ReadVal() {
return SerializeTrait<T>::ReadVal(*this);
}
template <typename T> template <typename T>
inline T* Materialize() { inline T* Materialize() {
return SerializeTrait<T>::Materialize(*this); return SerializeTrait<T>::Materialize(*this);
} }
uint64_t ReadInt();
bool ReadBool() { return ReadInt() ? true : false; }
// FIXME: Substitute a better implementation which calculates the minimum
// number of bits needed to serialize the enum.
template <typename EnumT>
EnumT ReadEnum(unsigned MinVal, unsigned MaxVal) {
return static_cast<EnumT>(ReadInt(32));
}
char* ReadCStr(char* cstr = NULL, unsigned MaxLen=0, bool isNullTerm=true); char* ReadCStr(char* cstr = NULL, unsigned MaxLen=0, bool isNullTerm=true);
void ReadCStr(std::vector<char>& buff, bool isNullTerm=false); void ReadCStr(std::vector<char>& buff, bool isNullTerm=false);
private: template <typename T>
void ReadRecord(); inline T* ReadOwnedPtr() {
unsigned PtrId = ReadInt();
inline bool inRecord() { T* x = SerializeTrait<T>::Materialize(*this);
if (Record.size() > 0) { RegisterPtr(PtrId,x);
if (RecIdx >= Record.size()) { return x;
RecIdx = 0;
Record.clear();
return false;
}
else return true;
}
else return false;
} }
};
void ReadPtr(void*& PtrRef);
void RegisterPtr(unsigned PtrId, void* Ptr);
void BackpatchPointers();
private:
void ReadRecord();
bool inRecord();
};
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -24,14 +24,14 @@ template <typename T> struct SerializeTrait;
#define SERIALIZE_INT_TRAIT(TYPE)\ #define SERIALIZE_INT_TRAIT(TYPE)\
template <> struct SerializeTrait<TYPE> {\ template <> struct SerializeTrait<TYPE> {\
static void Emit(Serializer& S, TYPE X);\ static void Emit(Serializer& S, TYPE X);\
static void Read(Deserializer& S, TYPE& X); }; static void Read(Deserializer& S, TYPE& X);\
static TYPE ReadVal(Deserializer& S); };
SERIALIZE_INT_TRAIT(bool) SERIALIZE_INT_TRAIT(bool)
SERIALIZE_INT_TRAIT(unsigned char) SERIALIZE_INT_TRAIT(unsigned char)
SERIALIZE_INT_TRAIT(unsigned short) SERIALIZE_INT_TRAIT(unsigned short)
SERIALIZE_INT_TRAIT(unsigned int) SERIALIZE_INT_TRAIT(unsigned int)
SERIALIZE_INT_TRAIT(unsigned long) SERIALIZE_INT_TRAIT(unsigned long)
SERIALIZE_INT_TRAIT(unsigned long long)
#undef SERIALIZE_INT_TRAIT #undef SERIALIZE_INT_TRAIT

View File

@ -18,6 +18,7 @@
#include "llvm/Bitcode/Serialization.h" #include "llvm/Bitcode/Serialization.h"
#include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
namespace llvm { namespace llvm {
@ -25,6 +26,10 @@ class Serializer {
BitstreamWriter& Stream; BitstreamWriter& Stream;
SmallVector<uint64_t,10> Record; SmallVector<uint64_t,10> Record;
bool inBlock; bool inBlock;
typedef DenseMap<void*,unsigned> MapTy;
MapTy PtrMap;
public: public:
Serializer(BitstreamWriter& stream, unsigned BlockID = 0); Serializer(BitstreamWriter& stream, unsigned BlockID = 0);
~Serializer(); ~Serializer();
@ -35,13 +40,22 @@ public:
void EmitInt(unsigned X); void EmitInt(unsigned X);
void EmitBool(bool X) { EmitInt(X); } void EmitBool(bool X) { EmitInt(X); }
void EmitCStr(const char* beg, const char* end); void EmitCStr(const char* beg, const char* end);
void EmitCStr(const char* cstr); void EmitCStr(const char* cstr);
void EmitPtr(void* ptr) { EmitInt(getPtrId(ptr)); }
template <typename T>
void EmitOwnedPtr(T* ptr) {
EmitPtr(ptr);
SerializeTrait<T>::Emit(*this,*ptr);
}
void Flush() { if (inRecord()) EmitRecord(); } void Flush() { if (inRecord()) EmitRecord(); }
private: private:
void EmitRecord(); void EmitRecord();
inline bool inRecord() { return Record.size() > 0; } inline bool inRecord() { return Record.size() > 0; }
unsigned getPtrId(void* ptr);
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -22,6 +22,21 @@ Deserializer::Deserializer(BitstreamReader& stream)
Deserializer::~Deserializer() { Deserializer::~Deserializer() {
assert (RecIdx >= Record.size() && assert (RecIdx >= Record.size() &&
"Still scanning bitcode record when deserialization completed."); "Still scanning bitcode record when deserialization completed.");
BackpatchPointers();
}
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() { void Deserializer::ReadRecord() {
@ -79,14 +94,49 @@ void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
buff.push_back('\0'); buff.push_back('\0');
} }
void Deserializer::RegisterPtr(unsigned PtrId,void* Ptr) {
BPatchEntry& E = BPatchMap[PtrId];
assert (E.Ptr == NULL && "Pointer already registered.");
E.Ptr = Ptr;
}
void Deserializer::ReadPtr(void*& PtrRef) {
unsigned PtrId = ReadInt();
BPatchEntry& E = BPatchMap[PtrId];
if (E.Ptr == NULL) {
// Register backpatch.
void* P = Allocator.Allocate<BPatchNode>();
E.Head = new (P) BPatchNode(E.Head,PtrRef);
}
else
PtrRef = E.Ptr;
}
void Deserializer::BackpatchPointers() {
for (MapTy::iterator I=BPatchMap.begin(),E=BPatchMap.end(); I!=E; ++I) {
BPatchEntry& E = I->second;
assert (E.Ptr && "No pointer found for backpatch.");
for (BPatchNode* N = E.Head; N != NULL; N = N->Next)
N->PtrRef = E.Ptr;
E.Head = NULL;
}
Allocator.Reset();
}
#define INT_READ(TYPE)\ #define INT_READ(TYPE)\
void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\ void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
X = (TYPE) D.ReadInt(); } X = (TYPE) D.ReadInt(); }\
TYPE SerializeTrait<TYPE>::ReadVal(Deserializer& D) {\
return (TYPE) D.ReadInt(); }
INT_READ(bool) INT_READ(bool)
INT_READ(unsigned char) INT_READ(unsigned char)
INT_READ(unsigned short) INT_READ(unsigned short)
INT_READ(unsigned int) INT_READ(unsigned int)
INT_READ(unsigned long) INT_READ(unsigned long)
INT_READ(unsigned long long)

View File

@ -57,6 +57,17 @@ void Serializer::EmitCStr(const char* s) {
EmitCStr(s,s+strlen(s)); EmitCStr(s,s+strlen(s));
} }
unsigned Serializer::getPtrId(void* ptr) {
MapTy::iterator I = PtrMap.find(ptr);
if (I == PtrMap.end()) {
unsigned id = PtrMap.size();
PtrMap[ptr] = id;
return id;
}
else return I->second;
}
#define INT_EMIT(TYPE)\ #define INT_EMIT(TYPE)\
void SerializeTrait<TYPE>::Emit(Serializer&S, TYPE X) { S.EmitInt(X); } void SerializeTrait<TYPE>::Emit(Serializer&S, TYPE X) { S.EmitInt(X); }
@ -65,4 +76,3 @@ INT_EMIT(unsigned char)
INT_EMIT(unsigned short) INT_EMIT(unsigned short)
INT_EMIT(unsigned int) INT_EMIT(unsigned int)
INT_EMIT(unsigned long) INT_EMIT(unsigned long)
INT_EMIT(unsigned long long)