blob: 075fcba2e08c3759ba7f5c2c160a08af3f1c2371 [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
Ted Kremenek07c0fd92007-11-06 23:52:19 +000082static bool ReadPreamble(llvm::BitstreamReader& Stream) {
Ted Kremenek018b3952007-11-06 19:50:53 +000083 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 // ===---------------------------------------------------===/
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000105 // Serialize the top-level decls.
106 // ===---------------------------------------------------===/
107
108 Sezr.EnterBlock(DeclBlock);
109
Ted Kremeneke7201982007-11-13 22:56:10 +0000110 // Create a printer to "consume" our deserialized ASTS.
111 ASTConsumer* Printer = CreateASTPrinter();
112 Janitor<ASTConsumer> PrinterJanitor(Printer);
113
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000114 for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) {
Ted Kremeneke7201982007-11-13 22:56:10 +0000115 llvm::cerr << "Serializing: Decl.\n";
116
117 Printer->HandleTopLevelDecl(*I);
118
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000119 Sezr.EmitOwnedPtr(*I);
120 }
121
122 Sezr.ExitBlock();
123
124 // ===---------------------------------------------------===/
Ted Kremenek018b3952007-11-06 19:50:53 +0000125 // Serialize the "Translation Unit" metadata.
126 // ===---------------------------------------------------===/
127
128 Sezr.EnterBlock(ContextBlock);
129
130 // "Fake" emit the SourceManager.
131 llvm::cerr << "Faux-serializing: SourceManager.\n";
132 Sezr.EmitPtr(&Context->SourceMgr);
133
134 // "Fake" emit the Target.
135 llvm::cerr << "Faux-serializing: Target.\n";
136 Sezr.EmitPtr(&Context->Target);
137
138 // "Fake" emit Selectors.
139 llvm::cerr << "Faux-serializing: Selectors.\n";
140 Sezr.EmitPtr(&Context->Selectors);
141
142 // Emit the Identifier Table.
143 llvm::cerr << "Serializing: IdentifierTable.\n";
144 Sezr.EmitOwnedPtr(&Context->Idents);
145
146 // Emit the ASTContext.
147 llvm::cerr << "Serializing: ASTContext.\n";
148 Sezr.EmitOwnedPtr(Context);
149
150 Sezr.ExitBlock();
151
152 // ===---------------------------------------------------===/
Ted Kremenek018b3952007-11-06 19:50:53 +0000153 // Finalize serialization: write the bits to disk.
154 // ===---------------------------------------------------===/
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000155
156 if (FILE *fp = fopen(Filename.c_str(),"wb")) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000157 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000158 fclose(fp);
159 }
160 else {
161 llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n";
Ted Kremenek4ac81212007-11-05 21:39:35 +0000162 return;
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000163 }
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000164
Ted Kremenek018b3952007-11-06 19:50:53 +0000165 llvm::cerr << "Commited bitstream to disk: " << Filename.c_str() << "\n";
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000166}
167
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000168
Ted Kremenek018b3952007-11-06 19:50:53 +0000169void SerializationTest::Deserialize(llvm::sys::Path& Filename) {
170
171 // Create the memory buffer that contains the contents of the file.
172
173 using llvm::MemoryBuffer;
174
175 MemoryBuffer* MBuffer = MemoryBuffer::getFile(Filename.c_str(),
176 strlen(Filename.c_str()));
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000177
Ted Kremenek4ac81212007-11-05 21:39:35 +0000178 if(!MBuffer) {
179 llvm::cerr << "ERROR: Cannot read file for deserialization.\n";
180 return;
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000181 }
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000182
Ted Kremenek018b3952007-11-06 19:50:53 +0000183 // Create an "autocollector" object to release the memory buffer upon
184 // termination of the current scope.
185 Janitor<MemoryBuffer> AutoReleaseBuffer(MBuffer);
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000186
Ted Kremenek018b3952007-11-06 19:50:53 +0000187 // Check if the file is of the proper length.
Ted Kremenek4ac81212007-11-05 21:39:35 +0000188 if (MBuffer->getBufferSize() & 0x3) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000189 llvm::cerr << "ERROR: AST file length should be a multiple of 4 bytes.\n";
Ted Kremenek4ac81212007-11-05 21:39:35 +0000190 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000191 }
192
Ted Kremenek018b3952007-11-06 19:50:53 +0000193 // Create the bitstream reader.
194 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
195 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000196
Ted Kremenek018b3952007-11-06 19:50:53 +0000197 // Sniff for the signature in the bitcode file.
Ted Kremenek07c0fd92007-11-06 23:52:19 +0000198 if (ReadPreamble(Stream)) {
Ted Kremenek4ac81212007-11-05 21:39:35 +0000199 llvm::cerr << "ERROR: Invalid AST-bitcode signature.\n";
200 return;
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000201 }
202
203 // Create the deserializer.
Ted Kremenek018b3952007-11-06 19:50:53 +0000204 llvm::Deserializer Dezr(Stream);
205
206 // ===---------------------------------------------------===/
207 // Deserialize the "Translation Unit" metadata.
208 // ===---------------------------------------------------===/
209
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000210 // Skip to the block that has the SourceManager, etc.
211 bool FoundBlock = Dezr.SkipToBlock(ContextBlock);
212 assert (FoundBlock);
213
Ted Kremenek018b3952007-11-06 19:50:53 +0000214 // "Fake" read the SourceManager.
215 llvm::cerr << "Faux-Deserializing: SourceManager.\n";
216 Dezr.RegisterPtr(&Context->SourceMgr);
217
218 // "Fake" read the TargetInfo.
219 llvm::cerr << "Faux-Deserializing: Target.\n";
220 Dezr.RegisterPtr(&Context->Target);
221
222 // "Fake" read the Selectors.
223 llvm::cerr << "Faux-Deserializing: Selectors.\n";
224 Dezr.RegisterPtr(&Context->Selectors);
225
226 // Read the identifier table.
227 llvm::cerr << "Deserializing: IdentifierTable\n";
228 Dezr.ReadOwnedPtr<IdentifierTable>();
229
230 // Read the ASTContext.
231 llvm::cerr << "Deserializing: ASTContext.\n";
232 Dezr.ReadOwnedPtr<ASTContext>();
233
234 // Create a printer to "consume" our deserialized ASTS.
235 ASTConsumer* Printer = CreateASTPrinter();
236 Janitor<ASTConsumer> PrinterJanitor(Printer);
237
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000238 // "Rewind" the stream. Find the block with the serialized top-level decls.
239 Dezr.Rewind();
240 FoundBlock = Dezr.SkipToBlock(DeclBlock);
241 assert (FoundBlock);
242 llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
243
Ted Kremenek018b3952007-11-06 19:50:53 +0000244 // The remaining objects in the file are top-level decls.
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000245 while (!Dezr.FinishedBlock(DeclBlockLoc)) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000246 llvm::cerr << "Deserializing: Decl.\n";
247 Decl* decl = Dezr.ReadOwnedPtr<Decl>();
248 Printer->HandleTopLevelDecl(decl);
249 }
250}
251
252
253SerializationTest::~SerializationTest() {
254
255 std::string ErrMsg;
256 llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
257
258 if (Filename.isEmpty()) {
259 llvm::cerr << "Error: " << ErrMsg << "\n";
260 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000261 }
262
Ted Kremenek018b3952007-11-06 19:50:53 +0000263 Filename.appendComponent("test.ast");
Ted Kremenek4ac81212007-11-05 21:39:35 +0000264
Ted Kremenek018b3952007-11-06 19:50:53 +0000265 if (Filename.makeUnique(true,&ErrMsg)) {
266 llvm::cerr << "Error: " << ErrMsg << "\n";
267 return;
268 }
Ted Kremenek4ac81212007-11-05 21:39:35 +0000269
Ted Kremenek018b3952007-11-06 19:50:53 +0000270 Serialize(Filename);
271 Deserialize(Filename);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000272}