blob: 856ef75469ca219c4e60f8b86448dc4dc5e7156e [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"
Ted Kremenekc637e6b2007-10-23 22:18:37 +000022#include "llvm/Support/Streams.h"
23#include "llvm/Support/MemoryBuffer.h"
Ted Kremeneka2bfb912007-10-24 19:06:02 +000024#include "llvm/Bitcode/Serialize.h"
25#include "llvm/Bitcode/Deserialize.h"
Ted Kremenekc637e6b2007-10-23 22:18:37 +000026#include <stdio.h>
Ted Kremenek018b3952007-11-06 19:50:53 +000027#include <list>
Ted Kremenekc637e6b2007-10-23 22:18:37 +000028
29//===----------------------------------------------------------------------===//
30// Driver code.
31//===----------------------------------------------------------------------===//
Ted Kremenekbfa82c42007-10-16 23:37:27 +000032
33using namespace clang;
Ted Kremenek4ac81212007-11-05 21:39:35 +000034using llvm::sys::TimeValue;
Ted Kremenekbfa82c42007-10-16 23:37:27 +000035
36namespace {
Ted Kremenekbfa82c42007-10-16 23:37:27 +000037
Ted Kremenek4ac81212007-11-05 21:39:35 +000038template<typename T> struct Janitor {
39 T* Obj;
40 Janitor(T* obj) : Obj(obj) {}
41 ~Janitor() { delete Obj; }
42};
43
44class SerializationTest : public ASTConsumer {
45 ASTContext* Context;
Ted Kremenek018b3952007-11-06 19:50:53 +000046 std::list<Decl*> Decls;
Ted Kremenek4ac81212007-11-05 21:39:35 +000047
Ted Kremenek018b3952007-11-06 19:50:53 +000048 enum { ContextBlock = 0x1, DeclBlock = 0x3 };
49
50public:
51 SerializationTest() : Context(NULL) {};
Ted Kremenek4ac81212007-11-05 21:39:35 +000052 ~SerializationTest();
53
Ted Kremenek018b3952007-11-06 19:50:53 +000054 virtual void Initialize(ASTContext& context, unsigned) {
55 Context = &context;
56 }
57
58 virtual void HandleTopLevelDecl(Decl *D) {
59 Decls.push_back(D);
60 }
61
62private:
63 void Serialize(llvm::sys::Path& Filename);
64 void Deserialize(llvm::sys::Path& Filename);
Ted Kremenek4ac81212007-11-05 21:39:35 +000065};
66
Ted Kremenekc637e6b2007-10-23 22:18:37 +000067} // end anonymous namespace
Ted Kremenekbfa82c42007-10-16 23:37:27 +000068
Ted Kremenek018b3952007-11-06 19:50:53 +000069ASTConsumer* clang::CreateSerializationTest() {
70 return new SerializationTest();
71}
72
73static void WritePreamble(llvm::BitstreamWriter& Stream) {
74 Stream.Emit((unsigned)'B', 8);
75 Stream.Emit((unsigned)'C', 8);
76 Stream.Emit(0xC, 4);
77 Stream.Emit(0xF, 4);
78 Stream.Emit(0xE, 4);
79 Stream.Emit(0x0, 4);
80}
81
82static bool ReadPremable(llvm::BitstreamReader& Stream) {
83 return Stream.Read(8) != 'B' ||
84 Stream.Read(8) != 'C' ||
85 Stream.Read(4) != 0xC ||
86 Stream.Read(4) != 0xF ||
87 Stream.Read(4) != 0xE ||
88 Stream.Read(4) != 0x0;
89}
90
91void SerializationTest::Serialize(llvm::sys::Path& Filename) {
Ted Kremenekc637e6b2007-10-23 22:18:37 +000092
Ted Kremenek018b3952007-11-06 19:50:53 +000093 // Reserve 256K for bitstream buffer.
94 std::vector<unsigned char> Buffer;
95 Buffer.reserve(256*1024);
96
97 // Create bitstream and write preamble.
98 llvm::BitstreamWriter Stream(Buffer);
99 WritePreamble(Stream);
100
101 // Create serializer.
102 llvm::Serializer Sezr(Stream);
103
104 // ===---------------------------------------------------===/
105 // Serialize the "Translation Unit" metadata.
106 // ===---------------------------------------------------===/
107
108 Sezr.EnterBlock(ContextBlock);
109
110 // "Fake" emit the SourceManager.
111 llvm::cerr << "Faux-serializing: SourceManager.\n";
112 Sezr.EmitPtr(&Context->SourceMgr);
113
114 // "Fake" emit the Target.
115 llvm::cerr << "Faux-serializing: Target.\n";
116 Sezr.EmitPtr(&Context->Target);
117
118 // "Fake" emit Selectors.
119 llvm::cerr << "Faux-serializing: Selectors.\n";
120 Sezr.EmitPtr(&Context->Selectors);
121
122 // Emit the Identifier Table.
123 llvm::cerr << "Serializing: IdentifierTable.\n";
124 Sezr.EmitOwnedPtr(&Context->Idents);
125
126 // Emit the ASTContext.
127 llvm::cerr << "Serializing: ASTContext.\n";
128 Sezr.EmitOwnedPtr(Context);
129
130 Sezr.ExitBlock();
131
132 // ===---------------------------------------------------===/
133 // Serialize the top-level decls.
134 // ===---------------------------------------------------===/
135
136 Sezr.EnterBlock(DeclBlock);
137
138 for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) {
139 llvm::cerr << "Serializing: Decl.\n";
140 Sezr.EmitOwnedPtr(*I);
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000141 }
Ted Kremenek018b3952007-11-06 19:50:53 +0000142
143 Sezr.ExitBlock();
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000144
Ted Kremenek018b3952007-11-06 19:50:53 +0000145 // ===---------------------------------------------------===/
146 // Finalize serialization: write the bits to disk.
147 // ===---------------------------------------------------===/
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000148
149 if (FILE *fp = fopen(Filename.c_str(),"wb")) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000150 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000151 fclose(fp);
152 }
153 else {
154 llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n";
Ted Kremenek4ac81212007-11-05 21:39:35 +0000155 return;
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000156 }
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000157
Ted Kremenek018b3952007-11-06 19:50:53 +0000158 llvm::cerr << "Commited bitstream to disk: " << Filename.c_str() << "\n";
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000159}
160
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000161
Ted Kremenek018b3952007-11-06 19:50:53 +0000162void SerializationTest::Deserialize(llvm::sys::Path& Filename) {
163
164 // Create the memory buffer that contains the contents of the file.
165
166 using llvm::MemoryBuffer;
167
168 MemoryBuffer* MBuffer = MemoryBuffer::getFile(Filename.c_str(),
169 strlen(Filename.c_str()));
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000170
Ted Kremenek4ac81212007-11-05 21:39:35 +0000171 if(!MBuffer) {
172 llvm::cerr << "ERROR: Cannot read file for deserialization.\n";
173 return;
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000174 }
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000175
Ted Kremenek018b3952007-11-06 19:50:53 +0000176 // Create an "autocollector" object to release the memory buffer upon
177 // termination of the current scope.
178 Janitor<MemoryBuffer> AutoReleaseBuffer(MBuffer);
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000179
Ted Kremenek018b3952007-11-06 19:50:53 +0000180 // Check if the file is of the proper length.
Ted Kremenek4ac81212007-11-05 21:39:35 +0000181 if (MBuffer->getBufferSize() & 0x3) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000182 llvm::cerr << "ERROR: AST file length should be a multiple of 4 bytes.\n";
Ted Kremenek4ac81212007-11-05 21:39:35 +0000183 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000184 }
185
Ted Kremenek018b3952007-11-06 19:50:53 +0000186 // Create the bitstream reader.
187 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
188 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000189
Ted Kremenek018b3952007-11-06 19:50:53 +0000190 // Sniff for the signature in the bitcode file.
191 if (!ReadPremable(Stream)) {
Ted Kremenek4ac81212007-11-05 21:39:35 +0000192 llvm::cerr << "ERROR: Invalid AST-bitcode signature.\n";
193 return;
Ted Kremenek018b3952007-11-06 19:50:53 +0000194 }
195
196 // Create the Dezr.
197 llvm::Deserializer Dezr(Stream);
198
199 // ===---------------------------------------------------===/
200 // Deserialize the "Translation Unit" metadata.
201 // ===---------------------------------------------------===/
202
203 // "Fake" read the SourceManager.
204 llvm::cerr << "Faux-Deserializing: SourceManager.\n";
205 Dezr.RegisterPtr(&Context->SourceMgr);
206
207 // "Fake" read the TargetInfo.
208 llvm::cerr << "Faux-Deserializing: Target.\n";
209 Dezr.RegisterPtr(&Context->Target);
210
211 // "Fake" read the Selectors.
212 llvm::cerr << "Faux-Deserializing: Selectors.\n";
213 Dezr.RegisterPtr(&Context->Selectors);
214
215 // Read the identifier table.
216 llvm::cerr << "Deserializing: IdentifierTable\n";
217 Dezr.ReadOwnedPtr<IdentifierTable>();
218
219 // Read the ASTContext.
220 llvm::cerr << "Deserializing: ASTContext.\n";
221 Dezr.ReadOwnedPtr<ASTContext>();
222
223 // Create a printer to "consume" our deserialized ASTS.
224 ASTConsumer* Printer = CreateASTPrinter();
225 Janitor<ASTConsumer> PrinterJanitor(Printer);
226
227 // The remaining objects in the file are top-level decls.
228 while (!Dezr.AtEnd()) {
229 llvm::cerr << "Deserializing: Decl.\n";
230 Decl* decl = Dezr.ReadOwnedPtr<Decl>();
231 Printer->HandleTopLevelDecl(decl);
232 }
233}
234
235
236SerializationTest::~SerializationTest() {
237
238 std::string ErrMsg;
239 llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
240
241 if (Filename.isEmpty()) {
242 llvm::cerr << "Error: " << ErrMsg << "\n";
243 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000244 }
245
Ted Kremenek018b3952007-11-06 19:50:53 +0000246 Filename.appendComponent("test.ast");
Ted Kremenek4ac81212007-11-05 21:39:35 +0000247
Ted Kremenek018b3952007-11-06 19:50:53 +0000248 if (Filename.makeUnique(true,&ErrMsg)) {
249 llvm::cerr << "Error: " << ErrMsg << "\n";
250 return;
251 }
Ted Kremenek4ac81212007-11-05 21:39:35 +0000252
Ted Kremenek018b3952007-11-06 19:50:53 +0000253 Serialize(Filename);
254 Deserialize(Filename);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000255}