#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;
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);
+}
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);
#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/ADT/OwningPtr.h"
#include "llvm/System/Path.h"
#include <memory>
-#include <fstream>
#include <algorithm>
using namespace clang;
Diagnostic& Diag, FileManager& FileMgr,
const LangOptions& LangOpts,
Preprocessor *PP,
- PreprocessorFactory *PPF,
- llvm::Module *&DestModule) {
+ PreprocessorFactory *PPF) {
switch (ProgAction) {
default:
return NULL;
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.
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");
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();
// 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");
#ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H
#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
+#include "clang/AST/ASTConsumer.h"
+#include <string>
+
namespace llvm {
class Module;
}
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
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)
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));
}
#include "clang/AST/Attr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/OwningPtr.h"
namespace llvm {
class Module;
const llvm::TargetData &TheTargetData;
Diagnostic &Diags;
CodeGenTypes Types;
- CGObjCRuntime *Runtime;
- CGDebugInfo *DebugInfo;
+ CGObjCRuntime* Runtime;
+ CGDebugInfo* DebugInfo;
llvm::Function *MemCpyFn;
llvm::Function *MemMoveFn;
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; }
#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;
#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) {
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) {
};
}
-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);
}
-