Implement -emit-llvm-bc option

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45339 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp
index 712bf55..c3a6b67 100644
--- a/Driver/ASTConsumers.cpp
+++ b/Driver/ASTConsumers.cpp
@@ -21,6 +21,7 @@
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/LocalCheckers.h"
 #include "llvm/Support/Streams.h"
+#include <fstream>
 
 using namespace clang;
 
@@ -554,17 +555,19 @@
 #include "llvm/Module.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Bitcode/ReaderWriter.h"
 
 namespace {
-  class LLVMEmitter : public ASTConsumer {
+  class CodeGenerator : public ASTConsumer {
     Diagnostic &Diags;
-    llvm::Module *M;
     const llvm::TargetData *TD;
     ASTContext *Ctx;
     const LangOptions &Features;
+  protected:
+    llvm::Module *M;
     CodeGen::CodeGenModule *Builder;
   public:
-    LLVMEmitter(Diagnostic &diags, const LangOptions &LO) 
+    CodeGenerator(Diagnostic &diags, const LangOptions &LO)
       : Diags(diags)
       , Features(LO) {}
     virtual void Initialize(ASTContext &Context) {
@@ -593,7 +596,15 @@
         //    << D->getName() << "'\n";
       }
     }
-    
+  };
+}
+
+namespace {
+  class LLVMEmitter : public CodeGenerator {
+  public:
+    LLVMEmitter(Diagnostic &diags, const LangOptions &LO)
+    : CodeGenerator(diags,LO) {}
+
     ~LLVMEmitter() {
       CodeGen::Terminate(Builder);
       
@@ -601,14 +612,47 @@
       M->print(llvm::cout.stream());
       delete M;
     }
-  }; 
-} // end anonymous namespace
+  };
+}
 
 ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, 
                                       const LangOptions &Features) {
   return new LLVMEmitter(Diags, Features);
 }
 
+namespace {
+  class BCWriter : public CodeGenerator {
+  public:
+    std::ostream& Out;
+
+    BCWriter(std::ostream* out, Diagnostic &diags, const LangOptions &LO)
+    : CodeGenerator(diags,LO)
+    , Out(*out) {}
+
+    ~BCWriter() {
+      CodeGen::Terminate(Builder);
+      llvm::WriteBitcodeToFile(M, Out);
+      delete M;
+    }
+  };
+}
+
+ASTConsumer *clang::CreateBCWriter(const std::string& InFile,
+                                   const std::string& OutputFile,
+                                   Diagnostic &Diags,
+                                   const LangOptions &Features) {
+  std::string FileName = OutputFile;
+  if (!OutputFile.size()) {
+    llvm::sys::Path Path(InFile);
+    Path.eraseSuffix();
+    Path.appendSuffix("bc");
+    FileName = Path.toString();
+  }
+
+  std::ofstream *Out = new std::ofstream(FileName.c_str());
+  return new BCWriter(Out, Diags, Features);
+}
+
 //===----------------------------------------------------------------------===//
 // AST Serializer