From 0b2d7aaf5cb376fb05c312f9c7db591cba32ad33 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 23 Oct 2007 21:29:33 +0000 Subject: [PATCH] Added preliminary implementation of generic object serialization to bitcode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43261 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/Serialization.h | 115 +++++++++++++++++++++++++++ lib/Bitcode/Reader/Deserialize.cpp | 83 +++++++++++++++++++ lib/Bitcode/Writer/Serialize.cpp | 52 ++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 include/llvm/Bitcode/Serialization.h create mode 100644 lib/Bitcode/Reader/Deserialize.cpp create mode 100644 lib/Bitcode/Writer/Serialize.cpp diff --git a/include/llvm/Bitcode/Serialization.h b/include/llvm/Bitcode/Serialization.h new file mode 100644 index 00000000000..2d633115a2a --- /dev/null +++ b/include/llvm/Bitcode/Serialization.h @@ -0,0 +1,115 @@ + //=- Serialization.h - 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 interface for generic object serialization to +// LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_SERIALIZE +#define LLVM_BITCODE_SERIALIZE + +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + +template struct SerializeTrait; + +class Serializer { + BitstreamWriter& Stream; + SmallVector Record; + bool inBlock; +public: + Serializer(BitstreamWriter& stream, unsigned BlockID = 0); + ~Serializer(); + + template + inline void Emit(const T& X) { SerializeTrait::Serialize(*this,X); } + + void EmitInt(unsigned X, unsigned bits); + void EmitCString(const char* cstr); + + void Flush() { if (inRecord()) EmitRecord(); } + +private: + void EmitRecord(); + inline bool inRecord() { return Record.size() > 0; } +}; + + +class Deserializer { + BitstreamReader& Stream; + SmallVector Record; + unsigned RecIdx; +public: + Deserializer(BitstreamReader& stream); + ~Deserializer(); + + template + inline void Read(T& X) { SerializeTrait::Deserialize(*this,X); } + + template + inline T* Materialize() { + T* X = SerializeTrait::Instantiate(); + Read(*X); + return X; + } + + uint64_t ReadInt(unsigned bits = 32); + bool ReadBool() { return ReadInt(1); } + + char* ReadCString(char* cstr = NULL, unsigned MaxLen=0, bool isNullTerm=true); + void ReadCString(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 +struct SerializeIntTrait { + static inline void Serialize(Serializer& S, uintty X) { + S.EmitInt(X,Bits); + } + + static inline void Deserialize(Deserializer& S, uintty& X) { + X = (uintty) S.ReadInt(Bits); + } +}; + + +template <> struct SerializeTrait + : public SerializeIntTrait {}; + +template <> struct SerializeTrait + : public SerializeIntTrait {}; + +template <> struct SerializeTrait + : public SerializeIntTrait {}; + +template <> struct SerializeTrait + : public SerializeIntTrait {}; + +} // end namespace llvm +#endif diff --git a/lib/Bitcode/Reader/Deserialize.cpp b/lib/Bitcode/Reader/Deserialize.cpp new file mode 100644 index 00000000000..ccd929a440d --- /dev/null +++ b/lib/Bitcode/Reader/Deserialize.cpp @@ -0,0 +1,83 @@ +//==- 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/Serialization.h" + +using namespace llvm; + +Deserializer::Deserializer(BitstreamReader& stream) + : Stream(stream), RecIdx(0) { +} + +Deserializer::~Deserializer() { + assert (RecIdx >= Record.size() && + "Still scanning bitcode record when deserialization completed."); +} + +void Deserializer::ReadRecord() { + // FIXME: Check if we haven't run off the edge of the stream. + // FIXME: Handle abbreviations. + unsigned Code = Stream.ReadCode(); + // FIXME: Check for the correct code. + assert (Record.size() == 0); + + Stream.ReadRecord(Code,Record); + + assert (Record.size() > 0); +} + +uint64_t Deserializer::ReadInt(unsigned Bits) { + // FIXME: Any error recovery/handling with incomplete or bad files? + if (!inRecord()) + ReadRecord(); + + // FIXME: check for loss of precision in read (compare to Bits) + return Record[RecIdx++]; +} + +char* Deserializer::ReadCString(char* cstr, unsigned MaxLen, bool isNullTerm) { + if (cstr == NULL) + MaxLen = 0; // Zero this just in case someone does something funny. + + unsigned len = ReadInt(32); + + // FIXME: perform dynamic checking of lengths? + 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] = ReadInt(8); + + if (isNullTerm) + cstr[len+1] = '\0'; + + return cstr; +} + +void Deserializer::ReadCString(std::vector& buff, bool isNullTerm) { + buff.clear(); + + unsigned len = ReadInt(32); + + buff.reserve(len); + + for (unsigned i = 0; i < len; ++i) + buff.push_back(ReadInt(8)); + + if (isNullTerm) + buff.push_back('\0'); +} diff --git a/lib/Bitcode/Writer/Serialize.cpp b/lib/Bitcode/Writer/Serialize.cpp new file mode 100644 index 00000000000..9fbb97de69f --- /dev/null +++ b/lib/Bitcode/Writer/Serialize.cpp @@ -0,0 +1,52 @@ +//==- Serialize.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/Serialization.h" + +using namespace llvm; + +Serializer::Serializer(BitstreamWriter& stream, unsigned BlockID) + : Stream(stream), inBlock(BlockID >= 8) { + + if (inBlock) Stream.EnterSubblock(8,3); +} + +Serializer::~Serializer() { + if (inRecord()) + EmitRecord(); + + if (inBlock) + Stream.ExitBlock(); + + Stream.FlushToWord(); +} + +void Serializer::EmitRecord() { + assert(Record.size() > 0 && "Cannot emit empty record."); + Stream.EmitRecord(8,Record); + Record.clear(); +} + +void Serializer::EmitInt(unsigned X, unsigned bits) { + Record.push_back(X); +} + +void Serializer::EmitCString(const char* cstr) { + unsigned l = strlen(cstr); + Record.push_back(l); + + for (unsigned i = 0; i < l; i++) + Record.push_back(cstr[i]); + + EmitRecord(); +}