Hi echristo, dblaikie, rnk,

- Added -mlink-init-bitcode-file option to pre-populate new module with IR 
loaded from specified file.
- Accept IR assembly as well as bitcode.
- Added test case.

The change is needed for upcoming CUDA-related changes that require linking 
with large device-specific library provided as bitcode. Initializing module 
with the library IR is faster than linking the library in after compilation. It 
also allows convenient way to run some cuda-specific passes on the library IR 
(NVVM reflect and Internalize) alone without affecting IR we generate during 
compilation.

http://reviews.llvm.org/D9721

Files:
  include/clang/CodeGen/ModuleBuilder.h
  include/clang/Driver/CC1Options.td
  include/clang/Frontend/CodeGenOptions.h
  lib/CodeGen/CodeGenAction.cpp
  lib/CodeGen/ModuleBuilder.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/link-bitcode-file.c

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/CodeGen/ModuleBuilder.h
===================================================================
--- include/clang/CodeGen/ModuleBuilder.h
+++ include/clang/CodeGen/ModuleBuilder.h
@@ -44,6 +44,7 @@
                                    const std::string &ModuleName,
                                    const CodeGenOptions &CGO,
                                    llvm::LLVMContext& C,
+                                   llvm::Module *InitModule = nullptr,
                                    CoverageSourceInfo *CoverageInfo = nullptr);
 }
 
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -233,6 +233,8 @@
   HelpText<"Emit complete constructors and destructors as aliases when possible">;
 def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
   HelpText<"Link the given bitcode file before performing optimizations.">;
+def mlink_init_bitcode_file : Separate<["-"], "mlink-init-bitcode-file">,
+  HelpText<"Link given bitcode file before code generation.">;
 def vectorize_loops : Flag<["-"], "vectorize-loops">,
   HelpText<"Run the Loop vectorization passes">;
 def vectorize_slp : Flag<["-"], "vectorize-slp">,
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -128,6 +128,8 @@
 
   /// The name of the bitcode file to link before optzns.
   std::string LinkBitcodeFile;
+  /// The name of bitcode file to load on module init.
+  std::string LinkInitBitcodeFile;
 
   /// The user provided name for the "main file", if non-empty. This is useful
   /// in situations where the input file name does not match the original input
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -26,6 +26,7 @@
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IRReader/IRReader.h"
@@ -61,12 +62,13 @@
                     const TargetOptions &targetopts,
                     const LangOptions &langopts, bool TimePasses,
                     const std::string &infile, llvm::Module *LinkModule,
-                    raw_pwrite_stream *OS, LLVMContext &C,
-                    CoverageSourceInfo *CoverageInfo = nullptr)
+                    llvm::Module *InitModule, raw_pwrite_stream *OS,
+                    LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr)
         : Diags(_Diags), Action(action), CodeGenOpts(compopts),
           TargetOpts(targetopts), LangOpts(langopts), AsmOutStream(OS),
           Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"),
-          Gen(CreateLLVMCodeGen(Diags, infile, compopts, C, CoverageInfo)),
+          Gen(CreateLLVMCodeGen(Diags, infile, compopts, C, InitModule,
+                                CoverageInfo)),
           LinkModule(LinkModule) {
       llvm::TimePassesIsEnabled = TimePasses;
     }
@@ -629,6 +631,18 @@
   llvm_unreachable("Invalid action!");
 }
 
+static llvm::Module *loadIRFromFile(CompilerInstance &CI,
+                                    llvm::LLVMContext *Context,
+                                    const std::string &IRFileName) {
+    SMDiagnostic Err;
+    std::unique_ptr<llvm::Module> M =
+        getLazyIRFileModule(IRFileName, Err, *Context);
+    if (!M)
+      CI.getDiagnostics().Report(diag::err_cannot_open_file)
+          << IRFileName << Err.getMessage();
+    return M.release();
+}
+
 std::unique_ptr<ASTConsumer>
 CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
   BackendAction BA = static_cast<BackendAction>(Act);
@@ -642,21 +656,17 @@
   // loaded from bitcode, do so now.
   const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile;
   if (!LinkModuleToUse && !LinkBCFile.empty()) {
-    auto BCBuf = CI.getFileManager().getBufferForFile(LinkBCFile);
-    if (!BCBuf) {
-      CI.getDiagnostics().Report(diag::err_cannot_open_file)
-          << LinkBCFile << BCBuf.getError().message();
+    LinkModuleToUse = loadIRFromFile(CI, VMContext, LinkBCFile);
+    if (!LinkModuleToUse)
       return nullptr;
-    }
+  }
 
-    ErrorOr<llvm::Module *> ModuleOrErr =
-        getLazyBitcodeModule(std::move(*BCBuf), *VMContext);
-    if (std::error_code EC = ModuleOrErr.getError()) {
-      CI.getDiagnostics().Report(diag::err_cannot_open_file)
-        << LinkBCFile << EC.message();
+  llvm::Module *LinkInitModuleToUse = nullptr;
+  const std::string &LinkInitBCFile = CI.getCodeGenOpts().LinkInitBitcodeFile;
+  if (!LinkInitBCFile.empty()) {
+    LinkInitModuleToUse = loadIRFromFile(CI, VMContext, LinkInitBCFile);
+    if (!LinkInitModuleToUse)
       return nullptr;
-    }
-    LinkModuleToUse = ModuleOrErr.get();
   }
 
   CoverageSourceInfo *CoverageInfo = nullptr;
