blob: 7bd6cd131335dc10ef1496e18687594dfc896b0b [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
Ted Kremenekbfa82c42007-10-16 23:37:27 +000017#include "clang/AST/ASTConsumer.h"
Ted Kremenek5656b782007-11-29 01:24:25 +000018#include "clang/AST/CFG.h"
Ted Kremenekc4ca2882007-12-03 22:48:14 +000019#include "clang.h"
Ted Kremenek35537662007-12-05 22:08:43 +000020#include "ASTConsumers.h"
21#include "TranslationUnit.h"
Ted Kremenekc637e6b2007-10-23 22:18:37 +000022#include "llvm/Support/MemoryBuffer.h"
Ted Kremenek35537662007-12-05 22:08:43 +000023#include "llvm/ADT/scoped_ptr.h"
24#include "llvm/Support/Streams.h"
Ted Kremenekea75c552007-11-28 21:32:21 +000025#include <fstream>
Ted Kremenekc637e6b2007-10-23 22:18:37 +000026
Ted Kremenekbfa82c42007-10-16 23:37:27 +000027using namespace clang;
Ted Kremenekbfa82c42007-10-16 23:37:27 +000028
Ted Kremenek79a2a262007-11-28 19:21:47 +000029//===----------------------------------------------------------------------===//
Ted Kremenek79a2a262007-11-28 19:21:47 +000030// Driver code.
31//===----------------------------------------------------------------------===//
32
Ted Kremenek35537662007-12-05 22:08:43 +000033namespace {
Ted Kremenek4ac81212007-11-05 21:39:35 +000034
Ted Kremenek35537662007-12-05 22:08:43 +000035class SerializationTest : public ASTConsumer {
36 TranslationUnit TU;
37 Diagnostic &Diags;
38 FileManager &FMgr;
Ted Kremenek018b3952007-11-06 19:50:53 +000039public:
Ted Kremenekacc9f332007-12-05 21:34:36 +000040 SerializationTest(Diagnostic &d, FileManager& fmgr, const LangOptions& LOpts)
Ted Kremenek35537662007-12-05 22:08:43 +000041 : TU(LOpts), Diags(d), FMgr(fmgr) {}
Ted Kremenekdca24662007-12-05 00:26:13 +000042
Ted Kremenek4ac81212007-11-05 21:39:35 +000043 ~SerializationTest();
44
Ted Kremenek018b3952007-11-06 19:50:53 +000045 virtual void Initialize(ASTContext& context, unsigned) {
Ted Kremenek35537662007-12-05 22:08:43 +000046 TU.setContext(&context);
47 }
Ted Kremenek018b3952007-11-06 19:50:53 +000048
Ted Kremenek35537662007-12-05 22:08:43 +000049 virtual void HandleTopLevelDecl(Decl *D) {
50 TU.AddTopLevelDecl(D);
51 }
Ted Kremenek018b3952007-11-06 19:50:53 +000052private:
Ted Kremenek35537662007-12-05 22:08:43 +000053 bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
54 bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
Ted Kremenek4ac81212007-11-05 21:39:35 +000055};
56
Ted Kremenekc637e6b2007-10-23 22:18:37 +000057} // end anonymous namespace
Ted Kremenekbfa82c42007-10-16 23:37:27 +000058
Ted Kremenekdca24662007-12-05 00:26:13 +000059ASTConsumer*
Ted Kremenekacc9f332007-12-05 21:34:36 +000060clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
61 const LangOptions &LOpts) {
62 return new SerializationTest(Diags,FMgr,LOpts);
Ted Kremenek018b3952007-11-06 19:50:53 +000063}
64
Ted Kremenek018b3952007-11-06 19:50:53 +000065
Ted Kremenek35537662007-12-05 22:08:43 +000066bool SerializationTest::Serialize(llvm::sys::Path& Filename,
Ted Kremenek79a2a262007-11-28 19:21:47 +000067 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek35537662007-12-05 22:08:43 +000068 {
69 // Pretty-print the decls to a temp file.
Ted Kremenekea75c552007-11-28 21:32:21 +000070 std::ofstream DeclPP(FNameDeclPrint.c_str());
71 assert (DeclPP && "Could not open file for printing out decls.");
Ted Kremenek35537662007-12-05 22:08:43 +000072 llvm::scoped_ptr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremeneke7201982007-11-13 22:56:10 +000073
Ted Kremenek35537662007-12-05 22:08:43 +000074 for (TranslationUnit::iterator I=TU.begin(), E=TU.end(); I!=E; ++I)
75 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek7a1f4db2007-11-10 02:07:12 +000076 }
77
Ted Kremenek35537662007-12-05 22:08:43 +000078 // Serialize the translation unit.
79 return TU.EmitBitcodeFile(Filename);
Ted Kremenekbfa82c42007-10-16 23:37:27 +000080}
81
Ted Kremenek35537662007-12-05 22:08:43 +000082bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
Ted Kremenek79a2a262007-11-28 19:21:47 +000083 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek018b3952007-11-06 19:50:53 +000084
Ted Kremenek35537662007-12-05 22:08:43 +000085 // Deserialize the translation unit.
86 TranslationUnit* NewTU = TranslationUnit::ReadBitcodeFile(Filename,FMgr);
Ted Kremenekb899ad22007-11-14 17:46:35 +000087
Ted Kremenek35537662007-12-05 22:08:43 +000088 if (!NewTU)
89 return false;
Ted Kremenekb899ad22007-11-14 17:46:35 +000090
Ted Kremenek35537662007-12-05 22:08:43 +000091 {
92 // Pretty-print the deserialized decls to a temp file.
93 std::ofstream DeclPP(FNameDeclPrint.c_str());
94 assert (DeclPP && "Could not open file for printing out decls.");
95 llvm::scoped_ptr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
96
97 for (TranslationUnit::iterator I=NewTU->begin(), E=NewTU->end(); I!=E; ++I)
98 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenekc4ca2882007-12-03 22:48:14 +000099 }
Ted Kremenek018b3952007-11-06 19:50:53 +0000100
Ted Kremenek35537662007-12-05 22:08:43 +0000101 return true;
Ted Kremenek018b3952007-11-06 19:50:53 +0000102}
103
Ted Kremenek79a2a262007-11-28 19:21:47 +0000104namespace {
105 class TmpDirJanitor {
106 llvm::sys::Path& Dir;
107 public:
108 explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
109
110 ~TmpDirJanitor() {
111 llvm::cerr << "Removing: " << Dir.c_str() << '\n';
112 Dir.eraseFromDisk(true);
113 }
114 };
115}
Ted Kremenek018b3952007-11-06 19:50:53 +0000116
117SerializationTest::~SerializationTest() {
Ted Kremenek79a2a262007-11-28 19:21:47 +0000118
Ted Kremenek018b3952007-11-06 19:50:53 +0000119 std::string ErrMsg;
Ted Kremenek79a2a262007-11-28 19:21:47 +0000120 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek018b3952007-11-06 19:50:53 +0000121
Ted Kremenek79a2a262007-11-28 19:21:47 +0000122 if (Dir.isEmpty()) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000123 llvm::cerr << "Error: " << ErrMsg << "\n";
124 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000125 }
126
Ted Kremenek79a2a262007-11-28 19:21:47 +0000127 TmpDirJanitor RemoveTmpOnExit(Dir);
128
129 llvm::sys::Path FNameDeclBefore = Dir;
130 FNameDeclBefore.appendComponent("test.decl_before.txt");
131
132 if (FNameDeclBefore.makeUnique(true,&ErrMsg)) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000133 llvm::cerr << "Error: " << ErrMsg << "\n";
134 return;
135 }
Ted Kremenek4ac81212007-11-05 21:39:35 +0000136
Ted Kremenek79a2a262007-11-28 19:21:47 +0000137 llvm::sys::Path FNameDeclAfter = Dir;
138 FNameDeclAfter.appendComponent("test.decl_after.txt");
139
140 if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
141 llvm::cerr << "Error: " << ErrMsg << "\n";
142 return;
143 }
144
145 llvm::sys::Path ASTFilename = Dir;
146 ASTFilename.appendComponent("test.ast");
147
148 if (ASTFilename.makeUnique(true,&ErrMsg)) {
149 llvm::cerr << "Error: " << ErrMsg << "\n";
150 return;
151 }
152
153 // Serialize and then deserialize the ASTs.
Ted Kremenek35537662007-12-05 22:08:43 +0000154 bool status = Serialize(ASTFilename, FNameDeclBefore);
155 assert (status && "Serialization failed.");
156 status = Deserialize(ASTFilename, FNameDeclAfter);
157 assert (status && "Deserialization failed.");
Ted Kremenek79a2a262007-11-28 19:21:47 +0000158
159 // Read both pretty-printed files and compare them.
160
161 using llvm::MemoryBuffer;
162
Ted Kremenek35537662007-12-05 22:08:43 +0000163 llvm::scoped_ptr<MemoryBuffer>
Ted Kremenek79a2a262007-11-28 19:21:47 +0000164 MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str(),
165 strlen(FNameDeclBefore.c_str())));
166
167 if(!MBufferSer) {
168 llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
169 return;
170 }
171
Ted Kremenek35537662007-12-05 22:08:43 +0000172 llvm::scoped_ptr<MemoryBuffer>
Ted Kremenek79a2a262007-11-28 19:21:47 +0000173 MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str(),
174 strlen(FNameDeclAfter.c_str())));
175
176 if(!MBufferDSer) {
177 llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
178 return;
179 }
180
181 const char *p1 = MBufferSer->getBufferStart();
182 const char *e1 = MBufferSer->getBufferEnd();
183 const char *p2 = MBufferDSer->getBufferStart();
184 const char *e2 = MBufferDSer->getBufferEnd();
185
186 if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
187 for ( ; p1 != e1 ; ++p1, ++p2 )
188 if (*p1 != *p2) break;
189
190 if (p1 != e1 || p2 != e2 )
191 llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
192 else
193 llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000194}