blob: 708328db77dbceb63d111ca0e48370c360931fe8 [file] [log] [blame]
Ted Kremenekbfa82c42007-10-16 23:37:27 +00001//===--- SerializationTest.cpp - Experimental Object Serialization --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Ted Kremenekbfa82c42007-10-16 23:37:27 +00007//
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
Ted Kremenekbfa82c42007-10-16 23:37:27 +000017#include "clang/AST/ASTConsumer.h"
Chris Lattner1266eca2009-03-28 04:31:31 +000018#include "clang/AST/ASTContext.h"
Ted Kremenek5656b782007-11-29 01:24:25 +000019#include "clang/AST/CFG.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000020#include "clang/AST/Decl.h"
Chris Lattner682bf922009-03-29 16:50:03 +000021#include "clang/AST/DeclGroup.h"
Ted Kremenekc2542b62009-03-31 18:58:14 +000022#include "clang-cc.h"
Ted Kremenek35537662007-12-05 22:08:43 +000023#include "ASTConsumers.h"
Ted Kremenekc637e6b2007-10-23 22:18:37 +000024#include "llvm/Support/MemoryBuffer.h"
Ted Kremenekee533642007-12-20 19:47:16 +000025#include "llvm/ADT/OwningPtr.h"
Ted Kremenek35537662007-12-05 22:08:43 +000026#include "llvm/Support/Streams.h"
Chris Lattner1266eca2009-03-28 04:31:31 +000027#include "llvm/System/Path.h"
Ted Kremenekea75c552007-11-28 21:32:21 +000028#include <fstream>
Chris Lattner87cf5ac2008-03-10 17:04:53 +000029#include <cstring>
Ted Kremenekbfa82c42007-10-16 23:37:27 +000030using namespace clang;
Ted Kremenekbfa82c42007-10-16 23:37:27 +000031
Ted Kremenek79a2a262007-11-28 19:21:47 +000032//===----------------------------------------------------------------------===//
Ted Kremenek79a2a262007-11-28 19:21:47 +000033// Driver code.
34//===----------------------------------------------------------------------===//
35
Ted Kremenek35537662007-12-05 22:08:43 +000036namespace {
Ted Kremenek4ac81212007-11-05 21:39:35 +000037
Ted Kremenek35537662007-12-05 22:08:43 +000038class SerializationTest : public ASTConsumer {
Ted Kremenek35537662007-12-05 22:08:43 +000039 Diagnostic &Diags;
40 FileManager &FMgr;
Ted Kremenek018b3952007-11-06 19:50:53 +000041public:
Ted Kremeneke7d07d12008-06-04 15:55:15 +000042 SerializationTest(Diagnostic &d, FileManager& fmgr)
Ted Kremeneke452e0f2008-08-08 04:15:52 +000043 : Diags(d), FMgr(fmgr) {}
Ted Kremenekdca24662007-12-05 00:26:13 +000044
Ted Kremeneke452e0f2008-08-08 04:15:52 +000045 ~SerializationTest() {}
46
Chris Lattnerdacbc5d2009-03-28 04:11:33 +000047 virtual void HandleTranslationUnit(ASTContext &C);
Ted Kremenek63ea8632007-12-19 19:27:38 +000048
Ted Kremenek018b3952007-11-06 19:50:53 +000049private:
Ted Kremeneke452e0f2008-08-08 04:15:52 +000050 bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint,
Chris Lattnerd2fa6752009-03-28 03:56:54 +000051 ASTContext &Ctx);
Ted Kremeneke452e0f2008-08-08 04:15:52 +000052
Ted Kremenek35537662007-12-05 22:08:43 +000053 bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
Ted Kremenek4ac81212007-11-05 21:39:35 +000054};
55
Ted Kremenekc637e6b2007-10-23 22:18:37 +000056} // end anonymous namespace
Ted Kremenekbfa82c42007-10-16 23:37:27 +000057
Ted Kremenekdca24662007-12-05 00:26:13 +000058ASTConsumer*
Ted Kremeneke7d07d12008-06-04 15:55:15 +000059clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr) {
60 return new SerializationTest(Diags, FMgr);
Ted Kremenek018b3952007-11-06 19:50:53 +000061}
62
Ted Kremenek018b3952007-11-06 19:50:53 +000063
Ted Kremenek35537662007-12-05 22:08:43 +000064bool SerializationTest::Serialize(llvm::sys::Path& Filename,
Ted Kremeneke452e0f2008-08-08 04:15:52 +000065 llvm::sys::Path& FNameDeclPrint,
Chris Lattnerd2fa6752009-03-28 03:56:54 +000066 ASTContext &Ctx) {
Ted Kremenek35537662007-12-05 22:08:43 +000067 {
68 // Pretty-print the decls to a temp file.
Ted Kremeneka95d3752008-09-13 05:16:45 +000069 std::string Err;
Daniel Dunbar26fb2722008-11-13 05:09:21 +000070 llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), true, Err);
Ted Kremeneka95d3752008-09-13 05:16:45 +000071 assert (Err.empty() && "Could not open file for printing out decls.");
Ted Kremenekee533642007-12-20 19:47:16 +000072 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremeneke7201982007-11-13 22:56:10 +000073
Chris Lattnerd2fa6752009-03-28 03:56:54 +000074 TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl();
Douglas Gregor6ab35242009-04-09 21:40:53 +000075 for (DeclContext::decl_iterator I = TUD->decls_begin(Ctx),
76 E = TUD->decls_end(Ctx);
Chris Lattnerd2fa6752009-03-28 03:56:54 +000077 I != E; ++I)
Chris Lattner682bf922009-03-29 16:50:03 +000078 FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
Ted Kremenek7a1f4db2007-11-10 02:07:12 +000079 }
80
Ted Kremenek35537662007-12-05 22:08:43 +000081 // Serialize the translation unit.
Chris Lattner80a03332009-03-28 03:53:02 +000082
83 // Reserve 256K for bitstream buffer.
84 std::vector<unsigned char> Buffer;
85 Buffer.reserve(256*1024);
86
Chris Lattner557c5b12009-03-28 04:27:18 +000087 Ctx.EmitASTBitcodeBuffer(Buffer);
Chris Lattner80a03332009-03-28 03:53:02 +000088
89 // Write the bits to disk.
90 if (FILE* fp = fopen(Filename.c_str(),"wb")) {
91 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
92 fclose(fp);
93 return true;
94 }
95
96 return false;
Ted Kremenekbfa82c42007-10-16 23:37:27 +000097}
98
Ted Kremenek35537662007-12-05 22:08:43 +000099bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
Ted Kremenek79a2a262007-11-28 19:21:47 +0000100 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000101
Ted Kremenek35537662007-12-05 22:08:43 +0000102 // Deserialize the translation unit.
Chris Lattner557c5b12009-03-28 04:27:18 +0000103 ASTContext *NewCtx;
Chris Lattner5f737cc2009-03-28 03:49:26 +0000104
105 {
106 // Create the memory buffer that contains the contents of the file.
107 llvm::OwningPtr<llvm::MemoryBuffer>
108 MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str()));
109
110 if (!MBuffer)
111 return false;
112
Chris Lattner557c5b12009-03-28 04:27:18 +0000113 NewCtx = ASTContext::ReadASTBitcodeBuffer(*MBuffer, FMgr);
Chris Lattner5f737cc2009-03-28 03:49:26 +0000114 }
Ted Kremenekb899ad22007-11-14 17:46:35 +0000115
Chris Lattner557c5b12009-03-28 04:27:18 +0000116 if (!NewCtx)
Ted Kremenek35537662007-12-05 22:08:43 +0000117 return false;
Ted Kremenekb899ad22007-11-14 17:46:35 +0000118
Ted Kremeneke452e0f2008-08-08 04:15:52 +0000119 {
Ted Kremenek35537662007-12-05 22:08:43 +0000120 // Pretty-print the deserialized decls to a temp file.
Ted Kremeneka95d3752008-09-13 05:16:45 +0000121 std::string Err;
Daniel Dunbar26fb2722008-11-13 05:09:21 +0000122 llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), true, Err);
Ted Kremeneka95d3752008-09-13 05:16:45 +0000123 assert (Err.empty() && "Could not open file for printing out decls.");
Ted Kremenekee533642007-12-20 19:47:16 +0000124 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenek35537662007-12-05 22:08:43 +0000125
Chris Lattner557c5b12009-03-28 04:27:18 +0000126 TranslationUnitDecl *TUD = NewCtx->getTranslationUnitDecl();
Douglas Gregor6ab35242009-04-09 21:40:53 +0000127 for (DeclContext::decl_iterator I = TUD->decls_begin(*NewCtx),
128 E = TUD->decls_end(*NewCtx);
Chris Lattner557c5b12009-03-28 04:27:18 +0000129 I != E; ++I)
Chris Lattner682bf922009-03-29 16:50:03 +0000130 FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
Ted Kremenekc4ca2882007-12-03 22:48:14 +0000131 }
Sam Bishop4ccea1a2008-04-03 05:03:34 +0000132
Chris Lattner557c5b12009-03-28 04:27:18 +0000133 delete NewCtx;
Ted Kremenek018b3952007-11-06 19:50:53 +0000134
Ted Kremenek35537662007-12-05 22:08:43 +0000135 return true;
Ted Kremenek018b3952007-11-06 19:50:53 +0000136}
137
Ted Kremenek79a2a262007-11-28 19:21:47 +0000138namespace {
139 class TmpDirJanitor {
140 llvm::sys::Path& Dir;
141 public:
142 explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
143
144 ~TmpDirJanitor() {
145 llvm::cerr << "Removing: " << Dir.c_str() << '\n';
146 Dir.eraseFromDisk(true);
147 }
148 };
149}
Ted Kremenek018b3952007-11-06 19:50:53 +0000150
Chris Lattnerdacbc5d2009-03-28 04:11:33 +0000151void SerializationTest::HandleTranslationUnit(ASTContext &Ctx) {
Ted Kremenek79a2a262007-11-28 19:21:47 +0000152
Ted Kremenek018b3952007-11-06 19:50:53 +0000153 std::string ErrMsg;
Ted Kremenek79a2a262007-11-28 19:21:47 +0000154 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek018b3952007-11-06 19:50:53 +0000155
Ted Kremenek79a2a262007-11-28 19:21:47 +0000156 if (Dir.isEmpty()) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000157 llvm::cerr << "Error: " << ErrMsg << "\n";
158 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000159 }
160
Ted Kremenek79a2a262007-11-28 19:21:47 +0000161 TmpDirJanitor RemoveTmpOnExit(Dir);
162
163 llvm::sys::Path FNameDeclBefore = Dir;
164 FNameDeclBefore.appendComponent("test.decl_before.txt");
165
Chris Lattnerdacbc5d2009-03-28 04:11:33 +0000166 if (FNameDeclBefore.makeUnique(true, &ErrMsg)) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000167 llvm::cerr << "Error: " << ErrMsg << "\n";
168 return;
169 }
Ted Kremenek4ac81212007-11-05 21:39:35 +0000170
Ted Kremenek79a2a262007-11-28 19:21:47 +0000171 llvm::sys::Path FNameDeclAfter = Dir;
172 FNameDeclAfter.appendComponent("test.decl_after.txt");
173
Chris Lattnerdacbc5d2009-03-28 04:11:33 +0000174 if (FNameDeclAfter.makeUnique(true, &ErrMsg)) {
Ted Kremenek79a2a262007-11-28 19:21:47 +0000175 llvm::cerr << "Error: " << ErrMsg << "\n";
176 return;
177 }
178
179 llvm::sys::Path ASTFilename = Dir;
180 ASTFilename.appendComponent("test.ast");
181
Chris Lattnerdacbc5d2009-03-28 04:11:33 +0000182 if (ASTFilename.makeUnique(true, &ErrMsg)) {
Ted Kremenek79a2a262007-11-28 19:21:47 +0000183 llvm::cerr << "Error: " << ErrMsg << "\n";
184 return;
185 }
186
187 // Serialize and then deserialize the ASTs.
Chris Lattnerdacbc5d2009-03-28 04:11:33 +0000188 bool status = Serialize(ASTFilename, FNameDeclBefore, Ctx);
Ted Kremenek35537662007-12-05 22:08:43 +0000189 assert (status && "Serialization failed.");
190 status = Deserialize(ASTFilename, FNameDeclAfter);
191 assert (status && "Deserialization failed.");
Ted Kremenek79a2a262007-11-28 19:21:47 +0000192
193 // Read both pretty-printed files and compare them.
194
195 using llvm::MemoryBuffer;
196
Ted Kremenekee533642007-12-20 19:47:16 +0000197 llvm::OwningPtr<MemoryBuffer>
Chris Lattner35de5122008-04-01 18:04:30 +0000198 MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str()));
Ted Kremenek79a2a262007-11-28 19:21:47 +0000199
200 if(!MBufferSer) {
201 llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
202 return;
203 }
204
Ted Kremenekee533642007-12-20 19:47:16 +0000205 llvm::OwningPtr<MemoryBuffer>
Chris Lattner35de5122008-04-01 18:04:30 +0000206 MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str()));
Ted Kremenek79a2a262007-11-28 19:21:47 +0000207
208 if(!MBufferDSer) {
209 llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
210 return;
211 }
212
213 const char *p1 = MBufferSer->getBufferStart();
214 const char *e1 = MBufferSer->getBufferEnd();
215 const char *p2 = MBufferDSer->getBufferStart();
216 const char *e2 = MBufferDSer->getBufferEnd();
217
218 if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
219 for ( ; p1 != e1 ; ++p1, ++p2 )
220 if (*p1 != *p2) break;
221
222 if (p1 != e1 || p2 != e2 )
223 llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
224 else
225 llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000226}