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 M = + getLazyIRFileModule(IRFileName, Err, *Context); + if (!M) + CI.getDiagnostics().Report(diag::err_cannot_open_file) + << IRFileName << Err.getMessage(); + return M.release(); +} + std::unique_ptr CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { BackendAction BA = static_cast(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 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 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 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