aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-08-05 18:50:11 +0000
committerTed Kremenek <kremenek@apple.com>2008-08-05 18:50:11 +0000
commit815c78fd9ab8bd5dfe8e8a91b8c6a413e2b8c889 (patch)
tree547c2e5fd353b83e909ad60e9292bb3af8037ace
parenta11440b68a02d54cd9c4b54160b0e339e0f30754 (diff)
Refactored driver logic for CodeGen into LLVMCodeGenWriter. This ASTConsumer layers on top of LLVMCodeGen (another existing ASTConsumer) to emit bitcode files to disk. This layering takes this logic out of clang.cpp and puts it directly into the ASTConsumer interface. The benefit is that now --emit-llvm works with both serialized ASTs and regular source files.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54364 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Driver/ASTConsumers.cpp76
-rw-r--r--Driver/ASTConsumers.h6
-rw-r--r--Driver/clang.cpp57
-rw-r--r--include/clang/CodeGen/ModuleBuilder.h16
-rw-r--r--lib/CodeGen/CodeGenModule.cpp12
-rw-r--r--lib/CodeGen/CodeGenModule.h9
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp49
7 files changed, 141 insertions, 84 deletions
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp
index efeb9be892..4a2ef778a0 100644
--- a/Driver/ASTConsumers.cpp
+++ b/Driver/ASTConsumers.cpp
@@ -18,9 +18,13 @@
#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);
+}
diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h
index c3cadfdcec..7cb4ffb227 100644
--- a/Driver/ASTConsumers.h
+++ b/Driver/ASTConsumers.h
@@ -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);
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index cb4c5e4bba..56389dfb69 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -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");
diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h
index b6ec1cf142..0f9b39341b 100644
--- a/include/clang/CodeGen/ModuleBuilder.h
+++ b/include/clang/CodeGen/ModuleBuilder.h
@@ -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
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5d85b7a70f..0c3b872b9a 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -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));
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 1fb2cf7ae0..bb5de154fb 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -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;
+ CGObjCRuntime* Runtime;
+ CGDebugInfo* DebugInfo;
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; }
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 201092f4d8..7329ed1d90 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -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);
}
-