blob: 6e9309dc28ba9c662aec71b9067f3a950f4efc63 [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"
Ted Kremenek09a0cef2007-11-29 01:24:25 +000018#include "clang/AST/CFG.h"
Ted Kremenek8b61b3b2007-12-03 22:48:14 +000019#include "clang.h"
Ted Kremenek177c5712007-12-05 22:08:43 +000020#include "ASTConsumers.h"
Ted Kremenek3a0b28b2007-12-18 21:36:21 +000021#include "clang/AST/TranslationUnit.h"
Ted Kremenek634cadf2007-10-23 22:18:37 +000022#include "llvm/Support/MemoryBuffer.h"
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000023#include "llvm/ADT/OwningPtr.h"
Ted Kremenek177c5712007-12-05 22:08:43 +000024#include "llvm/Support/Streams.h"
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000025#include <fstream>
Chris Lattner8b8720f2008-03-10 17:04:53 +000026#include <cstring>
Ted Kremenek221bb8d2007-10-16 23:37:27 +000027using namespace clang;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000028
Ted Kremenekb3b25972007-11-28 19:21:47 +000029//===----------------------------------------------------------------------===//
Ted Kremenekb3b25972007-11-28 19:21:47 +000030// Driver code.
31//===----------------------------------------------------------------------===//
32
Ted Kremenek177c5712007-12-05 22:08:43 +000033namespace {
Ted Kremenek47916ee2007-11-05 21:39:35 +000034
Ted Kremenek177c5712007-12-05 22:08:43 +000035class SerializationTest : public ASTConsumer {
Ted Kremenek863b01f2008-04-23 16:25:39 +000036 llvm::OwningPtr<TranslationUnit> TU;
Ted Kremenek177c5712007-12-05 22:08:43 +000037 Diagnostic &Diags;
38 FileManager &FMgr;
Ted Kremenek863b01f2008-04-23 16:25:39 +000039 const LangOptions& lopts;
Ted Kremenek1e049d22007-11-06 19:50:53 +000040public:
Ted Kremenekd890f6a2007-12-19 22:24:34 +000041 SerializationTest(Diagnostic &d, FileManager& fmgr, const LangOptions& LOpts)
Ted Kremenek863b01f2008-04-23 16:25:39 +000042 : Diags(d), FMgr(fmgr), lopts(LOpts) {}
Ted Kremenek923de592007-12-05 00:26:13 +000043
Ted Kremenek47916ee2007-11-05 21:39:35 +000044 ~SerializationTest();
45
Ted Kremenek17861c52007-12-19 22:51:13 +000046 virtual void Initialize(ASTContext& context) {
Ted Kremenek863b01f2008-04-23 16:25:39 +000047 if (!TU) TU.reset(new TranslationUnit(context, lopts));
Ted Kremenek177c5712007-12-05 22:08:43 +000048 }
Ted Kremenek1e049d22007-11-06 19:50:53 +000049
Ted Kremenek177c5712007-12-05 22:08:43 +000050 virtual void HandleTopLevelDecl(Decl *D) {
Ted Kremenek863b01f2008-04-23 16:25:39 +000051 TU->AddTopLevelDecl(D);
Ted Kremenek177c5712007-12-05 22:08:43 +000052 }
Ted Kremenekab749372007-12-19 19:27:38 +000053
Ted Kremenek1e049d22007-11-06 19:50:53 +000054private:
Ted Kremenek177c5712007-12-05 22:08:43 +000055 bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
56 bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
Ted Kremenek47916ee2007-11-05 21:39:35 +000057};
58
Ted Kremenek634cadf2007-10-23 22:18:37 +000059} // end anonymous namespace
Ted Kremenek221bb8d2007-10-16 23:37:27 +000060
Ted Kremenek923de592007-12-05 00:26:13 +000061ASTConsumer*
Ted Kremenekd890f6a2007-12-19 22:24:34 +000062clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
63 const LangOptions &LOpts) {
64
65 return new SerializationTest(Diags,FMgr,LOpts);
Ted Kremenek1e049d22007-11-06 19:50:53 +000066}
67
Ted Kremenek1e049d22007-11-06 19:50:53 +000068
Ted Kremenek177c5712007-12-05 22:08:43 +000069bool SerializationTest::Serialize(llvm::sys::Path& Filename,
Ted Kremenekb3b25972007-11-28 19:21:47 +000070 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek177c5712007-12-05 22:08:43 +000071 {
72 // Pretty-print the decls to a temp file.
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000073 std::ofstream DeclPP(FNameDeclPrint.c_str());
74 assert (DeclPP && "Could not open file for printing out decls.");
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000075 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenekea5bfc72007-11-13 22:56:10 +000076
Ted Kremenek863b01f2008-04-23 16:25:39 +000077 for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)
Ted Kremenek177c5712007-12-05 22:08:43 +000078 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek9dcb2882007-11-10 02:07:12 +000079 }
80
Ted Kremenek177c5712007-12-05 22:08:43 +000081 // Serialize the translation unit.
Ted Kremenek863b01f2008-04-23 16:25:39 +000082 return EmitASTBitcodeFile(*TU,Filename);
Ted Kremenek221bb8d2007-10-16 23:37:27 +000083}
84
Ted Kremenek177c5712007-12-05 22:08:43 +000085bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
Ted Kremenekb3b25972007-11-28 19:21:47 +000086 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek1e049d22007-11-06 19:50:53 +000087
Ted Kremenek177c5712007-12-05 22:08:43 +000088 // Deserialize the translation unit.
Ted Kremenekeccf0702007-12-18 21:44:50 +000089 TranslationUnit* NewTU = ReadASTBitcodeFile(Filename,FMgr);
Ted Kremenek286333d2007-11-14 17:46:35 +000090
Ted Kremenek177c5712007-12-05 22:08:43 +000091 if (!NewTU)
92 return false;
Ted Kremenek286333d2007-11-14 17:46:35 +000093
Ted Kremenek177c5712007-12-05 22:08:43 +000094 {
95 // Pretty-print the deserialized decls to a temp file.
96 std::ofstream DeclPP(FNameDeclPrint.c_str());
97 assert (DeclPP && "Could not open file for printing out decls.");
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000098 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenek177c5712007-12-05 22:08:43 +000099
100 for (TranslationUnit::iterator I=NewTU->begin(), E=NewTU->end(); I!=E; ++I)
101 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek8b61b3b2007-12-03 22:48:14 +0000102 }
Sam Bishop6e104ec2008-04-03 05:03:34 +0000103
104 delete NewTU;
Ted Kremenek1e049d22007-11-06 19:50:53 +0000105
Ted Kremenek177c5712007-12-05 22:08:43 +0000106 return true;
Ted Kremenek1e049d22007-11-06 19:50:53 +0000107}
108
Ted Kremenekb3b25972007-11-28 19:21:47 +0000109namespace {
110 class TmpDirJanitor {
111 llvm::sys::Path& Dir;
112 public:
113 explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
114
115 ~TmpDirJanitor() {
116 llvm::cerr << "Removing: " << Dir.c_str() << '\n';
117 Dir.eraseFromDisk(true);
118 }
119 };
120}
Ted Kremenek1e049d22007-11-06 19:50:53 +0000121
122SerializationTest::~SerializationTest() {
Ted Kremenekb3b25972007-11-28 19:21:47 +0000123
Ted Kremenek1e049d22007-11-06 19:50:53 +0000124 std::string ErrMsg;
Ted Kremenekb3b25972007-11-28 19:21:47 +0000125 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek1e049d22007-11-06 19:50:53 +0000126
Ted Kremenekb3b25972007-11-28 19:21:47 +0000127 if (Dir.isEmpty()) {
Ted Kremenek1e049d22007-11-06 19:50:53 +0000128 llvm::cerr << "Error: " << ErrMsg << "\n";
129 return;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000130 }
131
Ted Kremenekb3b25972007-11-28 19:21:47 +0000132 TmpDirJanitor RemoveTmpOnExit(Dir);
133
134 llvm::sys::Path FNameDeclBefore = Dir;
135 FNameDeclBefore.appendComponent("test.decl_before.txt");
136
137 if (FNameDeclBefore.makeUnique(true,&ErrMsg)) {
Ted Kremenek1e049d22007-11-06 19:50:53 +0000138 llvm::cerr << "Error: " << ErrMsg << "\n";
139 return;
140 }
Ted Kremenek47916ee2007-11-05 21:39:35 +0000141
Ted Kremenekb3b25972007-11-28 19:21:47 +0000142 llvm::sys::Path FNameDeclAfter = Dir;
143 FNameDeclAfter.appendComponent("test.decl_after.txt");
144
145 if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
146 llvm::cerr << "Error: " << ErrMsg << "\n";
147 return;
148 }
149
150 llvm::sys::Path ASTFilename = Dir;
151 ASTFilename.appendComponent("test.ast");
152
153 if (ASTFilename.makeUnique(true,&ErrMsg)) {
154 llvm::cerr << "Error: " << ErrMsg << "\n";
155 return;
156 }
157
158 // Serialize and then deserialize the ASTs.
Ted Kremenek177c5712007-12-05 22:08:43 +0000159 bool status = Serialize(ASTFilename, FNameDeclBefore);
160 assert (status && "Serialization failed.");
161 status = Deserialize(ASTFilename, FNameDeclAfter);
162 assert (status && "Deserialization failed.");
Ted Kremenekb3b25972007-11-28 19:21:47 +0000163
164 // Read both pretty-printed files and compare them.
165
166 using llvm::MemoryBuffer;
167
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000168 llvm::OwningPtr<MemoryBuffer>
Chris Lattnerd9606102008-04-01 18:04:30 +0000169 MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str()));
Ted Kremenekb3b25972007-11-28 19:21:47 +0000170
171 if(!MBufferSer) {
172 llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
173 return;
174 }
175
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000176 llvm::OwningPtr<MemoryBuffer>
Chris Lattnerd9606102008-04-01 18:04:30 +0000177 MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str()));
Ted Kremenekb3b25972007-11-28 19:21:47 +0000178
179 if(!MBufferDSer) {
180 llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
181 return;
182 }
183
184 const char *p1 = MBufferSer->getBufferStart();
185 const char *e1 = MBufferSer->getBufferEnd();
186 const char *p2 = MBufferDSer->getBufferStart();
187 const char *e2 = MBufferDSer->getBufferEnd();
188
189 if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
190 for ( ; p1 != e1 ; ++p1, ++p2 )
191 if (*p1 != *p2) break;
192
193 if (p1 != e1 || p2 != e2 )
194 llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
195 else
196 llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
Ted Kremenek634cadf2007-10-23 22:18:37 +0000197}