]> granicus.if.org Git - clang/commitdiff
Refactored driver logic for CodeGen into LLVMCodeGenWriter. This ASTConsumer layers...
authorTed Kremenek <kremenek@apple.com>
Tue, 5 Aug 2008 18:50:11 +0000 (18:50 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 5 Aug 2008 18:50:11 +0000 (18:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54364 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/ASTConsumers.cpp
Driver/ASTConsumers.h
Driver/clang.cpp
include/clang/CodeGen/ModuleBuilder.h
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/ModuleBuilder.cpp

index efeb9be8929462d55a2f682b8795c6d9a5546d8c..4a2ef778a09db1aa171409e8b66d35fa3b096265 100644 (file)
 #include "clang/Basic/FileManager.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTConsumer.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "llvm/Module.h"
+#include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Support/Streams.h"
 #include "llvm/Support/Timer.h"
 #include "llvm/ADT/OwningPtr.h"
+#include <fstream>
 
 using namespace clang;
 
@@ -631,3 +635,75 @@ ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
   FName.appendSuffix("ast");
   return new SingleFileSerializer(FName);
 }
+
+class LLVMCodeGenWriter : public ASTConsumer {
+  llvm::OwningPtr<CodeGenerator> Gen;
+  const std::string &InFile;
+  const std::string &OutputFile;
+  bool EmitBitcode;
+public:
+  
+  LLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags, const LangOptions &Features,
+                    const std::string& infile, const std::string& outfile,
+                    bool GenerateDebugInfo) 
+  : Gen(CreateLLVMCodeGen(Diags, Features, infile, GenerateDebugInfo)),
+    InFile(infile), OutputFile(outfile), EmitBitcode(EmitBC) {}
+
+  virtual void Initialize(ASTContext &Context) {
+    Gen->Initialize(Context);
+  }
+  
+  virtual void HandleTopLevelDecl(Decl *D) {
+    Gen->HandleTopLevelDecl(D);
+  }
+  
+  virtual void HandleTagDeclDefinition(TagDecl *D) {
+    Gen->HandleTagDeclDefinition(D);
+  }
+  
+  virtual ~LLVMCodeGenWriter() {
+    llvm::OwningPtr<llvm::Module> CodeGenModule(Gen->ReleaseModule());
+    
+    if (!CodeGenModule)
+      return;
+    
+    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 (!EmitBitcode)
+        Path.appendSuffix("ll");
+      else
+        Path.appendSuffix("bc");
+
+      Out = new std::ofstream(Path.toString().c_str(), 
+                              std::ios_base::binary|std::ios_base::out);
+    }
+    
+    if (!EmitBitcode)
+      CodeGenModule->print(*Out);
+    else
+      llvm::WriteBitcodeToFile(CodeGenModule.get(), *Out);
+    
+    if (Out != llvm::cout.stream())
+      delete Out;
+  }
+};
+
+ASTConsumer *clang::CreateLLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags,
+                                            const LangOptions &Features,
+                                            const std::string& InFile,
+                                            const std::string& OutFile,
+                                            bool GenerateDebugInfo) {
+
+  return new LLVMCodeGenWriter(EmitBC, Diags, Features, InFile, OutFile,
+                               GenerateDebugInfo);  
+}
index c3cadfdcec47ece89b426292011950e8390fcb47..7cb4ffb2274044da636ac0a37eb5c87c924cc016 100644 (file)
@@ -40,6 +40,12 @@ ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
                                     const std::string& OutFile,
                                     Diagnostic &Diags,
                                     const LangOptions &LOpts);
+  
+ASTConsumer *CreateLLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags,
+                                     const LangOptions &Features,
+                                     const std::string& InFile,
+                                     const std::string& OutFile,
+                                     bool GenerateDebugInfo);
 
 ASTConsumer* CreateHTMLPrinter(const std::string &OutFile, Diagnostic &D,
                                Preprocessor *PP, PreprocessorFactory* PPF);
index cb4c5e4bba36a29363635815d6ba8fad302dc8f0..56389dfb69390f42116f7e66271d1bf366dadd33 100644 (file)
@@ -37,9 +37,7 @@
 #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"
@@ -47,7 +45,6 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/System/Path.h"
 #include <memory>
-#include <fstream>
 #include <algorithm>
 using namespace clang;
 
