diff options
Diffstat (limited to 'Driver/SerializationTest.cpp')
-rw-r--r-- | Driver/SerializationTest.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/Driver/SerializationTest.cpp b/Driver/SerializationTest.cpp new file mode 100644 index 0000000000..35ef4b7d33 --- /dev/null +++ b/Driver/SerializationTest.cpp @@ -0,0 +1,240 @@ +//===--- SerializationTest.cpp - Experimental Object Serialization --------===// +// +// 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 implements prototype code for serialization of objects in clang. +// It is not intended yet for public use, but simply is a placeholder to +// experiment with new serialization features. Serialization will eventually +// be integrated as a proper component of the clang libraries. +// +//===----------------------------------------------------------------------===// + +#include "ASTConsumers.h" +#include "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "llvm/System/Path.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include <fstream> + +using namespace clang; +using llvm::BitstreamWriter; +using std::cerr; +using std::cout; +using std::endl; +using std::flush; + +namespace llvm { +template<typename T> struct IntrospectionTrait { + struct Flags { + enum { isPod = false, UniqueInstances = false, UniqueRefs = false }; + }; + + template<typename Introspector> + struct Ops { + static inline void Introspect(T& X, Introspector& I) { + assert (false && "Introspect not implemented."); + } + }; +}; +} + +namespace { +class SerializationTest : public ASTConsumer { + IdentifierTable* IdTable; + unsigned MainFileID; +public: + void Initialize(ASTContext& Context, unsigned mainFileID) { + IdTable = &Context.Idents; + MainFileID = mainFileID; + RunSerializationTest(); + } + + void RunSerializationTest(); + bool WriteAll(llvm::sys::Path& Filename); + + virtual void HandleTopLevelDecl(Decl *D) {} +}; + +class Writer { + std::vector<unsigned char> Buffer; + BitstreamWriter Stream; + std::ostream& Out; +public: + + enum { IdentifierTableBID = 0x8 }; + + Writer(std::ostream& out) : Stream(Buffer), Out(out) { + Buffer.reserve(256*1024); + + // Emit the file header. + Stream.Emit((unsigned)'B', 8); + Stream.Emit((unsigned)'C', 8); + Stream.Emit(0xC, 4); + Stream.Emit(0xF, 4); + Stream.Emit(0xE, 4); + Stream.Emit(0x0, 4); + } + + ~Writer() { + Out.write((char*)&Buffer.front(), Buffer.size()); + Out.flush(); + } + + template <typename T> inline void operator()(T& x) { + llvm::IntrospectionTrait<T>::template Ops<Writer>::Introspect(x,*this); + } + + template <typename T> inline void operator()(T& x, unsigned bits) { + llvm::IntrospectionTrait<T>::template Ops<Writer>::Introspect(x,bits,*this); + } + + template <typename T> inline void operator()(const T& x) { + operator()(const_cast<T&>(x)); + } + + template <typename T> inline void operator()(const T& x, unsigned bits) { + operator()(const_cast<T&>(x),bits); + } + + inline void operator()(bool X) { Stream.Emit(X,1); } + inline void operator()(unsigned X) { Stream.Emit(X,32); } + inline void operator()(unsigned X, unsigned bits, bool VBR=false) { + if (VBR) Stream.Emit(X,bits); + else Stream.Emit(X,bits); + } + + inline BitstreamWriter& getStream() { + return Stream; + } + + template <typename T> inline void EnterSubblock(unsigned CodeLen) { + Stream.EnterSubblock(8,CodeLen); + } + + inline void ExitBlock() { Stream.ExitBlock(); } + +}; + +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// External Interface. +//===----------------------------------------------------------------------===// + +ASTConsumer* clang::CreateSerializationTest() { + return new SerializationTest(); +} + +//===----------------------------------------------------------------------===// +// Serialization "Driver" code. +//===----------------------------------------------------------------------===// + +void SerializationTest::RunSerializationTest() { + std::string ErrMsg; + llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); + + if (Filename.isEmpty()) { + cerr << "Error: " << ErrMsg << "\n"; + return; + } + + Filename.appendComponent("test.cfe_bc"); + + if (Filename.makeUnique(true,&ErrMsg)) { + cerr << "Error: " << ErrMsg << "\n"; + return; + } + + if (!WriteAll(Filename)) + return; + + cout << "Wrote file: " << Filename.c_str() << "\n"; +} + +bool SerializationTest::WriteAll(llvm::sys::Path& Filename) { + std::ofstream Out(Filename.c_str()); + + if (!Out) { + cerr << "Error: Cannot open " << Filename.c_str() << "\n"; + return false; + } + + Writer W(Out); + W(*IdTable); + + W.getStream().FlushToWord(); + return true; +} + +//===----------------------------------------------------------------------===// +// Serialization Methods. +//===----------------------------------------------------------------------===// + +namespace llvm { + +struct IntrospectionPrimitivesFlags { + enum { isPod = true, UniqueInstances = false, UniqueRefs = false }; +}; + + +template<> struct +IntrospectionTrait<bool>::Flags : public IntrospectionPrimitivesFlags {}; + +template<> struct +IntrospectionTrait<unsigned>::Flags : public IntrospectionPrimitivesFlags {}; + +template<> struct +IntrospectionTrait<short>::Flags : public IntrospectionPrimitivesFlags {}; + + + +template<> +struct IntrospectionTrait<clang::IdentifierInfo>::Flags { + enum { isPod = false, // Cannot copy via memcpy. Must use copy-ctor. + hasUniqueInstances = true, // Two pointers with different + // addreses point to objects + // that are not equal to each other. + hasUniqueReferences = true // Two (non-temporary) pointers + // will point to distinct instances. + }; +}; + +template<> template<typename Introspector> +struct IntrospectionTrait<clang::IdentifierInfo>::Ops<Introspector> { + static void Introspect(clang::IdentifierInfo& X, Introspector& I) { +// I(X.getTokenID()); + I(X.getBuiltinID(),9); // FIXME: do 9 bit specialization. +// I(X.getObjCKeywordID()); + I(X.hasMacroDefinition()); + I(X.isExtensionToken()); + I(X.isPoisoned()); + I(X.isOtherTargetMacro()); + I(X.isCPlusPlusOperatorKeyword()); + I(X.isNonPortableBuiltin()); + } +}; + +template<> template<> +struct IntrospectionTrait<clang::IdentifierTable>::Ops<Writer> { + static void Introspect(clang::IdentifierTable& X, Writer& W) { + W.EnterSubblock<clang::IdentifierTable>(1); +/* + for (clang::IdentifierTable::iterator I = X.begin(), E = X.end(); + I != E; ++I) + W(I->getValue()); + */ + W.ExitBlock(); + } +}; + + + + +} // end namespace llvm + |