blob: 4a7137db6b8f84dbb10f092d30782c8edd9c2d17 [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
110 for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) {
111 llvm::cerr << "Serializing: Decl.\n";
112 Sezr.EmitOwnedPtr(*I);
113 }
114
115 Sezr.ExitBlock();
116
117 // ===---------------------------------------------------===/
Ted Kremenek018b3952007-11-06 19:50:53 +0000118 // Serialize the "Translation Unit" metadata.
119 // ===---------------------------------------------------===/
120
121 Sezr.EnterBlock(ContextBlock);
122
123 // "Fake" emit the SourceManager.
124 llvm::cerr << "Faux-serializing: SourceManager.\n";
125 Sezr.EmitPtr(&Context->SourceMgr);
126
127 // "Fake" emit the Target.
128 llvm::cerr << "Faux-serializing: Target.\n";
129 Sezr.EmitPtr(&Context->Target);
130
131 // "Fake" emit Selectors.
132 llvm::cerr << "Faux-serializing: Selectors.\n";
133 Sezr.EmitPtr(&Context->Selectors);
134
135 // Emit the Identifier Table.
136 llvm::cerr << "Serializing: IdentifierTable.\n";
137 Sezr.EmitOwnedPtr(&Context->Idents);
138
139 // Emit the ASTContext.
140 llvm::cerr << "Serializing: ASTContext.\n";
141 Sezr.EmitOwnedPtr(Context);
142
143 Sezr.ExitBlock();
144
145 // ===---------------------------------------------------===/
Ted Kremenek018b3952007-11-06 19:50:53 +0000146 // 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.
Ted Kremenek07c0fd92007-11-06 23:52:19 +0000191 if (ReadPreamble(Stream)) {
Ted Kremenek4ac81212007-11-05 21:39:35 +0000192 llvm::cerr << "ERROR: Invalid AST-bitcode signature.\n";
193 return;
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000194 }
195
196 // Create the deserializer.
Ted Kremenek018b3952007-11-06 19:50:53 +0000197 llvm::Deserializer Dezr(Stream);
198
199 // ===---------------------------------------------------===/
200 // Deserialize the "Translation Unit" metadata.
201 // ===---------------------------------------------------===/
202
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000203 // Skip to the block that has the SourceManager, etc.
204 bool FoundBlock = Dezr.SkipToBlock(ContextBlock);
205 assert (FoundBlock);
206
Ted Kremenek018b3952007-11-06 19:50:53 +0000207 // "Fake" read the SourceManager.
208 llvm::cerr << "Faux-Deserializing: SourceManager.\n";
209 Dezr.RegisterPtr(&Context->SourceMgr);
210
211 // "Fake" read the TargetInfo.
212 llvm::cerr << "Faux-Deserializing: Target.\n";
213 Dezr.RegisterPtr(&Context->Target);
214
215 // "Fake" read the Selectors.
216 llvm::cerr << "Faux-Deserializing: Selectors.\n";
217 Dezr.RegisterPtr(&Context->Selectors);
218
219 // Read the identifier table.
220 llvm::cerr << "Deserializing: IdentifierTable\n";
221 Dezr.ReadOwnedPtr<IdentifierTable>();
222
223 // Read the ASTContext.
224 llvm::cerr << "Deserializing: ASTContext.\n";
225 Dezr.ReadOwnedPtr<ASTContext>();
226
227 // Create a printer to "consume" our deserialized ASTS.
228 ASTConsumer* Printer = CreateASTPrinter();
229 Janitor<ASTConsumer> PrinterJanitor(Printer);
230
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000231 // "Rewind" the stream. Find the block with the serialized top-level decls.
232 Dezr.Rewind();
233 FoundBlock = Dezr.SkipToBlock(DeclBlock);
234 assert (FoundBlock);
235 llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
236
Ted Kremenek018b3952007-11-06 19:50:53 +0000237 // The remaining objects in the file are top-level decls.
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000238 while (!Dezr.FinishedBlock(DeclBlockLoc)) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000239 llvm::cerr << "Deserializing: Decl.\n";
240 Decl* decl = Dezr.ReadOwnedPtr<Decl>();
241 Printer->HandleTopLevelDecl(decl);
242 }
243}
244
245
246SerializationTest::~SerializationTest() {
247
248 std::string ErrMsg;
249 llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
250
251 if (Filename.isEmpty()) {
252 llvm::cerr << "Error: " << ErrMsg << "\n";
253 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000254 }
255
Ted Kremenek018b3952007-11-06 19:50:53 +0000256 Filename.appendComponent("test.ast");
Ted Kremenek4ac81212007-11-05 21:39:35 +0000257
Ted Kremenek018b3952007-11-06 19:50:53 +0000258 if (Filename.makeUnique(true,&ErrMsg)) {
259 llvm::cerr << "Error: " << ErrMsg << "\n";
260 return;
261 }
Ted Kremenek4ac81212007-11-05 21:39:35 +0000262
Ted Kremenek018b3952007-11-06 19:50:53 +0000263 Serialize(Filename);
264 Deserialize(Filename);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000265}