blob: 50d06d4d77adcac9b86d8eb87194816041638ef3 [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"
Daniel Dunbarde300732008-08-11 04:54:23 +000019#include "clang/AST/Decl.h"
Ted Kremenek8b61b3b2007-12-03 22:48:14 +000020#include "clang.h"
Ted Kremenek177c5712007-12-05 22:08:43 +000021#include "ASTConsumers.h"
Ted Kremenek3a0b28b2007-12-18 21:36:21 +000022#include "clang/AST/TranslationUnit.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"
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000026#include <fstream>
Chris Lattner8b8720f2008-03-10 17:04:53 +000027#include <cstring>
Ted Kremenek221bb8d2007-10-16 23:37:27 +000028using namespace clang;
Ted Kremenek221bb8d2007-10-16 23:37:27 +000029
Ted Kremenekb3b25972007-11-28 19:21:47 +000030//===----------------------------------------------------------------------===//
Ted Kremenekb3b25972007-11-28 19:21:47 +000031// Driver code.
32//===----------------------------------------------------------------------===//
33
Ted Kremenek177c5712007-12-05 22:08:43 +000034namespace {
Ted Kremenek47916ee2007-11-05 21:39:35 +000035
Ted Kremenek177c5712007-12-05 22:08:43 +000036class SerializationTest : public ASTConsumer {
Ted Kremenek177c5712007-12-05 22:08:43 +000037 Diagnostic &Diags;
38 FileManager &FMgr;
Ted Kremenek1e049d22007-11-06 19:50:53 +000039public:
Ted Kremenek842126e2008-06-04 15:55:15 +000040 SerializationTest(Diagnostic &d, FileManager& fmgr)
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000041 : Diags(d), FMgr(fmgr) {}
Ted Kremenek923de592007-12-05 00:26:13 +000042
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000043 ~SerializationTest() {}
44
45 virtual void HandleTranslationUnit(TranslationUnit& TU);
Ted Kremenekab749372007-12-19 19:27:38 +000046
Ted Kremenek1e049d22007-11-06 19:50:53 +000047private:
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000048 bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint,
49 TranslationUnit& TU);
50
Ted Kremenek177c5712007-12-05 22:08:43 +000051 bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
Ted Kremenek47916ee2007-11-05 21:39:35 +000052};
53
Ted Kremenek634cadf2007-10-23 22:18:37 +000054} // end anonymous namespace
Ted Kremenek221bb8d2007-10-16 23:37:27 +000055
Ted Kremenek923de592007-12-05 00:26:13 +000056ASTConsumer*
Ted Kremenek842126e2008-06-04 15:55:15 +000057clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr) {
58 return new SerializationTest(Diags, FMgr);
Ted Kremenek1e049d22007-11-06 19:50:53 +000059}
60
Ted Kremenek1e049d22007-11-06 19:50:53 +000061
Ted Kremenek177c5712007-12-05 22:08:43 +000062bool SerializationTest::Serialize(llvm::sys::Path& Filename,
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000063 llvm::sys::Path& FNameDeclPrint,
64 TranslationUnit& TU) {
Ted Kremenek177c5712007-12-05 22:08:43 +000065 {
66 // Pretty-print the decls to a temp file.
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000067 std::ofstream DeclPP(FNameDeclPrint.c_str());
68 assert (DeclPP && "Could not open file for printing out decls.");
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000069 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenekea5bfc72007-11-13 22:56:10 +000070
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000071 for (TranslationUnit::iterator I=TU.begin(), E=TU.end(); I!=E; ++I)
Ted Kremenek177c5712007-12-05 22:08:43 +000072 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek9dcb2882007-11-10 02:07:12 +000073 }
74
Ted Kremenek177c5712007-12-05 22:08:43 +000075 // Serialize the translation unit.
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000076 return EmitASTBitcodeFile(TU,Filename);
Ted Kremenek221bb8d2007-10-16 23:37:27 +000077}
78
Ted Kremenek177c5712007-12-05 22:08:43 +000079bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
Ted Kremenekb3b25972007-11-28 19:21:47 +000080 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek1e049d22007-11-06 19:50:53 +000081
Ted Kremenek177c5712007-12-05 22:08:43 +000082 // Deserialize the translation unit.
Ted Kremenek842126e2008-06-04 15:55:15 +000083 TranslationUnit* NewTU = ReadASTBitcodeFile(Filename, FMgr);
Ted Kremenek286333d2007-11-14 17:46:35 +000084
Ted Kremenek177c5712007-12-05 22:08:43 +000085 if (!NewTU)
86 return false;
Ted Kremenek286333d2007-11-14 17:46:35 +000087
Ted Kremenekcab0b0c2008-08-08 04:15:52 +000088 {
Ted Kremenek177c5712007-12-05 22:08:43 +000089 // Pretty-print the deserialized decls to a temp file.
90 std::ofstream DeclPP(FNameDeclPrint.c_str());
91 assert (DeclPP && "Could not open file for printing out decls.");
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +000092 llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenek177c5712007-12-05 22:08:43 +000093
94 for (TranslationUnit::iterator I=NewTU->begin(), E=NewTU->end(); I!=E; ++I)
95 FilePrinter->HandleTopLevelDecl(*I);
Ted Kremenek8b61b3b2007-12-03 22:48:14 +000096 }
Sam Bishop6e104ec2008-04-03 05:03:34 +000097
98 delete NewTU;
Ted Kremenek1e049d22007-11-06 19:50:53 +000099
Ted Kremenek177c5712007-12-05 22:08:43 +0000100 return true;
Ted Kremenek1e049d22007-11-06 19:50:53 +0000101}
102
Ted Kremenekb3b25972007-11-28 19:21:47 +0000103namespace {
104 class TmpDirJanitor {
105 llvm::sys::Path& Dir;
106 public:
107 explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
108
109 ~TmpDirJanitor() {
110 llvm::cerr << "Removing: " << Dir.c_str() << '\n';
111 Dir.eraseFromDisk(true);
112 }
113 };
114}
Ted Kremenek1e049d22007-11-06 19:50:53 +0000115
Ted Kremenekcab0b0c2008-08-08 04:15:52 +0000116void SerializationTest::HandleTranslationUnit(TranslationUnit& TU) {
Ted Kremenekb3b25972007-11-28 19:21:47 +0000117
Ted Kremenek1e049d22007-11-06 19:50:53 +0000118 std::string ErrMsg;
Ted Kremenekb3b25972007-11-28 19:21:47 +0000119 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek1e049d22007-11-06 19:50:53 +0000120
Ted Kremenekb3b25972007-11-28 19:21:47 +0000121 if (Dir.isEmpty()) {
Ted Kremenek1e049d22007-11-06 19:50:53 +0000122 llvm::cerr << "Error: " << ErrMsg << "\n";
123 return;
Ted Kremenek634cadf2007-10-23 22:18:37 +0000124 }
125
Ted Kremenekb3b25972007-11-28 19:21:47 +0000126 TmpDirJanitor RemoveTmpOnExit(Dir);
127
128 llvm::sys::Path FNameDeclBefore = Dir;
129 FNameDeclBefore.appendComponent("test.decl_before.txt");
130
131 if (FNameDeclBefore.makeUnique(true,&ErrMsg)) {
Ted Kremenek1e049d22007-11-06 19:50:53 +0000132 llvm::cerr << "Error: " << ErrMsg << "\n";
133 return;
134 }
Ted Kremenek47916ee2007-11-05 21:39:35 +0000135
Ted Kremenekb3b25972007-11-28 19:21:47 +0000136 llvm::sys::Path FNameDeclAfter = Dir;
137 FNameDeclAfter.appendComponent("test.decl_after.txt");
138
139 if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
140 llvm::cerr << "Error: " << ErrMsg << "\n";
141 return;
142 }
143
144 llvm::sys::Path ASTFilename = Dir;
145 ASTFilename.appendComponent("test.ast");
146
147 if (ASTFilename.makeUnique(true,&ErrMsg)) {
148 llvm::cerr << "Error: " << ErrMsg << "\n";
149 return;
150 }
151
152 // Serialize and then deserialize the ASTs.
Ted Kremenekcab0b0c2008-08-08 04:15:52 +0000153 bool status = Serialize(ASTFilename, FNameDeclBefore, TU);
Ted Kremenek177c5712007-12-05 22:08:43 +0000154 assert (status && "Serialization failed.");
155 status = Deserialize(ASTFilename, FNameDeclAfter);
156 assert (status && "Deserialization failed.");
Ted Kremenekb3b25972007-11-28 19:21:47 +0000157
158 // Read both pretty-printed files and compare them.
159
160 using llvm::MemoryBuffer;
161
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000162 llvm::OwningPtr<MemoryBuffer>
Chris Lattnerd9606102008-04-01 18:04:30 +0000163 MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str()));
Ted Kremenekb3b25972007-11-28 19:21:47 +0000164
165 if(!MBufferSer) {
166 llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
167 return;
168 }
169
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000170 llvm::OwningPtr<MemoryBuffer>
Chris Lattnerd9606102008-04-01 18:04:30 +0000171 MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str()));
Ted Kremenekb3b25972007-11-28 19:21:47 +0000172
173 if(!MBufferDSer) {
174 llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
175 return;
176 }
177
178 const char *p1 = MBufferSer->getBufferStart();
179 const char *e1 = MBufferSer->getBufferEnd();
180 const char *p2 = MBufferDSer->getBufferStart();
181 const char *e2 = MBufferDSer->getBufferEnd();
182
183 if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
184 for ( ; p1 != e1 ; ++p1, ++p2 )
185 if (*p1 != *p2) break;
186
187 if (p1 != e1 || p2 != e2 )
188 llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
189 else
190 llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
Ted Kremenek634cadf2007-10-23 22:18:37 +0000191}