diff --git a/llvm/include/llvm/Bitcode/Deserialize.h b/llvm/include/llvm/Bitcode/Deserialize.h index 6ee09aaa3446..f5adcffe25c1 100644 --- a/llvm/include/llvm/Bitcode/Deserialize.h +++ b/llvm/include/llvm/Bitcode/Deserialize.h @@ -17,6 +17,9 @@ #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/Serialization.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" #include namespace llvm { @@ -25,50 +28,79 @@ class Deserializer { BitstreamReader& Stream; SmallVector Record; 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 MapTy; + + MapTy BPatchMap; + public: Deserializer(BitstreamReader& stream); ~Deserializer(); - + + uint64_t ReadInt(); + bool ReadBool() { + return ReadInt() ? true : false; + } + template inline T& Read(T& X) { SerializeTrait::Read(*this,X); return X; } + template + inline T ReadVal() { + return SerializeTrait::ReadVal(*this); + } + template inline T* Materialize() { return SerializeTrait::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 - EnumT ReadEnum(unsigned MinVal, unsigned MaxVal) { - return static_cast(ReadInt(32)); - } char* ReadCStr(char* cstr = NULL, unsigned MaxLen=0, bool isNullTerm=true); void ReadCStr(std::vector& buff, bool isNullTerm=false); - -private: - void ReadRecord(); - - inline bool inRecord() { - if (Record.size() > 0) { - if (RecIdx >= Record.size()) { - RecIdx = 0; - Record.clear(); - return false; - } - else return true; - } - else return false; + + template + inline T* ReadOwnedPtr() { + unsigned PtrId = ReadInt(); + T* x = SerializeTrait::Materialize(*this); + RegisterPtr(PtrId,x); + return x; } -}; + void ReadPtr(void*& PtrRef); + void RegisterPtr(unsigned PtrId, void* Ptr); + + + void BackpatchPointers(); +private: + void ReadRecord(); + bool inRecord(); +}; + } // end namespace llvm #endif diff --git a/llvm/include/llvm/Bitcode/Serialization.h b/llvm/include/llvm/Bitcode/Serialization.h index 935452cc1b86..02db22305344 100644 --- a/llvm/include/llvm/Bitcode/Serialization.h +++ b/llvm/include/llvm/Bitcode/Serialization.h @@ -24,14 +24,14 @@ template struct SerializeTrait; #define SERIALIZE_INT_TRAIT(TYPE)\ template <> struct SerializeTrait {\ 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(unsigned char) SERIALIZE_INT_TRAIT(unsigned short) SERIALIZE_INT_TRAIT(unsigned int) SERIALIZE_INT_TRAIT(unsigned long) -SERIALIZE_INT_TRAIT(unsigned long long) #undef SERIALIZE_INT_TRAIT diff --git a/llvm/include/llvm/Bitcode/Serialize.h b/llvm/include/llvm/Bitcode/Serialize.h index 061ccaf7c302..dc1fe646f227 100644 --- a/llvm/include/llvm/Bitcode/Serialize.h +++ b/llvm/include/llvm/Bitcode/Serialize.h @@ -18,6 +18,7 @@ #include "llvm/Bitcode/Serialization.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" namespace llvm { @@ -25,6 +26,10 @@ class Serializer { BitstreamWriter& Stream; SmallVector Record; bool inBlock; + + typedef DenseMap MapTy; + MapTy PtrMap; + public: Serializer(BitstreamWriter& stream, unsigned BlockID = 0); ~Serializer(); @@ -35,13 +40,22 @@ public: void EmitInt(unsigned X); void EmitBool(bool X) { EmitInt(X); } 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 + void EmitOwnedPtr(T* ptr) { + EmitPtr(ptr); + SerializeTrait::Emit(*this,*ptr); + } void Flush() { if (inRecord()) EmitRecord(); } private: void EmitRecord(); - inline bool inRecord() { return Record.size() > 0; } + inline bool inRecord() { return Record.size() > 0; } + unsigned getPtrId(void* ptr); }; } // end namespace llvm diff --git a/llvm/lib/Bitcode/Reader/Deserialize.cpp b/llvm/lib/Bitcode/Reader/Deserialize.cpp index cf5fe205eba4..febb2d7cafc9 100644 --- a/llvm/lib/Bitcode/Reader/Deserialize.cpp +++ b/llvm/lib/Bitcode/Reader/Deserialize.cpp @@ -22,6 +22,21 @@ Deserializer::Deserializer(BitstreamReader& stream) Deserializer::~Deserializer() { assert (RecIdx >= Record.size() && "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() { @@ -79,14 +94,49 @@ void Deserializer::ReadCStr(std::vector& buff, bool isNullTerm) { 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(); + 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)\ void SerializeTrait::Read(Deserializer& D, TYPE& X) {\ - X = (TYPE) D.ReadInt(); } + X = (TYPE) D.ReadInt(); }\ +TYPE SerializeTrait::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) -INT_READ(unsigned long long) diff --git a/llvm/lib/Bitcode/Writer/Serialize.cpp b/llvm/lib/Bitcode/Writer/Serialize.cpp index 72939334bc2f..fbe1d1007c9f 100644 --- a/llvm/lib/Bitcode/Writer/Serialize.cpp +++ b/llvm/lib/Bitcode/Writer/Serialize.cpp @@ -57,6 +57,17 @@ void Serializer::EmitCStr(const char* 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)\ void SerializeTrait::Emit(Serializer&S, TYPE X) { S.EmitInt(X); } @@ -65,4 +76,3 @@ INT_EMIT(unsigned char) INT_EMIT(unsigned short) INT_EMIT(unsigned int) INT_EMIT(unsigned long) -INT_EMIT(unsigned long long)