@@ -1174,8 +1171,7 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile,
                                       Diagnostic& Diag, FileManager& FileMgr, 
                                       const LangOptions& LangOpts,
                                       Preprocessor *PP,
-                                      PreprocessorFactory *PPF,
-                                      llvm::Module *&DestModule) {
+                                      PreprocessorFactory *PPF) {
   switch (ProgAction) {
     default:
       return NULL;
@@ -1197,8 +1193,8 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile,
       
     case EmitLLVM:
     case EmitBC:
-      DestModule = new llvm::Module(InFile);
-      return CreateLLVMCodeGen(Diag, LangOpts, DestModule, GenerateDebugInfo);
+      return CreateLLVMCodeGenWriter(ProgAction == EmitBC, Diag, LangOpts,
+                                     InFile, OutputFile, GenerateDebugInfo);
 
     case SerializeAST:
       // FIXME: Allow user to tailor where the file is written.
@@ -1225,13 +1221,12 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
 
   ASTConsumer* Consumer = NULL;
   bool ClearSourceMgr = false;
-  llvm::Module *CodeGenModule = 0;
   
   switch (ProgAction) {
   default:
     Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(),
                                  PP.getFileManager(), PP.getLangOptions(), &PP,
-                                 &PPF, CodeGenModule);
+                                 &PPF);
     
     if (!Consumer) {      
       fprintf(stderr, "Unexpected program action!\n");
@@ -1296,47 +1291,6 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
     ParseAST(PP, Consumer, Stats);
   }
 
-  // Don't emit code when the input had errors.
-  if (CodeGenModule && PP.getDiagnostics().hasErrorOccurred()) {
-    delete CodeGenModule;
-    CodeGenModule = 0;
-  }
-
-  // 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());
     PP.PrintStats();
@@ -1379,10 +1333,9 @@ 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<ASTConsumer>
     Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOptions(),
-                               0, 0, DestModule));
+                               0, 0));
   
   if (!Consumer) {      
     fprintf(stderr, "Unsupported program action with serialized ASTs!\n");
index b6ec1cf142dfd147ea84efca72c4b7f62b24a9c2..0f9b39341bd8f588847fdf134643d6c0fb1a65c5 100644 (file)
@@ -14,6 +14,9 @@
 #ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H
 #define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
 
+#include "clang/AST/ASTConsumer.h"
+#include <string>
+
 namespace llvm {
   class Module;
 }
@@ -21,11 +24,16 @@ namespace llvm {
 namespace clang {
   class Diagnostic;
   struct LangOptions;
-  class ASTConsumer;
   
-  ASTConsumer *CreateLLVMCodeGen(Diagnostic &Diags, const LangOptions &Features,
-                                 llvm::Module *&DestModule,
-                                 bool GenerateDebugInfo);
+  class CodeGenerator : public ASTConsumer {
+    public:
+      virtual llvm::Module* ReleaseModule() = 0;    
+  };
+  
+  CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags,
+                                   const LangOptions &Features,
+                                   const std::string& ModuleName,
+                                   bool GenerateDebugInfo);
 }
 
 #endif
index 5d85b7a70f44eaa25e0d81f7f613622d2b987f22..0c3b872b9a9a29df752b58b74e3ed9af3f9556c3 100644 (file)
@@ -42,13 +42,15 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
   Runtime = CreateObjCRuntime(*this);
 
   // If debug info generation is enabled, create the CGDebugInfo object.
-  if (GenerateDebugInfo)
-    DebugInfo = new CGDebugInfo(this);
-  else
-    DebugInfo = NULL;
+  DebugInfo = GenerateDebugInfo ? new CGDebugInfo(this) : 0;      
 }
 
 CodeGenModule::~CodeGenModule() {
+  delete Runtime;
+  delete DebugInfo;
+}
+
+void CodeGenModule::Release() {
   EmitStatics();
   llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction();
   if (ObjCInitFunction)
@@ -56,8 +58,6 @@ CodeGenModule::~CodeGenModule() {
   EmitCtorList(GlobalCtors, "llvm.global_ctors");
   EmitCtorList(GlobalDtors, "llvm.global_dtors");
   EmitAnnotations();
-  delete Runtime;
-  delete DebugInfo;
   // Run the verifier to check that the generated code is consistent.
   assert(!verifyModule(TheModule));
 }
index 1fb2cf7ae024db2b37e2a9a822c4145b7a2baaa1..bb5de154fb18ed2063f5dd321be2902a8f654cbe 100644 (file)
@@ -19,6 +19,7 @@
 #include "clang/AST/Attr.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/OwningPtr.h"
 
 namespace llvm {
   class Module;
@@ -62,8 +63,8 @@ class CodeGenModule {
   const llvm::TargetData &TheTargetData;
   Diagnostic &Diags;
   CodeGenTypes Types;
-  CGObjCRuntime *Runtime;
-  CGDebugInfo *DebugInfo;
+  CGObjCRuntimeRuntime;
+  CGDebugInfoDebugInfo;
 
   llvm::Function *MemCpyFn;
   llvm::Function *MemMoveFn;
@@ -103,8 +104,12 @@ public:
   CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M, 
                 const llvm::TargetData &TD, Diagnostic &Diags,
                 bool GenerateDebugInfo);
+
   ~CodeGenModule();
   
+  /// Release - Finalize LLVM code generation.
+  void Release();
+  
   CGObjCRuntime *getObjCRuntime() { return Runtime; }
   CGDebugInfo *getDebugInfo() { return DebugInfo; }
   ASTContext &getContext() const { return Context; }
index 201092f4d837b2aa60358b89b0854fbaf2f9fbe4..7329ed1d90d067a69bda1c7f4a8d0eafd56d48ec 100644 (file)
@@ -13,7 +13,6 @@
 
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "CodeGenModule.h"
-#include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 using namespace clang;
@@ -27,26 +26,37 @@ using namespace clang;
 #include "llvm/Module.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/OwningPtr.h"
+
 
 namespace {
-  class CodeGenerator : public ASTConsumer {
+  class VISIBILITY_HIDDEN CodeGeneratorImpl : public CodeGenerator {
     Diagnostic &Diags;
-    const llvm::TargetData *TD;
+    llvm::OwningPtr<const llvm::TargetData> TD;
     ASTContext *Ctx;
     const LangOptions &Features;
     bool GenerateDebugInfo;
   protected:
-    llvm::Module *&M;
-    CodeGen::CodeGenModule *Builder;
+    llvm::OwningPtr<llvm::Module> M;
+    llvm::OwningPtr<CodeGen::CodeGenModule> Builder;
   public:
-    CodeGenerator(Diagnostic &diags, const LangOptions &LO,
-                  llvm::Module *&DestModule, bool DebugInfoFlag)
+    CodeGeneratorImpl(Diagnostic &diags, const LangOptions &LO,
+                      const std::string& ModuleName,
+                      bool DebugInfoFlag)
     : Diags(diags), Features(LO), GenerateDebugInfo(DebugInfoFlag),
-    M(DestModule) {}
+      M(new llvm::Module(ModuleName)) {}
+    
+    virtual ~CodeGeneratorImpl() {}
     
-    ~CodeGenerator() {
-      delete Builder;
-      delete TD;
+    virtual llvm::Module* ReleaseModule() {      
+      if (Diags.hasErrorOccurred())
+        return 0;
+      
+      if (Builder)
+        Builder->Release();
+      
+      return M.take();
     }
     
     virtual void Initialize(ASTContext &Context) {
@@ -54,9 +64,9 @@ namespace {
       
       M->setTargetTriple(Ctx->Target.getTargetTriple());
       M->setDataLayout(Ctx->Target.getTargetDescription());
-      TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
-      Builder = new CodeGen::CodeGenModule(Context, Features, *M, *TD, Diags,
-                                           GenerateDebugInfo);
+      TD.reset(new llvm::TargetData(Ctx->Target.getTargetDescription()));
+      Builder.reset(new CodeGen::CodeGenModule(Context, Features, *M, *TD,
+                                               Diags, GenerateDebugInfo));
     }
     
     virtual void HandleTopLevelDecl(Decl *D) {
@@ -128,10 +138,9 @@ namespace {
   };
 }
 
-ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags, 
-                                      const LangOptions &Features,
-                                      llvm::Module *&DestModule,
-                                      bool GenerateDebugInfo) {
-  return new CodeGenerator(Diags, Features, DestModule, GenerateDebugInfo);
+CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags, 
+                                        const LangOptions &Features,
+                                        const std::string& ModuleName,
+                                        bool GenerateDebugInfo) {
+  return new CodeGeneratorImpl(Diags, Features, ModuleName, GenerateDebugInfo);
 }
-