Implemented prototype serialization of pointers, including support
authorTed Kremenek <kremenek@apple.com>
Thu, 25 Oct 2007 00:10:21 +0000 (00:10 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 25 Oct 2007 00:10:21 +0000 (00:10 +0000)
for backpatching.

Added Deserialize::ReadVal.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43319 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Bitcode/Deserialize.h
include/llvm/Bitcode/Serialization.h
include/llvm/Bitcode/Serialize.h
lib/Bitcode/Reader/Deserialize.cpp
lib/Bitcode/Writer/Serialize.cpp

index 6ee09aaa34465d85ca2bd33d0dbd5915dda725fb..f5adcffe25c183ec82c3af2b8f6fc50f5329d49f 100644 (file)
@@ -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 <vector>
 
 namespace llvm {
@@ -25,50 +28,79 @@ class Deserializer {
   BitstreamReader& Stream;
   SmallVector<uint64_t,10> 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<unsigned,BPatchEntry,PtrIdInfo,BPatchEntry> MapTy;
+
+  MapTy BPatchMap;  
+  
 public:
   Deserializer(BitstreamReader& stream);
   ~Deserializer();
-  
+
+  uint64_t ReadInt();
+  bool ReadBool() {
+    return ReadInt() ? true : false;
+  }
+
   template <typename T>
   inline T& Read(T& X) {
     SerializeTrait<T>::Read(*this,X);
     return X;
   }
   
+  template <typename T>
+  inline T ReadVal() {
+    return SerializeTrait<T>::ReadVal(*this);
+  }
+
   template <typename T>
   inline T* Materialize() {
     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);
   void ReadCStr(std::vector<char>& buff, bool isNullTerm=false);
+
+  template <typename T>
+  inline T* ReadOwnedPtr() {    
+    unsigned PtrId = ReadInt();
+    T* x = SerializeTrait<T>::Materialize(*this);
+    RegisterPtr(PtrId,x);
+    return x;
+  }
   
+  void ReadPtr(void*& PtrRef);  
+  void RegisterPtr(unsigned PtrId, void* Ptr);
+
+
+  void BackpatchPointers();
 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;
-  }
+  void ReadRecord();  
+  bool inRecord();
 };
-  
+    
 } // end namespace llvm
 
 #endif
index 935452cc1b860f53973a35f11a94fe75538d563c..02db22305344e7eb7c00d773464cb231ddf308ff 100644 (file)
@@ -24,14 +24,14 @@ template <typename T> struct SerializeTrait;
 #define SERIALIZE_INT_TRAIT(TYPE)\
 template <> struct SerializeTrait<TYPE> {\
   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
   
index 061ccaf7c302179330ec5b94231b8e5cc64096f6..dc1fe646f227df00e6bbab4f05223aa691b2604f 100644 (file)
@@ -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<uint64_t,10> Record;
   bool inBlock;
+  
+  typedef DenseMap<void*,unsigned> 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 <typename T>
+  void EmitOwnedPtr(T* ptr) {
+    EmitPtr(ptr);
+    SerializeTrait<T>::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
index cf5fe205eba4faae7aa12c93d84573160764890b..febb2d7cafc93819d1637f34745055ef29186132 100644 (file)
@@ -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<char>& 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<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)\
 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(unsigned char)
 INT_READ(unsigned short)
 INT_READ(unsigned int)
 INT_READ(unsigned long)
-INT_READ(unsigned long long)
index 72939334bc2fa80960a8bc520829f8e0fb336380..fbe1d1007c9f054f04dd6b0c745d7e8f272de29e 100644 (file)
@@ -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<TYPE>::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)