blob: 19015914208d22f894385c53a0184164ebe233cc [file] [log] [blame]
Ted Kremenekbfa82c42007-10-16 23:37:27 +00001//===--- SerializationTest.cpp - Experimental Object Serialization --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements prototype code for serialization of objects in clang.
11// It is not intended yet for public use, but simply is a placeholder to
12// experiment with new serialization features. Serialization will eventually
13// be integrated as a proper component of the clang libraries.
14//
15//===----------------------------------------------------------------------===//
16
17#include "ASTConsumers.h"
18#include "clang/AST/AST.h"
19#include "clang/AST/ASTConsumer.h"
20#include "clang/AST/ASTContext.h"
21#include "llvm/System/Path.h"
22#include "llvm/Bitcode/BitstreamWriter.h"
23#include <fstream>
Anders Carlssonadc9b132007-10-17 00:50:25 +000024#include <iostream>
Ted Kremenekbfa82c42007-10-16 23:37:27 +000025
26using namespace clang;
27using llvm::BitstreamWriter;
28using std::cerr;
29using std::cout;
30using std::endl;
31using std::flush;
32
33namespace llvm {
34template<typename T> struct IntrospectionTrait {
35 struct Flags {
36 enum { isPod = false, UniqueInstances = false, UniqueRefs = false };
37 };
38
39 template<typename Introspector>
40 struct Ops {
41 static inline void Introspect(T& X, Introspector& I) {
42 assert (false && "Introspect not implemented.");
43 }
44 };
45};
46}
47
48namespace {
49class SerializationTest : public ASTConsumer {
50 IdentifierTable* IdTable;
51 unsigned MainFileID;
52public:
53 void Initialize(ASTContext& Context, unsigned mainFileID) {
54 IdTable = &Context.Idents;
55 MainFileID = mainFileID;
56 RunSerializationTest();
57 }
58
59 void RunSerializationTest();
60 bool WriteAll(llvm::sys::Path& Filename);
61
62 virtual void HandleTopLevelDecl(Decl *D) {}
63};
64
65class Writer {
66 std::vector<unsigned char> Buffer;
67 BitstreamWriter Stream;
68 std::ostream& Out;
69public:
70
71 enum { IdentifierTableBID = 0x8 };
72
73 Writer(std::ostream& out) : Stream(Buffer), Out(out) {
74 Buffer.reserve(256*1024);
75
76 // Emit the file header.
77 Stream.Emit((unsigned)'B', 8);
78 Stream.Emit((unsigned)'C', 8);
79 Stream.Emit(0xC, 4);
80 Stream.Emit(0xF, 4);
81 Stream.Emit(0xE, 4);
82 Stream.Emit(0x0, 4);
83 }
84
85 ~Writer() {
86 Out.write((char*)&Buffer.front(), Buffer.size());
87 Out.flush();
88 }
89
90 template <typename T> inline void operator()(T& x) {
91 llvm::IntrospectionTrait<T>::template Ops<Writer>::Introspect(x,*this);
92 }
93
94 template <typename T> inline void operator()(T& x, unsigned bits) {
95 llvm::IntrospectionTrait<T>::template Ops<Writer>::Introspect(x,bits,*this);
96 }
97
98 template <typename T> inline void operator()(const T& x) {
99 operator()(const_cast<T&>(x));
100 }
101
102 template <typename T> inline void operator()(const T& x, unsigned bits) {
103 operator()(const_cast<T&>(x),bits);
104 }
105
106 inline void operator()(bool X) { Stream.Emit(X,1); }
107 inline void operator()(unsigned X) { Stream.Emit(X,32); }
108 inline void operator()(unsigned X, unsigned bits, bool VBR=false) {
109 if (VBR) Stream.Emit(X,bits);
110 else Stream.Emit(X,bits);
111 }
112
113 inline BitstreamWriter& getStream() {
114 return Stream;
115 }
116
117 template <typename T> inline void EnterSubblock(unsigned CodeLen) {
118 Stream.EnterSubblock(8,CodeLen);
119 }
120
121 inline void ExitBlock() { Stream.ExitBlock(); }
122
123};
124
125} // end anonymous namespace
126
127//===----------------------------------------------------------------------===//
128// External Interface.
129//===----------------------------------------------------------------------===//
130
131ASTConsumer* clang::CreateSerializationTest() {
132 return new SerializationTest();
133}
134
135//===----------------------------------------------------------------------===//
136// Serialization "Driver" code.
137//===----------------------------------------------------------------------===//
138
139void SerializationTest::RunSerializationTest() {
140 std::string ErrMsg;
141 llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
142
143 if (Filename.isEmpty()) {
144 cerr << "Error: " << ErrMsg << "\n";
145 return;
146 }
147
148 Filename.appendComponent("test.cfe_bc");
149
150 if (Filename.makeUnique(true,&ErrMsg)) {
151 cerr << "Error: " << ErrMsg << "\n";
152 return;
153 }
154
155 if (!WriteAll(Filename))
156 return;
157
158 cout << "Wrote file: " << Filename.c_str() << "\n";
159}
160
161bool SerializationTest::WriteAll(llvm::sys::Path& Filename) {
162 std::ofstream Out(Filename.c_str());
163
164 if (!Out) {
165 cerr << "Error: Cannot open " << Filename.c_str() << "\n";
166 return false;
167 }
168
169 Writer W(Out);
170 W(*IdTable);
171
172 W.getStream().FlushToWord();
173 return true;
174}
175
176//===----------------------------------------------------------------------===//
177// Serialization Methods.
178//===----------------------------------------------------------------------===//
179
180namespace llvm {
181
182struct IntrospectionPrimitivesFlags {
183 enum { isPod = true, UniqueInstances = false, UniqueRefs = false };
184};
185
186
187template<> struct
188IntrospectionTrait<bool>::Flags : public IntrospectionPrimitivesFlags {};
189
190template<> struct
191IntrospectionTrait<unsigned>::Flags : public IntrospectionPrimitivesFlags {};
192
193template<> struct
194IntrospectionTrait<short>::Flags : public IntrospectionPrimitivesFlags {};
195
196
197
198template<>
Hartmut Kaiser7b660002007-10-17 15:00:17 +0000199struct IntrospectionTrait<clang::IdentifierInfo> {
200
201 struct Flags {
202 enum { isPod = false, // Cannot copy via memcpy. Must use copy-ctor.
203 hasUniqueInstances = true, // Two pointers with different
204 // addreses point to objects
205 // that are not equal to each other.
206 hasUniqueReferences = true // Two (non-temporary) pointers
207 // will point to distinct instances.
208 };
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000209 };
Hartmut Kaiser7b660002007-10-17 15:00:17 +0000210
211 template<typename Introspector>
212 struct Ops {
213 static void Introspect(clang::IdentifierInfo& X, Introspector& I) {
214 // I(X.getTokenID());
215 I(X.getBuiltinID(),9); // FIXME: do 9 bit specialization.
216 // I(X.getObjCKeywordID());
217 I(X.hasMacroDefinition());
218 I(X.isExtensionToken());
219 I(X.isPoisoned());
220 I(X.isOtherTargetMacro());
221 I(X.isCPlusPlusOperatorKeyword());
222 I(X.isNonPortableBuiltin());
223 }
224 };
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000225};
226
227template<> template<>
228struct IntrospectionTrait<clang::IdentifierTable>::Ops<Writer> {
229 static void Introspect(clang::IdentifierTable& X, Writer& W) {
230 W.EnterSubblock<clang::IdentifierTable>(1);
231/*
232 for (clang::IdentifierTable::iterator I = X.begin(), E = X.end();
233 I != E; ++I)
234 W(I->getValue());
235 */
236 W.ExitBlock();
237 }
238};
239
240
241
242
243} // end namespace llvm
244