aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}
-