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