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
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp
index efeb9be..4a2ef77 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 @@
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);
+}