From a1fa3a19bf2c4553aa7e7f27ff2a1b3b2e2db62c Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 13 Dec 2007 00:37:31 +0000 Subject: [PATCH] Implemented -serialize-ast option for the driver. This is not really tested and is a work in progress. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44967 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/ASTConsumers.cpp | 38 ++++++++++++++++++++++++++++++++++++++ Driver/ASTConsumers.h | 5 +++++ Driver/TranslationUnit.cpp | 7 ++++--- Driver/TranslationUnit.h | 4 ++-- Driver/clang.cpp | 27 ++++++++++++++++++++++++--- 5 files changed, 73 insertions(+), 8 deletions(-) diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 790baf5a70..332f589f05 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "ASTConsumers.h" +#include "TranslationUnit.h" #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/CFG.h" @@ -604,3 +605,40 @@ ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Feat return new LLVMEmitter(Diags, Features); } +//===----------------------------------------------------------------------===// +// AST Serializer + +namespace { + class ASTSerializer : public ASTConsumer { + Diagnostic &Diags; + TranslationUnit TU; + const llvm::sys::Path FName; + public: + ASTSerializer(const llvm::sys::Path& F, Diagnostic &diags, + const LangOptions &LO) + : Diags(diags), TU(LO), FName(F) {} + + + virtual void Initialize(ASTContext &Context, unsigned MainFileID) { + TU.setContext(&Context); + } + + virtual void HandleTopLevelDecl(Decl *D) { + // If an error occurred, stop code generation, but continue parsing and + // semantic analysis (to ensure all warnings and errors are emitted). + if (Diags.hasErrorOccurred()) + return; + + TU.AddTopLevelDecl(D); + } + + ~ASTSerializer() { TU.EmitBitcodeFile(FName); } + }; +} // end anonymous namespace + + +ASTConsumer *clang::CreateASTSerializer(const llvm::sys::Path& FName, + Diagnostic &Diags, + const LangOptions &Features) { + return new ASTSerializer(FName, Diags, Features); +} diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h index ab2f0ee6d4..027370f708 100644 --- a/Driver/ASTConsumers.h +++ b/Driver/ASTConsumers.h @@ -16,6 +16,8 @@ #include +namespace llvm { namespace sys { class Path; }} + namespace clang { class ASTConsumer; @@ -34,6 +36,9 @@ ASTConsumer *CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features); ASTConsumer *CreateCodeRewriterTest(Diagnostic &Diags); ASTConsumer *CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr, const LangOptions &LOpts); + +ASTConsumer *CreateASTSerializer(const llvm::sys::Path& FName, + Diagnostic &Diags, const LangOptions &LOpts); } // end clang namespace diff --git a/Driver/TranslationUnit.cpp b/Driver/TranslationUnit.cpp index 62a27f55ac..398afb0666 100644 --- a/Driver/TranslationUnit.cpp +++ b/Driver/TranslationUnit.cpp @@ -33,7 +33,7 @@ namespace { using namespace clang; -bool TranslationUnit::EmitBitcodeFile(llvm::sys::Path& Filename) const { +bool TranslationUnit::EmitBitcodeFile(const llvm::sys::Path& Filename) const { // Reserve 256K for bitstream buffer. std::vector Buffer; @@ -122,8 +122,9 @@ void TranslationUnit::Emit(llvm::Serializer& Sezr) const { Sezr.ExitBlock(); // exit "ASTContextBlock" } -TranslationUnit* TranslationUnit::ReadBitcodeFile(llvm::sys::Path& Filename, - FileManager& FMgr) { +TranslationUnit* +TranslationUnit::ReadBitcodeFile(const llvm::sys::Path& Filename, + FileManager& FMgr) { // Create the memory buffer that contains the contents of the file. llvm::scoped_ptr diff --git a/Driver/TranslationUnit.h b/Driver/TranslationUnit.h index f0c93663b9..b22ec469f5 100644 --- a/Driver/TranslationUnit.h +++ b/Driver/TranslationUnit.h @@ -47,7 +47,7 @@ public: const LangOptions& getLangOpts() const { return LangOpts; } /// EmitBitcodeFile - Emit the translation unit to a bitcode file. - bool EmitBitcodeFile(llvm::sys::Path& Filename) const; + bool EmitBitcodeFile(const llvm::sys::Path& Filename) const; /// Emit - Emit the translation unit to an arbitray bitcode stream. void Emit(llvm::Serializer& S) const; @@ -56,7 +56,7 @@ public: static TranslationUnit* Create(llvm::Deserializer& D, FileManager& FMgr); /// ReadBitcodeFile - Reconsitute a translation unit from a bitcode file. - static TranslationUnit* ReadBitcodeFile(llvm::sys::Path& Filename, + static TranslationUnit* ReadBitcodeFile(const llvm::sys::Path& Filename, FileManager& FMgr); // Accessors diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 76cad929d1..8c08d7cadc 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -53,6 +53,7 @@ Stats("stats", llvm::cl::desc("Print performance metrics and statistics")); enum ProgActions { RewriteTest, // Rewriter testing stuff. EmitLLVM, // Emit a .ll file. + SerializeAST, // Emit a .ast file. ASTPrint, // Parse ASTs and print them. ASTDump, // Parse ASTs and dump them. ASTView, // Parse ASTs and view them in Graphviz. @@ -107,6 +108,8 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore, "Run prototype serializtion code."), clEnumValN(EmitLLVM, "emit-llvm", "Build ASTs then convert to LLVM, emit .ll file"), + clEnumValN(SerializeAST, "serialize-ast", + "Build ASTs and emit .ast file"), clEnumValN(RewriteTest, "rewrite-test", "Playground for the code rewriter"), clEnumValEnd)); @@ -816,7 +819,8 @@ static void ParseFile(Preprocessor &PP, MinimalAction *PA, unsigned MainFileID){ /// CreateASTConsumer - Create the ASTConsumer for the corresponding program /// action. These consumers can operate on both ASTs that are freshly /// parsed from source files as well as those deserialized from Bitcode. -static ASTConsumer* CreateASTConsumer(Diagnostic& Diag, FileManager& FileMgr, +static ASTConsumer* CreateASTConsumer(const std::string& InFile, + Diagnostic& Diag, FileManager& FileMgr, const LangOptions& LangOpts) { switch (ProgAction) { default: @@ -850,6 +854,21 @@ static ASTConsumer* CreateASTConsumer(Diagnostic& Diag, FileManager& FileMgr, case EmitLLVM: return CreateLLVMEmitter(Diag, LangOpts); + case SerializeAST: { + // FIXME: Allow user to tailor where the file is written. + llvm::sys::Path FName = llvm::sys::Path::GetTemporaryDirectory(NULL); + FName.appendComponent((InFile + ".ast").c_str()); + + if (FName.makeUnique(true,NULL)) { + fprintf (stderr, "error: cannot create serialized file: '%s'\n", + FName.c_str()); + + return NULL; + } + + return CreateASTSerializer(FName, Diag, LangOpts); + } + case RewriteTest: return CreateCodeRewriterTest(Diag); } @@ -869,7 +888,8 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID, switch (ProgAction) { default: - Consumer = CreateASTConsumer(PP.getDiagnostics(), HeaderInfo.getFileMgr(), + Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(), + HeaderInfo.getFileMgr(), PP.getLangOptions()); if (!Consumer) { @@ -964,7 +984,8 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag, } TranslationUnit* TU = TranslationUnit::ReadBitcodeFile(Filename,FileMgr); - ASTConsumer* Consumer = CreateASTConsumer(Diag,FileMgr,TU->getLangOpts()); + ASTConsumer* Consumer = CreateASTConsumer(InFile,Diag, + FileMgr,TU->getLangOpts()); if (!Consumer) { fprintf(stderr, "Unsupported program action with serialized ASTs!\n");