blob: 74ccb4b4d1f8d973d9a296d954578eb70342a5ab [file] [log] [blame]
Ted Kremenek221bb8d2007-10-16 23:37:27 +00001//===--- SerializationTest.cpp - Experimental Object Serialization --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner959e5be2007-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 Kremenek221bb8d2007-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 Kremenek221bb8d2007-10-16 23:37:27 +000017#include "clang/AST/ASTConsumer.h"
Chris Lattnerfc318192009-03-28 04:31:31 +000018#include "clang/AST/ASTContext.h"
Ted Kremenek09a0cef2007-11-29 01:24:25 +000019#include "clang/AST/CFG.h"
Daniel Dunbarde300732008-08-11 04:54:23 +000020#include "clang/AST/Decl.h"
Ted Kremenek8b61b3b2007-12-03 22:48:14 +000021#include "clang.h"
Ted Kremenek177c5712007-12-05 22:08:43 +000022#include "ASTConsumers.h"
Ted Kremenek634cadf2007-10-23 22:18:37 +000023#include "llvm/Support/MemoryBuffer.h"
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000024#include "llvm/ADT/OwningPtr.h"
Ted Kremenek177c5712007-12-05 22:08:43 +000025#include "llvm/Support/Streams.h"
Chris Lattnerfc318192009-03-28 04:31:31 +000026#include "llvm/System/Path.h"
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000027#include <fstream>
Chris Lattner8b8720f2008-03-10 17:04:53 +000028#include <cstring>
Ted Kremenek221bb8d2007-10-16 23:37:27 +000029using namespace clang;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000030
Ted Kremenekb3b25972007-11-28 19:21:47 +000031//===----------------------------------------------------------------------===//
Ted Kremenekb3b25972007-11-28 19:21:47 +000032// Driver code.
33//===----------------------------------------------------------------------===//
34
Ted Kremenek177c5712007-12-05 22:08:43 +000035namespace {
Ted Kremenek47916ee2007-11-05 21:39:35 +000036
Ted Kremenek177c5712007-12-05 22:08:43 +000037class SerializationTest : public ASTConsumer {
Ted Kremenek177c5712007-12-05 22:08:43 +000038 Diagnostic &Diags;
39 FileManager &FMgr;
Ted Kremenek1e049d22007-11-06 19:50:53 +000040public:
Ted Kremenek842126e2008-06-04 15:55:15 +000041 SerializationTest(Diagnostic &d, FileManager& fmgr)
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000042 : Diags(d), FMgr(fmgr) {}
Ted Kremenek923de592007-12-05 00:26:13 +000043
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000044 ~SerializationTest() {}
45
Chris Lattner2a594d02009-03-28 04:11:33 +000046 virtual void HandleTranslationUnit(ASTContext &C);
Ted Kremenekab749372007-12-19 19:27:38 +000047
Ted Kremenek1e049d22007-11-06 19:50:53 +000048private:
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000049 bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint,
Chris Lattner8c86cdf2009-03-28 03:56:54 +000050 ASTContext &Ctx);
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000051
Ted Kremenek177c5712007-12-05 22:08:43 +000052 bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
Ted Kremenek47916ee2007-11-05 21:39:35 +000053};
54
Ted Kremenek634cadf2007-10-23 22:18:37 +000055} // end anonymous namespace
Ted Kremenek221bb8d2007-10-16 23:37:27 +000056
Ted Kremenek923de592007-12-05 00:26:13 +000057ASTConsumer*
Ted Kremenek842126e2008-06-04 15:55:15 +000058clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr) {
59 return new SerializationTest(Diags, FMgr);
Ted Kremenek1e049d22007-11-06 19:50:53 +000060}
61
Ted Kremenek1e049d22007-11-06 19:50:53 +000062
Ted Kremenek177c5712007-12-05 22:08:43 +000063bool SerializationTest::Serialize(llvm::sys::Path& Filename,
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000064 llvm::sys::Path& FNameDeclPrint,
Chris Lattner8c86cdf2009-03-28 03:56:54 +000065 ASTContext &Ctx) {
Ted Kremenek177c5712007-12-05 22:08:43 +000066 {
67 // Pretty-print the decls to a temp file.
Ted Kremenek7b6f67b2008-09-13 05:16:45 +000068 std::string Err;
Daniel Dunbar8fc9ba62008-11-13 05:09:21 +000069 llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), true, Err);
Ted Kremenek7b6f67b2008-09-13 05:16:45 +000070 assert (Err.empty() && "Could not open file for printing out decls.");
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000071 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenekea5bfc72007-11-13 22:56:10 +000072
Chris Lattner8c86cdf2009-03-28 03:56:54 +000073 TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl();
74 for (DeclContext::decl_iterator I = TUD->decls_begin(), E =TUD->decls_end();
75 I != E; ++I)
Ted Kremenek177c5712007-12-05 22:08:43 +000076 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek9dcb2882007-11-10 02:07:12 +000077 }
78
Ted Kremenek177c5712007-12-05 22:08:43 +000079 // Serialize the translation unit.
Chris Lattner78e3dd42009-03-28 03:53:02 +000080
81 // Reserve 256K for bitstream buffer.
82 std::vector<unsigned char> Buffer;
83 Buffer.reserve(256*1024);
84
Chris Lattnerf4fbc442009-03-28 04:27:18 +000085 Ctx.EmitASTBitcodeBuffer(Buffer);
Chris Lattner78e3dd42009-03-28 03:53:02 +000086
87 // Write the bits to disk.
88 if (FILE* fp = fopen(Filename.c_str(),"wb")) {
89 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
90 fclose(fp);
91 return true;
92 }
93
94 return false;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000095}
96
Ted Kremenek177c5712007-12-05 22:08:43 +000097bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
Ted Kremenekb3b25972007-11-28 19:21:47 +000098 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek1e049d22007-11-06 19:50:53 +000099
Ted Kremenek177c5712007-12-05 22:08:43 +0000100 // Deserialize the translation unit.
Chris Lattnerf4fbc442009-03-28 04:27:18 +0000101 ASTContext *NewCtx;
Chris Lattner06459ae2009-03-28 03:49:26 +0000102
103 {
104 // Create the memory buffer that contains the contents of the file.
105 llvm::OwningPtr<llvm::MemoryBuffer>
106 MBuffer(llvm::MemoryBuffer::getFile(Filename.c_str()));
107
108 if (!MBuffer)
109 return false;
110
Chris Lattnerf4fbc442009-03-28 04:27:18 +0000111 NewCtx = ASTContext::ReadASTBitcodeBuffer(*MBuffer, FMgr);
Chris Lattner06459ae2009-03-28 03:49:26 +0000112 }
Ted Kremenek286333d2007-11-14 17:46:35 +0000113
Chris Lattnerf4fbc442009-03-28 04:27:18 +0000114 if (!NewCtx)
Ted Kremenek177c5712007-12-05 22:08:43 +0000115 return false;
Ted Kremenek286333d2007-11-14 17:46:35 +0000116
Ted Kremenekcab0b0c2008-08-08 04:15:52 +0000117 {
Ted Kremenek177c5712007-12-05 22:08:43 +0000118 // Pretty-print the deserialized decls to a temp file.
Ted Kremenek7b6f67b2008-09-13 05:16:45 +0000119 std::string Err;
Daniel Dunbar8fc9ba62008-11-13 05:09:21 +0000120 llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), true, Err);
Ted Kremenek7b6f67b2008-09-13 05:16:45 +0000121 assert (Err.empty() && "Could not open file for printing out decls.");
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000122 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenek177c5712007-12-05 22:08:43 +0000123
Chris Lattnerf4fbc442009-03-28 04:27:18 +0000124 TranslationUnitDecl *TUD = NewCtx->getTranslationUnitDecl();
125 for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end();
126 I != E; ++I)
Ted Kremenek177c5712007-12-05 22:08:43 +0000127 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek8b61b3b2007-12-03 22:48:14 +0000128 }
Sam Bishop6e104ec2008-04-03 05:03:34 +0000129
Chris Lattnerf4fbc442009-03-28 04:27:18 +0000130 delete NewCtx;
Ted Kremenek1e049d22007-11-06 19:50:53 +0000131
Ted Kremenek177c5712007-12-05 22:08:43 +0000132 return true;
Ted Kremenek1e049d22007-11-06 19:50:53 +0000133}
134
Ted Kremenekb3b25972007-11-28 19:21:47 +0000135namespace {
136 class TmpDirJanitor {
137 llvm::sys::Path& Dir;
138 public:
139 explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
140
141 ~TmpDirJanitor() {
142 llvm::cerr << "Removing: " << Dir.c_str() << '\n';
143 Dir.eraseFromDisk(true);
144 }
145 };
146}
Ted Kremenek1e049d22007-11-06 19:50:53 +0000147
Chris Lattner2a594d02009-03-28 04:11:33 +0000148void SerializationTest::HandleTranslationUnit(ASTContext &Ctx) {
Ted Kremenekb3b25972007-11-28 19:21:47 +0000149
Ted Kremenek1e049d22007-11-06 19:50:53 +0000150 std::string ErrMsg;
Ted Kremenekb3b25972007-11-28 19:21:47 +0000151 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek1e049d22007-11-06 19:50:53 +0000152
Ted Kremenekb3b25972007-11-28 19:21:47 +0000153 if (Dir.isEmpty()) {
Ted Kremenek1e049d22007-11-06 19:50:53 +0000154 llvm::cerr << "Error: " << ErrMsg << "\n";
155 return;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000156 }
157
Ted Kremenekb3b25972007-11-28 19:21:47 +0000158 TmpDirJanitor RemoveTmpOnExit(Dir);
159
160 llvm::sys::Path FNameDeclBefore = Dir;
161 FNameDeclBefore.appendComponent("test.decl_before.txt");
162
Chris Lattner2a594d02009-03-28 04:11:33 +0000163 if (FNameDeclBefore.makeUnique(true, &ErrMsg)) {
Ted Kremenek1e049d22007-11-06 19:50:53 +0000164 llvm::cerr << "Error: " << ErrMsg << "\n";
165 return;
166 }
Ted Kremenek47916ee2007-11-05 21:39:35 +0000167
Ted Kremenekb3b25972007-11-28 19:21:47 +0000168 llvm::sys::Path FNameDeclAfter = Dir;
169 FNameDeclAfter.appendComponent("test.decl_after.txt");
170
Chris Lattner2a594d02009-03-28 04:11:33 +0000171 if (FNameDeclAfter.makeUnique(true, &ErrMsg)) {
Ted Kremenekb3b25972007-11-28 19:21:47 +0000172 llvm::cerr << "Error: " << ErrMsg << "\n";
173 return;
174 }
175
176 llvm::sys::Path ASTFilename = Dir;
177 ASTFilename.appendComponent("test.ast");
178
Chris Lattner2a594d02009-03-28 04:11:33 +0000179 if (ASTFilename.makeUnique(true, &ErrMsg)) {
Ted Kremenekb3b25972007-11-28 19:21:47 +0000180 llvm::cerr << "Error: " << ErrMsg << "\n";
181 return;
182 }
183
184 // Serialize and then deserialize the ASTs.
Chris Lattner2a594d02009-03-28 04:11:33 +0000185 bool status = Serialize(ASTFilename, FNameDeclBefore, Ctx);
Ted Kremenek177c5712007-12-05 22:08:43 +0000186 assert (status && "Serialization failed.");
187 status = Deserialize(ASTFilename, FNameDeclAfter);
188 assert (status && "Deserialization failed.");
Ted Kremenekb3b25972007-11-28 19:21:47 +0000189
190 // Read both pretty-printed files and compare them.
191
192 using llvm::MemoryBuffer;
193
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000194 llvm::OwningPtr<MemoryBuffer>
Chris Lattnerd9606102008-04-01 18:04:30 +0000195 MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str()));
Ted Kremenekb3b25972007-11-28 19:21:47 +0000196
197 if(!MBufferSer) {
198 llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
199 return;
200 }
201
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000202 llvm::OwningPtr<MemoryBuffer>
Chris Lattnerd9606102008-04-01 18:04:30 +0000203 MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str()));
Ted Kremenekb3b25972007-11-28 19:21:47 +0000204
205 if(!MBufferDSer) {
206 llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
207 return;
208 }
209
210 const char *p1 = MBufferSer->getBufferStart();
211 const char *e1 = MBufferSer->getBufferEnd();
212 const char *p2 = MBufferDSer->getBufferStart();
213 const char *e2 = MBufferDSer->getBufferEnd();
214
215 if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
216 for ( ; p1 != e1 ; ++p1, ++p2 )
217 if (*p1 != *p2) break;
218
219 if (p1 != e1 || p2 != e2 )
220 llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
221 else
222 llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
Ted Kremenek634cadf2007-10-23 22:18:37 +0000223}