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