blob: 7e1884a0d7a21b2873946c87e602ae4b7931e77d [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"
Ted Kremenek634cadf2007-10-23 22:18:37 +000022#include "llvm/Support/Streams.h"
23#include "llvm/Support/MemoryBuffer.h"
Ted Kremenekce797d92007-10-24 19:06:02 +000024#include "llvm/Bitcode/Serialize.h"
25#include "llvm/Bitcode/Deserialize.h"
Ted Kremenek47916ee2007-11-05 21:39:35 +000026#include "llvm/System/TimeValue.h"
Ted Kremenek634cadf2007-10-23 22:18:37 +000027#include <stdio.h>
28
29//===----------------------------------------------------------------------===//
30// Driver code.
31//===----------------------------------------------------------------------===//
Ted Kremenek221bb8d2007-10-16 23:37:27 +000032
33using namespace clang;
Ted Kremenek47916ee2007-11-05 21:39:35 +000034using llvm::sys::TimeValue;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000035
36namespace {
Ted Kremenek221bb8d2007-10-16 23:37:27 +000037
Ted Kremenek47916ee2007-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;
46 llvm::sys::Path Filename;
47 std::vector<unsigned char>* Buffer;
48 llvm::BitstreamWriter* OBStream;
49 llvm::Serializer* serializer;
50
51 void DeserializeTest();
52public:
53
54 SerializationTest(llvm::sys::Path filename);
55 ~SerializationTest();
56
57 virtual void Initialize(ASTContext& context, unsigned);
58 virtual void HandleTopLevelDecl(Decl *D);
59};
60
Ted Kremenek634cadf2007-10-23 22:18:37 +000061} // end anonymous namespace
Ted Kremenek221bb8d2007-10-16 23:37:27 +000062
63ASTConsumer* clang::CreateSerializationTest() {
Ted Kremenek221bb8d2007-10-16 23:37:27 +000064 std::string ErrMsg;
65 llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek634cadf2007-10-23 22:18:37 +000066
Ted Kremenek221bb8d2007-10-16 23:37:27 +000067 if (Filename.isEmpty()) {
Ted Kremenek634cadf2007-10-23 22:18:37 +000068 llvm::cerr << "Error: " << ErrMsg << "\n";
Ted Kremenek47916ee2007-11-05 21:39:35 +000069 return NULL;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000070 }
71
Ted Kremenek634cadf2007-10-23 22:18:37 +000072 Filename.appendComponent("test.ast");
Ted Kremenek221bb8d2007-10-16 23:37:27 +000073
74 if (Filename.makeUnique(true,&ErrMsg)) {
Ted Kremenek634cadf2007-10-23 22:18:37 +000075 llvm::cerr << "Error: " << ErrMsg << "\n";
Ted Kremenek47916ee2007-11-05 21:39:35 +000076 return NULL;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000077 }
78
Ted Kremenek47916ee2007-11-05 21:39:35 +000079 return new SerializationTest(Filename);
Ted Kremenek221bb8d2007-10-16 23:37:27 +000080}
81
Ted Kremenek47916ee2007-11-05 21:39:35 +000082SerializationTest::SerializationTest(llvm::sys::Path filename)
83 : Filename(filename), OBStream(NULL), serializer(NULL) {
84
85 // Reserve 256K for bitstream buffer.
86 Buffer = new std::vector<unsigned char>();
87 assert (Buffer && "Could not allocate buffer.");
88 Buffer->reserve(256*1024);
89
90 // Open bitstream and write preamble.
91 OBStream = new llvm::BitstreamWriter(*Buffer);
92 assert (OBStream && "could not create bitstream for serialization");
93
94 OBStream->Emit((unsigned)'B', 8);
95 OBStream->Emit((unsigned)'C', 8);
96 OBStream->Emit(0xC, 4);
97 OBStream->Emit(0xF, 4);
98 OBStream->Emit(0xE, 4);
99 OBStream->Emit(0x0, 4);
100
101 // Open serializer.
102 serializer = new llvm::Serializer(*OBStream,0);
103 assert (serializer && "could not create serializer");
104}
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000105
Ted Kremenek634cadf2007-10-23 22:18:37 +0000106
Ted Kremenek47916ee2007-11-05 21:39:35 +0000107void SerializationTest::Initialize(ASTContext& context, unsigned) {
108 llvm::cerr << "[ " << TimeValue::now().toString() << " ] "
109 << "Faux-serializing: SourceManager et al.\n";
110
111 serializer->EnterBlock();
112 // "Fake" emit the SourceManager, etc.
113 Context = &context;
114 serializer->EmitPtr(&context.SourceMgr);
115 serializer->EmitPtr(&context.Target);
116 serializer->EmitPtr(&context.Idents);
117 serializer->EmitPtr(&context.Selectors);
118
119 llvm::cerr << "[ " << TimeValue::now().toString() << " ] "
120 << "Serializing: ASTContext.\n";
121
122
123 serializer->EmitOwnedPtr(&context);
124 serializer->ExitBlock();
125}
126
127void SerializationTest::HandleTopLevelDecl(Decl *D) {
128 llvm::cerr << "[ " << TimeValue::now().toString() << " ] "
129 << "Serializing: Decl.\n";
130
131 serializer->EnterBlock();
132 serializer->EmitOwnedPtr(D);
133 serializer->ExitBlock();
134}
135
136SerializationTest::~SerializationTest() {
137 delete serializer;
138 delete OBStream;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000139
140 if (FILE *fp = fopen(Filename.c_str(),"wb")) {
Ted Kremenek47916ee2007-11-05 21:39:35 +0000141 fwrite((char*)&Buffer->front(), sizeof(char), Buffer->size(), fp);
142 delete Buffer;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000143 fclose(fp);
144 }
145 else {
146 llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n";
Ted Kremenek47916ee2007-11-05 21:39:35 +0000147 delete Buffer;
148 return;
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000149 }
Ted Kremenek47916ee2007-11-05 21:39:35 +0000150
151 llvm::cerr << "[ " << TimeValue::now().toString() << " ] "
152 << "Commited bitstream to disk: " << Filename.c_str() << "\n";
Ted Kremenek634cadf2007-10-23 22:18:37 +0000153
Ted Kremenek47916ee2007-11-05 21:39:35 +0000154 DeserializeTest();
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000155}
156
Ted Kremenek47916ee2007-11-05 21:39:35 +0000157void SerializationTest::DeserializeTest() {
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000158
Ted Kremenek47916ee2007-11-05 21:39:35 +0000159 llvm::MemoryBuffer* MBuffer =
Ted Kremenek634cadf2007-10-23 22:18:37 +0000160 llvm::MemoryBuffer::getFile(Filename.c_str(), strlen(Filename.c_str()));
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000161
Ted Kremenek47916ee2007-11-05 21:39:35 +0000162 if(!MBuffer) {
163 llvm::cerr << "ERROR: Cannot read file for deserialization.\n";
164 return;
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000165 }
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000166
Ted Kremenek47916ee2007-11-05 21:39:35 +0000167 Janitor<llvm::MemoryBuffer> AutoReleaseBuffer(MBuffer);
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000168
Ted Kremenek47916ee2007-11-05 21:39:35 +0000169 if (MBuffer->getBufferSize() & 0x3) {
170 llvm::cerr << "ERROR: AST file should be a multiple of 4 bytes in length.\n";
171 return;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000172 }
173
Ted Kremenek47916ee2007-11-05 21:39:35 +0000174 unsigned char *BufPtr = (unsigned char *)MBuffer->getBufferStart();
175 llvm::BitstreamReader IBStream(BufPtr,BufPtr+MBuffer->getBufferSize());
Ted Kremenek634cadf2007-10-23 22:18:37 +0000176
177 // Sniff for the signature.
Ted Kremenek47916ee2007-11-05 21:39:35 +0000178 if (IBStream.Read(8) != 'B' ||
179 IBStream.Read(8) != 'C' ||
180 IBStream.Read(4) != 0xC ||
181 IBStream.Read(4) != 0xF ||
182 IBStream.Read(4) != 0xE ||
183 IBStream.Read(4) != 0x0) {
184 llvm::cerr << "ERROR: Invalid AST-bitcode signature.\n";
185 return;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000186 }
187
Ted Kremenek47916ee2007-11-05 21:39:35 +0000188 llvm::Deserializer deserializer(IBStream);
189
190
191 // "Fake" read the SourceManager, etc.
192 llvm::cerr << "[ " << TimeValue::now().toString() << " ] "
193 << "Faux-Deserializing: SourceManager et al.\n";
194
195 deserializer.RegisterPtr(&Context->SourceMgr);
196 deserializer.RegisterPtr(&Context->Target);
197 deserializer.RegisterPtr(&Context->Idents);
198 deserializer.RegisterPtr(&Context->Selectors);
199
200 llvm::cerr << "[ " << TimeValue::now().toString() << " ] "
201 << "Deserializing: ASTContext.\n";
Ted Kremenek221bb8d2007-10-16 23:37:27 +0000202
Ted Kremenek47916ee2007-11-05 21:39:35 +0000203 // Deserialize the AST context.
204 deserializer.ReadOwnedPtr<ASTContext>();
205// ASTContext* context =
Ted Kremenek634cadf2007-10-23 22:18:37 +0000206}