From: Chris Lattner Date: Wed, 6 Feb 2008 01:42:25 +0000 (+0000) Subject: pull .ll and .bc writing out of the ASTConsumer destructors into some top X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e66b65c3a3377d487104f6adc071d054b0d9d343;p=clang pull .ll and .bc writing out of the ASTConsumer destructors into some top level code in clang. This is a cleanup, but does implement "-o" for -emit-llvm. One effect of this is that "clang foo.c -emit-llvm" will now emit into foo.ll instead of stdout. Use "clang foo.c -emit-llvm -o -" or "clang < foo.c -emit-llvm" to get the old behavior. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46791 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 904a22e59c..4dba24bdce 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -22,8 +22,6 @@ #include "clang/Analysis/Analyses/GRConstants.h" #include "clang/Analysis/LocalCheckers.h" #include "llvm/Support/Streams.h" -#include - using namespace clang; //===----------------------------------------------------------------------===// @@ -607,15 +605,20 @@ namespace { ASTContext *Ctx; const LangOptions &Features; protected: - llvm::Module *M; + llvm::Module *&M; CodeGen::CodeGenModule *Builder; public: - CodeGenerator(Diagnostic &diags, const LangOptions &LO) - : Diags(diags) - , Features(LO) {} + CodeGenerator(Diagnostic &diags, const LangOptions &LO, + llvm::Module *&DestModule) + : Diags(diags), Features(LO), M(DestModule) {} + + ~CodeGenerator() { + CodeGen::Terminate(Builder); + } + virtual void Initialize(ASTContext &Context) { Ctx = &Context; - M = new llvm::Module("foo"); + M->setTargetTriple(Ctx->Target.getTargetTriple()); M->setDataLayout(Ctx->Target.getTargetDescription()); TD = new llvm::TargetData(Ctx->Target.getTargetDescription()); @@ -641,70 +644,10 @@ namespace { }; } -namespace { - class LLVMEmitter : public CodeGenerator { - public: - LLVMEmitter(Diagnostic &diags, const LangOptions &LO) - : CodeGenerator(diags,LO) {} - - ~LLVMEmitter() { - CodeGen::Terminate(Builder); - - // Print the generated code. - M->print(llvm::cout.stream()); - delete M; - } - }; -} - -ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, - const LangOptions &Features) { - return new LLVMEmitter(Diags, Features); -} - -namespace { - class BCWriter : public CodeGenerator { - public: - std::ostream& Out; - - BCWriter(std::ostream* out, Diagnostic &diags, const LangOptions &LO) - : CodeGenerator(diags,LO) - , Out(*out) {} - - ~BCWriter() { - CodeGen::Terminate(Builder); - llvm::WriteBitcodeToFile(M, Out); - delete M; - } - }; -} - -ASTConsumer *clang::CreateBCWriter(const std::string& InFile, - const std::string& OutputFile, - Diagnostic &Diags, - const LangOptions &Features) { - std::string FileName = OutputFile; - - std::ostream *Out; - if (OutputFile == "-") - Out = llvm::cout.stream(); - else if (!OutputFile.size()) { - if (InFile == "-") - Out = llvm::cout.stream(); - else { - llvm::sys::Path Path(InFile); - Path.eraseSuffix(); - Path.appendSuffix("bc"); - FileName = Path.toString(); - Out = new std::ofstream(FileName.c_str(), - std::ios_base::binary|std::ios_base::out); - } - } else { - Out = new std::ofstream(FileName.c_str(), - std::ios_base::binary|std::ios_base::out); - } - - return new BCWriter(Out, Diags, Features); +ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags, + const LangOptions &Features, + llvm::Module *&DestModule) { + return new CodeGenerator(Diags, Features, DestModule); } //===----------------------------------------------------------------------===// diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h index 423b23f27d..3c7589b4fd 100644 --- a/Driver/ASTConsumers.h +++ b/Driver/ASTConsumers.h @@ -16,8 +16,10 @@ #include -namespace llvm { namespace sys { class Path; }} - +namespace llvm { + class Module; + namespace sys { class Path; } +} namespace clang { class ASTConsumer; @@ -41,12 +43,9 @@ ASTConsumer *CreateUnitValsChecker(Diagnostic &Diags); ASTConsumer *CreateGRConstants(); -ASTConsumer *CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features); - -ASTConsumer *CreateBCWriter(const std::string& InFile, - const std::string& OutFile, - Diagnostic &Diags, - const LangOptions &LOpts); + +ASTConsumer *CreateLLVMCodeGen(Diagnostic &Diags, const LangOptions &Features, + llvm::Module *&DestModule); ASTConsumer *CreateCodeRewriterTest(const std::string& InFile, Diagnostic &Diags); diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 3aabdc312c..6e76a4a0cd 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -34,13 +34,16 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/Module.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Signals.h" #include "llvm/Config/config.h" #include "llvm/ADT/OwningPtr.h" #include +#include using namespace clang; //===----------------------------------------------------------------------===// @@ -930,7 +933,8 @@ static void ParseFile(Preprocessor &PP, MinimalAction *PA){ /// parsed from source files as well as those deserialized from Bitcode. static ASTConsumer* CreateASTConsumer(const std::string& InFile, Diagnostic& Diag, FileManager& FileMgr, - const LangOptions& LangOpts) { + const LangOptions& LangOpts, + llvm::Module *&DestModule) { switch (ProgAction) { default: return NULL; @@ -964,10 +968,9 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile, return CreateSerializationTest(Diag, FileMgr, LangOpts); case EmitLLVM: - return CreateLLVMEmitter(Diag, LangOpts); - case EmitBC: - return CreateBCWriter(InFile, OutputFile, Diag, LangOpts); + DestModule = new llvm::Module(InFile); + return CreateLLVMCodeGen(Diag, LangOpts, DestModule); case SerializeAST: // FIXME: Allow user to tailor where the file is written. @@ -985,13 +988,15 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile, ASTConsumer* Consumer = NULL; bool ClearSourceMgr = false; + llvm::Module *CodeGenModule = 0; switch (ProgAction) { default: Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(), PP.getFileManager(), - PP.getLangOptions()); + PP.getLangOptions(), + CodeGenModule); if (!Consumer) { fprintf(stderr, "Unexpected program action!\n"); @@ -1050,6 +1055,41 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile, // This deletes Consumer. ParseAST(PP, Consumer, Stats); } + + // If running the code generator, finish up now. + if (CodeGenModule) { + std::ostream *Out; + if (OutputFile == "-") { + Out = llvm::cout.stream(); + } else if (!OutputFile.empty()) { + Out = new std::ofstream(OutputFile.c_str(), + std::ios_base::binary|std::ios_base::out); + } else if (InFile == "-") { + Out = llvm::cout.stream(); + } else { + llvm::sys::Path Path(InFile); + Path.eraseSuffix(); + if (ProgAction == EmitLLVM) + Path.appendSuffix("ll"); + else if (ProgAction == EmitBC) + Path.appendSuffix("bc"); + else + assert(0 && "Unknown action"); + Out = new std::ofstream(Path.toString().c_str(), + std::ios_base::binary|std::ios_base::out); + } + + if (ProgAction == EmitLLVM) { + CodeGenModule->print(*Out); + } else { + assert(ProgAction == EmitBC); + llvm::WriteBitcodeToFile(CodeGenModule, *Out); + } + + if (Out != llvm::cout.stream()) + delete Out; + delete CodeGenModule; + } if (Stats) { fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str()); @@ -1093,8 +1133,10 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag, // Observe that we use the source file name stored in the deserialized // translation unit, rather than InFile. + llvm::Module *DestModule; llvm::OwningPtr - Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts())); + Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts(), + DestModule)); if (!Consumer) { fprintf(stderr, "Unsupported program action with serialized ASTs!\n"); @@ -1103,6 +1145,7 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag, Consumer->Initialize(*TU->getContext()); + // FIXME: We need to inform Consumer about completed TagDecls as well. for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I) Consumer->HandleTopLevelDecl(*I); } diff --git a/test/CodeGen/bitfield.c b/test/CodeGen/bitfield.c index 441a54a673..70414a9c1e 100644 --- a/test/CodeGen/bitfield.c +++ b/test/CodeGen/bitfield.c @@ -1,4 +1,4 @@ -// RUN: clang %s -emit-llvm > %t1 +// RUN: clang %s -emit-llvm -o - > %t1 // RUN: grep "shl i32 %tmp, 19" %t1 && // RUN: grep "ashr i32 %tmp1, 19" %t1 && // RUN: grep "shl i16 %tmp4, 1" %t1 && diff --git a/test/CodeGen/merge-statics.c b/test/CodeGen/merge-statics.c index 56fd7d4bb6..1e0d689122 100644 --- a/test/CodeGen/merge-statics.c +++ b/test/CodeGen/merge-statics.c @@ -1,4 +1,4 @@ -// RUN: clang %s -emit-llvm | grep internal | count 1 +// RUN: clang < %s -emit-llvm | grep internal | count 1 // The two decls for 'a' should merge into one llvm GlobalVariable. diff --git a/test/CodeGen/struct-x86-darwin.c b/test/CodeGen/struct-x86-darwin.c index faa5bb2dc4..3d3729dc9b 100644 --- a/test/CodeGen/struct-x86-darwin.c +++ b/test/CodeGen/struct-x86-darwin.c @@ -1,4 +1,4 @@ -// RUN: clang %s -emit-llvm > %t1 +// RUN: clang < %s -emit-llvm > %t1 // Run grep "STest1 = type { i32, \[4 x i16\], double }" %t1 && // RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1 && // RUN: grep "STest3 = type { i8, i8, i16, i32 }" %t1 && diff --git a/test/Lexer/11-27-2007-FloatLiterals.c b/test/Lexer/11-27-2007-FloatLiterals.c index b454d5e68e..3f938576a7 100644 --- a/test/Lexer/11-27-2007-FloatLiterals.c +++ b/test/Lexer/11-27-2007-FloatLiterals.c @@ -1,5 +1,5 @@ -// RUN: clang %s -emit-llvm 2>&1 | grep 0x3BFD83C940000000 | count 2 -// RUN: clang %s -emit-llvm 2>&1 | grep 2.000000e+32 | count 2 +// RUN: clang %s -emit-llvm -o - | grep 0x3BFD83C940000000 | count 2 +// RUN: clang %s -emit-llvm -o - | grep 2.000000e+32 | count 2 float F = 1e-19f; double D = 2e32;