pull .ll and .bc writing out of the ASTConsumer destructors into some top
level code in clang.  This is a cleanup, but does implement "-o" for 
-emit-llvm.  One effect of this is that "clang foo.c -emit-llvm" will now
emit into foo.ll instead of stdout.  Use "clang foo.c -emit-llvm -o -" or 
"clang < foo.c -emit-llvm" to get the old behavior.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46791 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index 3aabdc3..6e76a4a 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -34,13 +34,16 @@
 #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/Config/config.h"
 #include "llvm/ADT/OwningPtr.h"
 #include <memory>
+#include <fstream>
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -930,7 +933,8 @@
 ///  parsed from source files as well as those deserialized from Bitcode.
 static ASTConsumer* CreateASTConsumer(const std::string& InFile,
                                       Diagnostic& Diag, FileManager& FileMgr, 
-                                      const LangOptions& LangOpts) {
+                                      const LangOptions& LangOpts,
+                                      llvm::Module *&DestModule) {
   switch (ProgAction) {
     default:
       return NULL;
@@ -964,10 +968,9 @@
       return CreateSerializationTest(Diag, FileMgr, LangOpts);
       
     case EmitLLVM:
-      return CreateLLVMEmitter(Diag, LangOpts);
-
     case EmitBC:
-      return CreateBCWriter(InFile, OutputFile, Diag, LangOpts);
+      DestModule = new llvm::Module(InFile);
+      return CreateLLVMCodeGen(Diag, LangOpts, DestModule);
 
     case SerializeAST:
       // FIXME: Allow user to tailor where the file is written.
@@ -985,13 +988,15 @@
 
   ASTConsumer* Consumer = NULL;
   bool ClearSourceMgr = false;
+  llvm::Module *CodeGenModule = 0;
   
   switch (ProgAction) {
   default:
     Consumer = CreateASTConsumer(InFile,
                                  PP.getDiagnostics(),
                                  PP.getFileManager(),
-                                 PP.getLangOptions());
+                                 PP.getLangOptions(),
+                                 CodeGenModule);
     
     if (!Consumer) {      
       fprintf(stderr, "Unexpected program action!\n");
@@ -1050,6 +1055,41 @@
     // This deletes Consumer.
     ParseAST(PP, Consumer, Stats);
   }
+
+  // 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());
@@ -1093,8 +1133,10 @@
   
   // 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->getLangOpts()));
+    Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts(),
+                               DestModule));
   
   if (!Consumer) {      
     fprintf(stderr, "Unsupported program action with serialized ASTs!\n");
@@ -1103,6 +1145,7 @@
   
   Consumer->Initialize(*TU->getContext());
   
+  // FIXME: We need to inform Consumer about completed TagDecls as well.
   for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)
     Consumer->HandleTopLevelDecl(*I);
 }