Add support for lazily linking bitcode files (using a new
-mlink-bitcode-file flag), and more generally llvm::Modules, before
running optimisations.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143314 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 11d6075..db2bab9 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/AST/ASTConsumer.h"
@@ -18,9 +19,11 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/LLVMContext.h"
+#include "llvm/Linker.h"
 #include "llvm/Module.h"
 #include "llvm/Pass.h"
 #include "llvm/ADT/OwningPtr.h"
+#include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Support/IRReader.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
@@ -42,7 +45,7 @@
 
     llvm::OwningPtr<CodeGenerator> Gen;
 
-    llvm::OwningPtr<llvm::Module> TheModule;
+    llvm::OwningPtr<llvm::Module> TheModule, LinkModule;
 
   public:
     BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags,
@@ -50,7 +53,9 @@
                     const TargetOptions &targetopts,
                     const LangOptions &langopts,
                     bool TimePasses,
-                    const std::string &infile, raw_ostream *OS,
+                    const std::string &infile,
+                    llvm::Module *LinkModule,
+                    raw_ostream *OS,
                     LLVMContext &C) :
       Diags(_Diags),
       Action(action),
@@ -59,11 +64,13 @@
       LangOpts(langopts),
       AsmOutStream(OS),
       LLVMIRGeneration("LLVM IR Generation Time"),
-      Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)) {
+      Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)),
+      LinkModule(LinkModule) {
       llvm::TimePassesIsEnabled = TimePasses;
     }
 
     llvm::Module *takeModule() { return TheModule.take(); }
+    llvm::Module *takeLinkModule() { return LinkModule.take(); }
 
     virtual void Initialize(ASTContext &Ctx) {
       Context = &Ctx;
@@ -122,6 +129,17 @@
       assert(TheModule.get() == M &&
              "Unexpected module change during IR generation");
 
+      // Link LinkModule into this module if present, preserving its validity.
+      if (LinkModule) {
+        std::string ErrorMsg;
+        if (Linker::LinkModules(M, LinkModule.get(), Linker::PreserveSource,
+                                &ErrorMsg)) {
+          Diags.Report(diag::err_fe_cannot_link_module)
+            << LinkModule->getModuleIdentifier() << ErrorMsg;
+          return;
+        }
+      }
+
       // Install an inline asm handler so that diagnostics get printed through
       // our diagnostics hooks.
       LLVMContext &Ctx = TheModule->getContext();
@@ -238,7 +256,8 @@
 //
 
 CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
-  : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
+  : Act(_Act), LinkModule(0),
+    VMContext(_VMContext ? _VMContext : new LLVMContext),
     OwnsVMContext(!_VMContext) {}
 
 CodeGenAction::~CodeGenAction() {
@@ -254,6 +273,10 @@
   if (!getCompilerInstance().hasASTConsumer())
     return;
 
+  // If we were given a link module, release consumer's ownership of it.
+  if (LinkModule)
+    BEConsumer->takeLinkModule();
+
   // Steal the module from the consumer.
   TheModule.reset(BEConsumer->takeModule());
 }
@@ -294,12 +317,36 @@
   if (BA != Backend_EmitNothing && !OS)
     return 0;
 
+  llvm::Module *LinkModuleToUse = LinkModule;
+
+  // If we were not given a link module, and the user requested that one be
+  // loaded from bitcode, do so now.
+  const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile;
+  if (!LinkModuleToUse && !LinkBCFile.empty()) {
+    std::string ErrorStr;
+
+    llvm::MemoryBuffer *BCBuf =
+      CI.getFileManager().getBufferForFile(LinkBCFile, &ErrorStr);
+    if (!BCBuf) {
+      CI.getDiagnostics().Report(diag::err_cannot_open_file)
+        << LinkBCFile << ErrorStr;
+      return 0;
+    }
+
+    LinkModuleToUse = getLazyBitcodeModule(BCBuf, *VMContext, &ErrorStr);
+    if (!LinkModuleToUse) {
+      CI.getDiagnostics().Report(diag::err_cannot_open_file)
+        << LinkBCFile << ErrorStr;
+      return 0;
+    }
+  }
+
   BEConsumer = 
       new BackendConsumer(BA, CI.getDiagnostics(),
                           CI.getCodeGenOpts(), CI.getTargetOpts(),
                           CI.getLangOpts(),
-                          CI.getFrontendOpts().ShowTimers, InFile, OS.take(),
-                          *VMContext);
+                          CI.getFrontendOpts().ShowTimers, InFile,
+                          LinkModuleToUse, OS.take(), *VMContext);
   return BEConsumer;
 }