@@ -669,7 +679,7 @@
   std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
       BA, CI.getDiagnostics(), CI.getCodeGenOpts(), CI.getTargetOpts(),
       CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile,
-      LinkModuleToUse, OS, *VMContext, CoverageInfo));
+      LinkModuleToUse, LinkInitModuleToUse, OS, *VMContext, CoverageInfo));
   BEConsumer = Result.get();
   return std::move(Result);
 }
Index: lib/CodeGen/ModuleBuilder.cpp
===================================================================
--- lib/CodeGen/ModuleBuilder.cpp
+++ lib/CodeGen/ModuleBuilder.cpp
@@ -56,12 +56,13 @@
     SmallVector<CXXMethodDecl *, 8> DeferredInlineMethodDefinitions;
 
   public:
-    CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName,
-                      const CodeGenOptions &CGO, llvm::LLVMContext& C,
+    CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string &ModuleName,
+                      const CodeGenOptions &CGO, llvm::LLVMContext &C,
+                      llvm::Module *InitModule,
                       CoverageSourceInfo *CoverageInfo = nullptr)
-      : Diags(diags), Ctx(nullptr), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
-        CoverageInfo(CoverageInfo),
-        M(new llvm::Module(ModuleName, C)) {}
+        : Diags(diags), Ctx(nullptr), CodeGenOpts(CGO),
+          HandlingTopLevelDecls(0), CoverageInfo(CoverageInfo),
+          M(InitModule ? InitModule : new llvm::Module(ModuleName, C)) {}
 
     ~CodeGeneratorImpl() override {
       // There should normally not be any leftover inline method definitions.
@@ -237,9 +238,11 @@
 void CodeGenerator::anchor() { }
 
 CodeGenerator *clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags,
-                                        const std::string& ModuleName,
+                                        const std::string &ModuleName,
                                         const CodeGenOptions &CGO,
-                                        llvm::LLVMContext& C,
+                                        llvm::LLVMContext &C,
+                                        llvm::Module *InitModule,
                                         CoverageSourceInfo *CoverageInfo) {
-  return new CodeGeneratorImpl(Diags, ModuleName, CGO, C, CoverageInfo);
+  return new CodeGeneratorImpl(Diags, ModuleName, CGO, C, InitModule,
+                               CoverageInfo);
 }
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -526,6 +526,7 @@
   Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
   Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
   Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
+  Opts.LinkInitBitcodeFile = Args.getLastArgValue(OPT_mlink_init_bitcode_file);
   Opts.SanitizeCoverageType =
       getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags);
   Opts.SanitizeCoverageIndirectCalls =
Index: test/CodeGen/link-bitcode-file.c
===================================================================
--- test/CodeGen/link-bitcode-file.c
+++ test/CodeGen/link-bitcode-file.c
@@ -1,28 +1,38 @@
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -DBITCODE -emit-llvm-bc -o %t.bc %s
-// RUN: %clang_cc1 -triple i386-pc-linux-gnu -mlink-bitcode-file %t.bc -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NO-BC %s
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -mlink-bitcode-file %t.bc -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-F-BC -check-prefix=CHECK-G %s
 // RUN: not %clang_cc1 -triple i386-pc-linux-gnu -DBITCODE -mlink-bitcode-file %t.bc -O3 -emit-llvm -o - %s 2>&1 | FileCheck -check-prefix=CHECK-BC %s
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -mlink-init-bitcode-file %t.bc -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-F-IBC -check-prefix=CHECK-G %s
+// RUN: not %clang_cc1 -triple i386-pc-linux-gnu -DBITCODE -mlink-init-bitcode-file %t.bc -O3 -emit-llvm -o - %s 2>&1 | FileCheck -check-prefix=CHECK-IBC %s
 // Make sure we deal with failure to load the file.
 // RUN: not %clang_cc1 -triple i386-pc-linux-gnu -mlink-bitcode-file no-such-file.bc \
 // RUN:    -emit-llvm -o - %s 2>&1 | FileCheck -check-prefix=CHECK-NO-FILE %s
+// RUN: not %clang_cc1 -triple i386-pc-linux-gnu -mlink-init-bitcode-file no-such-file.bc \
+// RUN:    -emit-llvm -o - %s 2>&1 | FileCheck -check-prefix=CHECK-NO-FILE %s
 
 int f(void);
 
 #ifdef BITCODE
 
+// Check for symbol conflicts between the file and loaded bitcode.
 // CHECK-BC: fatal error: cannot link module {{.*}}'f': symbol multiply defined
+// CHECK-IBC: error: definition with same mangled name as another definition
 int f(void) {
   return 42;
 }
 
 #else
 
-// CHECK-NO-BC-LABEL: define i32 @g
-// CHECK-NO-BC: ret i32 42
+// Init bitcode gets loaded first.
+// CHECK-F-IBC-LABEL: define i32 @f
+
+// CHECK-G-LABEL: define i32 @g
+// CHECK-G: ret i32 42
 int g(void) {
   return f();
 }
 
-// CHECK-NO-BC-LABEL: define i32 @f
+// regular bitcode gets linked in at the end.
+// CHECK-F-BC-LABEL: define i32 @f
 
 #endif
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to