2007-10-17 07:37:27 +08:00
|
|
|
//===--- SerializationTest.cpp - Experimental Object Serialization --------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by Ted Kremenek and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements prototype code for serialization of objects in clang.
|
|
|
|
// It is not intended yet for public use, but simply is a placeholder to
|
|
|
|
// experiment with new serialization features. Serialization will eventually
|
|
|
|
// be integrated as a proper component of the clang libraries.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ASTConsumers.h"
|
|
|
|
#include "clang/AST/AST.h"
|
|
|
|
#include "clang/AST/ASTConsumer.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2007-11-29 09:24:25 +08:00
|
|
|
#include "clang/AST/CFG.h"
|
2007-10-17 07:37:27 +08:00
|
|
|
#include "llvm/System/Path.h"
|
2007-10-24 06:18:37 +08:00
|
|
|
#include "llvm/Support/Streams.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2007-10-25 03:06:02 +08:00
|
|
|
#include "llvm/Bitcode/Serialize.h"
|
|
|
|
#include "llvm/Bitcode/Deserialize.h"
|
2007-11-29 05:32:21 +08:00
|
|
|
#include <fstream>
|
2007-10-24 06:18:37 +08:00
|
|
|
#include <stdio.h>
|
2007-11-07 03:50:53 +08:00
|
|
|
#include <list>
|
2007-10-24 06:18:37 +08:00
|
|
|
|
2007-10-17 07:37:27 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utility classes
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-10-24 06:18:37 +08:00
|
|
|
namespace {
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
template<typename T> class Janitor {
|
2007-11-06 05:39:35 +08:00
|
|
|
T* Obj;
|
2007-11-29 03:21:47 +08:00
|
|
|
public:
|
|
|
|
explicit Janitor(T* obj) : Obj(obj) {}
|
2007-11-06 05:39:35 +08:00
|
|
|
~Janitor() { delete Obj; }
|
2007-11-29 03:21:47 +08:00
|
|
|
operator T*() const { return Obj; }
|
|
|
|
T* operator->() { return Obj; }
|
2007-11-06 05:39:35 +08:00
|
|
|
};
|
2007-11-29 03:21:47 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Driver code.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-11-06 05:39:35 +08:00
|
|
|
class SerializationTest : public ASTConsumer {
|
|
|
|
ASTContext* Context;
|
2007-11-07 03:50:53 +08:00
|
|
|
std::list<Decl*> Decls;
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-15 01:46:35 +08:00
|
|
|
enum { BasicMetadataBlock,
|
|
|
|
ASTContextBlock,
|
|
|
|
DeclsBlock };
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
public:
|
|
|
|
SerializationTest() : Context(NULL) {};
|
|
|
|
~SerializationTest();
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
virtual void Initialize(ASTContext& context, unsigned) {
|
|
|
|
Context = &context;
|
2007-10-17 07:37:27 +08:00
|
|
|
}
|
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
virtual void HandleTopLevelDecl(Decl *D) {
|
|
|
|
Decls.push_back(D);
|
2007-10-17 07:37:27 +08:00
|
|
|
}
|
2007-11-07 03:50:53 +08:00
|
|
|
|
|
|
|
private:
|
2007-11-29 03:21:47 +08:00
|
|
|
void Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
|
|
|
|
void Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
|
2007-11-07 03:50:53 +08:00
|
|
|
};
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
} // end anonymous namespace
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
ASTConsumer* clang::CreateSerializationTest() {
|
|
|
|
return new SerializationTest();
|
2007-11-06 05:39:35 +08:00
|
|
|
}
|
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
static void WritePreamble(llvm::BitstreamWriter& Stream) {
|
|
|
|
Stream.Emit((unsigned)'B', 8);
|
|
|
|
Stream.Emit((unsigned)'C', 8);
|
|
|
|
Stream.Emit(0xC, 4);
|
|
|
|
Stream.Emit(0xF, 4);
|
|
|
|
Stream.Emit(0xE, 4);
|
|
|
|
Stream.Emit(0x0, 4);
|
|
|
|
}
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-07 07:52:19 +08:00
|
|
|
static bool ReadPreamble(llvm::BitstreamReader& Stream) {
|
2007-11-07 03:50:53 +08:00
|
|
|
return Stream.Read(8) != 'B' ||
|
|
|
|
Stream.Read(8) != 'C' ||
|
|
|
|
Stream.Read(4) != 0xC ||
|
|
|
|
Stream.Read(4) != 0xF ||
|
|
|
|
Stream.Read(4) != 0xE ||
|
|
|
|
Stream.Read(4) != 0x0;
|
|
|
|
}
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
void SerializationTest::Serialize(llvm::sys::Path& Filename,
|
|
|
|
llvm::sys::Path& FNameDeclPrint) {
|
2007-11-07 03:50:53 +08:00
|
|
|
|
|
|
|
// Reserve 256K for bitstream buffer.
|
|
|
|
std::vector<unsigned char> Buffer;
|
|
|
|
Buffer.reserve(256*1024);
|
|
|
|
|
|
|
|
// Create bitstream and write preamble.
|
|
|
|
llvm::BitstreamWriter Stream(Buffer);
|
|
|
|
WritePreamble(Stream);
|
|
|
|
|
|
|
|
// Create serializer.
|
|
|
|
llvm::Serializer Sezr(Stream);
|
|
|
|
|
2007-11-10 10:07:12 +08:00
|
|
|
// ===---------------------------------------------------===/
|
|
|
|
// Serialize the top-level decls.
|
|
|
|
// ===---------------------------------------------------===/
|
|
|
|
|
2007-11-15 01:46:35 +08:00
|
|
|
Sezr.EnterBlock(DeclsBlock);
|
2007-11-14 06:56:10 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
{ // Create a printer to "consume" our deserialized ASTS.
|
|
|
|
|
|
|
|
Janitor<ASTConsumer> Printer(CreateASTPrinter());
|
2007-11-29 05:32:21 +08:00
|
|
|
std::ofstream DeclPP(FNameDeclPrint.c_str());
|
|
|
|
assert (DeclPP && "Could not open file for printing out decls.");
|
|
|
|
Janitor<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
|
2007-11-14 06:56:10 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) {
|
|
|
|
llvm::cerr << "Serializing: Decl.\n";
|
|
|
|
|
2007-11-30 03:04:54 +08:00
|
|
|
// Only serialize the head of a decl chain. The ASTConsumer interfaces
|
|
|
|
// provides us with each top-level decl, including those nested in
|
|
|
|
// a decl chain, so we may be passed decls that are already serialized.
|
|
|
|
if (!Sezr.isRegistered(*I)) {
|
|
|
|
Printer->HandleTopLevelDecl(*I);
|
|
|
|
FilePrinter->HandleTopLevelDecl(*I);
|
|
|
|
|
|
|
|
if (FunctionDecl* FD = dyn_cast<FunctionDecl>(*I))
|
|
|
|
if (FD->getBody()) {
|
|
|
|
// Construct and print a CFG.
|
|
|
|
Janitor<CFG> cfg(CFG::buildCFG(FD->getBody()));
|
|
|
|
cfg->print(DeclPP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serialize the decl.
|
|
|
|
Sezr.EmitOwnedPtr(*I);
|
|
|
|
}
|
2007-11-29 03:21:47 +08:00
|
|
|
}
|
2007-11-10 10:07:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Sezr.ExitBlock();
|
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// ===---------------------------------------------------===/
|
|
|
|
// Serialize the "Translation Unit" metadata.
|
|
|
|
// ===---------------------------------------------------===/
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-15 01:46:35 +08:00
|
|
|
// Emit ASTContext.
|
|
|
|
Sezr.EnterBlock(ASTContextBlock);
|
|
|
|
llvm::cerr << "Serializing: ASTContext.\n";
|
|
|
|
Sezr.EmitOwnedPtr(Context);
|
|
|
|
Sezr.ExitBlock();
|
|
|
|
|
|
|
|
|
|
|
|
Sezr.EnterBlock(BasicMetadataBlock);
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// "Fake" emit the SourceManager.
|
|
|
|
llvm::cerr << "Faux-serializing: SourceManager.\n";
|
|
|
|
Sezr.EmitPtr(&Context->SourceMgr);
|
|
|
|
|
|
|
|
// "Fake" emit the Target.
|
|
|
|
llvm::cerr << "Faux-serializing: Target.\n";
|
|
|
|
Sezr.EmitPtr(&Context->Target);
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// "Fake" emit Selectors.
|
|
|
|
llvm::cerr << "Faux-serializing: Selectors.\n";
|
|
|
|
Sezr.EmitPtr(&Context->Selectors);
|
2007-10-24 06:18:37 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// Emit the Identifier Table.
|
|
|
|
llvm::cerr << "Serializing: IdentifierTable.\n";
|
|
|
|
Sezr.EmitOwnedPtr(&Context->Idents);
|
2007-11-15 01:46:35 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
Sezr.ExitBlock();
|
|
|
|
|
|
|
|
// ===---------------------------------------------------===/
|
2007-11-29 03:21:47 +08:00
|
|
|
// Finalize serialization: write the bits to disk.
|
2007-11-29 05:32:21 +08:00
|
|
|
if (FILE* fp = fopen(Filename.c_str(),"wb")) {
|
|
|
|
fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n";
|
|
|
|
return;
|
2007-10-17 07:37:27 +08:00
|
|
|
}
|
2007-10-24 06:18:37 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
llvm::cerr << "Commited bitstream to disk: " << Filename.c_str() << "\n";
|
2007-10-17 07:37:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
void SerializationTest::Deserialize(llvm::sys::Path& Filename,
|
|
|
|
llvm::sys::Path& FNameDeclPrint) {
|
2007-11-07 03:50:53 +08:00
|
|
|
|
|
|
|
// Create the memory buffer that contains the contents of the file.
|
|
|
|
|
|
|
|
using llvm::MemoryBuffer;
|
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
Janitor<MemoryBuffer> MBuffer(MemoryBuffer::getFile(Filename.c_str(),
|
|
|
|
strlen(Filename.c_str())));
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-06 05:39:35 +08:00
|
|
|
if(!MBuffer) {
|
|
|
|
llvm::cerr << "ERROR: Cannot read file for deserialization.\n";
|
|
|
|
return;
|
2007-10-24 06:18:37 +08:00
|
|
|
}
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// Check if the file is of the proper length.
|
2007-11-06 05:39:35 +08:00
|
|
|
if (MBuffer->getBufferSize() & 0x3) {
|
2007-11-07 03:50:53 +08:00
|
|
|
llvm::cerr << "ERROR: AST file length should be a multiple of 4 bytes.\n";
|
2007-11-06 05:39:35 +08:00
|
|
|
return;
|
2007-10-17 07:37:27 +08:00
|
|
|
}
|
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// Create the bitstream reader.
|
|
|
|
unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
|
|
|
|
llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
|
2007-10-24 06:18:37 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// Sniff for the signature in the bitcode file.
|
2007-11-07 07:52:19 +08:00
|
|
|
if (ReadPreamble(Stream)) {
|
2007-11-06 05:39:35 +08:00
|
|
|
llvm::cerr << "ERROR: Invalid AST-bitcode signature.\n";
|
|
|
|
return;
|
2007-11-10 10:07:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create the deserializer.
|
2007-11-07 03:50:53 +08:00
|
|
|
llvm::Deserializer Dezr(Stream);
|
|
|
|
|
|
|
|
// ===---------------------------------------------------===/
|
|
|
|
// Deserialize the "Translation Unit" metadata.
|
|
|
|
// ===---------------------------------------------------===/
|
|
|
|
|
2007-11-15 01:46:35 +08:00
|
|
|
// Skip to the BasicMetaDataBlock. First jump to ASTContextBlock
|
|
|
|
// (which will appear earlier) and record its location.
|
|
|
|
|
|
|
|
bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
|
|
|
|
assert (FoundBlock);
|
|
|
|
|
|
|
|
llvm::Deserializer::Location ASTContextBlockLoc =
|
|
|
|
Dezr.getCurrentBlockLocation();
|
|
|
|
|
|
|
|
FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
|
2007-11-10 10:07:12 +08:00
|
|
|
assert (FoundBlock);
|
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// "Fake" read the SourceManager.
|
|
|
|
llvm::cerr << "Faux-Deserializing: SourceManager.\n";
|
|
|
|
Dezr.RegisterPtr(&Context->SourceMgr);
|
|
|
|
|
|
|
|
// "Fake" read the TargetInfo.
|
|
|
|
llvm::cerr << "Faux-Deserializing: Target.\n";
|
|
|
|
Dezr.RegisterPtr(&Context->Target);
|
|
|
|
|
|
|
|
// "Fake" read the Selectors.
|
|
|
|
llvm::cerr << "Faux-Deserializing: Selectors.\n";
|
|
|
|
Dezr.RegisterPtr(&Context->Selectors);
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// Read the identifier table.
|
|
|
|
llvm::cerr << "Deserializing: IdentifierTable\n";
|
|
|
|
Dezr.ReadOwnedPtr<IdentifierTable>();
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-15 01:46:35 +08:00
|
|
|
// Now jump back to ASTContextBlock and read the ASTContext.
|
|
|
|
Dezr.JumpTo(ASTContextBlockLoc);
|
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// Read the ASTContext.
|
|
|
|
llvm::cerr << "Deserializing: ASTContext.\n";
|
|
|
|
Dezr.ReadOwnedPtr<ASTContext>();
|
2007-11-29 03:21:47 +08:00
|
|
|
|
2007-11-10 10:07:12 +08:00
|
|
|
// "Rewind" the stream. Find the block with the serialized top-level decls.
|
|
|
|
Dezr.Rewind();
|
2007-11-15 01:46:35 +08:00
|
|
|
FoundBlock = Dezr.SkipToBlock(DeclsBlock);
|
2007-11-10 10:07:12 +08:00
|
|
|
assert (FoundBlock);
|
|
|
|
llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
|
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
// Create a printer to "consume" our deserialized ASTS.
|
|
|
|
ASTConsumer* Printer = CreateASTPrinter();
|
|
|
|
Janitor<ASTConsumer> PrinterJanitor(Printer);
|
2007-11-29 05:32:21 +08:00
|
|
|
std::ofstream DeclPP(FNameDeclPrint.c_str());
|
|
|
|
assert (DeclPP && "Could not open file for printing out decls.");
|
|
|
|
Janitor<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
|
2007-11-29 03:21:47 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
// The remaining objects in the file are top-level decls.
|
2007-11-10 10:07:12 +08:00
|
|
|
while (!Dezr.FinishedBlock(DeclBlockLoc)) {
|
2007-11-07 03:50:53 +08:00
|
|
|
llvm::cerr << "Deserializing: Decl.\n";
|
|
|
|
Decl* decl = Dezr.ReadOwnedPtr<Decl>();
|
2007-11-29 03:21:47 +08:00
|
|
|
Printer->HandleTopLevelDecl(decl);
|
|
|
|
FilePrinter->HandleTopLevelDecl(decl);
|
2007-11-29 09:24:25 +08:00
|
|
|
|
|
|
|
if (FunctionDecl* FD = dyn_cast<FunctionDecl>(decl))
|
|
|
|
if (FD->getBody()) {
|
|
|
|
// Construct and print a CFG.
|
|
|
|
Janitor<CFG> cfg(CFG::buildCFG(FD->getBody()));
|
|
|
|
cfg->print(DeclPP);
|
|
|
|
}
|
2007-11-07 03:50:53 +08:00
|
|
|
}
|
|
|
|
}
|
2007-11-06 05:39:35 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
namespace {
|
|
|
|
class TmpDirJanitor {
|
|
|
|
llvm::sys::Path& Dir;
|
|
|
|
public:
|
|
|
|
explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
|
|
|
|
|
|
|
|
~TmpDirJanitor() {
|
|
|
|
llvm::cerr << "Removing: " << Dir.c_str() << '\n';
|
|
|
|
Dir.eraseFromDisk(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2007-10-17 07:37:27 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
SerializationTest::~SerializationTest() {
|
2007-11-29 03:21:47 +08:00
|
|
|
|
2007-11-07 03:50:53 +08:00
|
|
|
std::string ErrMsg;
|
2007-11-29 03:21:47 +08:00
|
|
|
llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
|
2007-11-07 03:50:53 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
if (Dir.isEmpty()) {
|
2007-11-07 03:50:53 +08:00
|
|
|
llvm::cerr << "Error: " << ErrMsg << "\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
TmpDirJanitor RemoveTmpOnExit(Dir);
|
|
|
|
|
|
|
|
llvm::sys::Path FNameDeclBefore = Dir;
|
|
|
|
FNameDeclBefore.appendComponent("test.decl_before.txt");
|
|
|
|
|
|
|
|
if (FNameDeclBefore.makeUnique(true,&ErrMsg)) {
|
|
|
|
llvm::cerr << "Error: " << ErrMsg << "\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::sys::Path FNameDeclAfter = Dir;
|
|
|
|
FNameDeclAfter.appendComponent("test.decl_after.txt");
|
|
|
|
|
|
|
|
if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
|
|
|
|
llvm::cerr << "Error: " << ErrMsg << "\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::sys::Path ASTFilename = Dir;
|
|
|
|
ASTFilename.appendComponent("test.ast");
|
2007-11-07 03:50:53 +08:00
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
if (ASTFilename.makeUnique(true,&ErrMsg)) {
|
2007-11-07 03:50:53 +08:00
|
|
|
llvm::cerr << "Error: " << ErrMsg << "\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-11-29 03:21:47 +08:00
|
|
|
// Serialize and then deserialize the ASTs.
|
|
|
|
Serialize(ASTFilename, FNameDeclBefore);
|
|
|
|
Deserialize(ASTFilename, FNameDeclAfter);
|
|
|
|
|
|
|
|
// Read both pretty-printed files and compare them.
|
|
|
|
|
|
|
|
using llvm::MemoryBuffer;
|
|
|
|
|
|
|
|
Janitor<MemoryBuffer>
|
|
|
|
MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str(),
|
|
|
|
strlen(FNameDeclBefore.c_str())));
|
|
|
|
|
|
|
|
if(!MBufferSer) {
|
|
|
|
llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Janitor<MemoryBuffer>
|
|
|
|
MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str(),
|
|
|
|
strlen(FNameDeclAfter.c_str())));
|
|
|
|
|
|
|
|
if(!MBufferDSer) {
|
|
|
|
llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *p1 = MBufferSer->getBufferStart();
|
|
|
|
const char *e1 = MBufferSer->getBufferEnd();
|
|
|
|
const char *p2 = MBufferDSer->getBufferStart();
|
|
|
|
const char *e2 = MBufferDSer->getBufferEnd();
|
|
|
|
|
|
|
|
if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
|
|
|
|
for ( ; p1 != e1 ; ++p1, ++p2 )
|
|
|
|
if (*p1 != *p2) break;
|
|
|
|
|
|
|
|
if (p1 != e1 || p2 != e2 )
|
|
|
|
llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
|
|
|
|
else
|
|
|
|
llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
|
2007-10-24 06:18:37 +08:00
|
|
|
}
|