From 724c91234dd49b88d70ebead406d09105695c3e5 Mon Sep 17 00:00:00 2001 From: Ziv Dunkelman Date: Wed, 8 Jun 2022 17:30:16 +0300 Subject: [PATCH] rustc: add ability to output regular LTO bitcode modules Adding the option to control from rustc CLI if the resulted ".o" bitcode module files are with thinLTO info or regular LTO info. Allows using "-lto-embed-bitcode=optimized" during linkage correctly. Signed-off-by: Ziv Dunkelman --- compiler/rustc_codegen_llvm/src/back/lto.rs | 6 +++--- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 2 ++ compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 9 +++++++-- compiler/rustc_session/src/options.rs | 2 ++ .../issue-84395-lto-embed-bitcode/Makefile | 11 +++++++++++ .../issue-84395-lto-embed-bitcode/test.rs | 3 +++ src/test/rustdoc-ui/z-help.stdout | 1 + 10 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile create mode 100644 src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 38402e0431379..9f793a4ef63d4 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -199,7 +199,7 @@ pub(crate) fn run_thin( pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBuffer) { let name = module.name.clone(); - let buffer = ThinBuffer::new(module.module_llvm.llmod()); + let buffer = ThinBuffer::new(module.module_llvm.llmod(), true); (name, buffer) } @@ -709,9 +709,9 @@ unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - pub fn new(m: &llvm::Module) -> ThinBuffer { + pub fn new(m: &llvm::Module, is_thin: bool) -> ThinBuffer { unsafe { - let buffer = llvm::LLVMRustThinLTOBufferCreate(m); + let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin); ThinBuffer(buffer) } } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 2b465ce40e7d4..534d32e8a90e9 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -790,7 +790,7 @@ pub(crate) unsafe fn codegen( let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name); - let thin = ThinBuffer::new(llmod); + let thin = ThinBuffer::new(llmod, config.emit_thin_lto); let data = thin.data(); if let Some(bitcode_filename) = bc_out.file_name() { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 5ebc2d6139fc8..1928d47df74ef 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2469,7 +2469,7 @@ extern "C" { pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer); pub fn LLVMRustModuleCost(M: &Module) -> u64; - pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> &'static mut ThinLTOBuffer; + pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer; pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer); pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char; pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c2ac21eec6723..ea60f6055f3d5 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -99,6 +99,7 @@ pub struct ModuleConfig { pub emit_ir: bool, pub emit_asm: bool, pub emit_obj: EmitObj, + pub emit_thin_lto: bool, pub bc_cmdline: String, // Miscellaneous flags. These are mostly copied from command-line @@ -218,6 +219,7 @@ impl ModuleConfig { false ), emit_obj, + emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto, bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(), verify_llvm_ir: sess.verify_llvm_ir(), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 9c0b534798e39..9cbbc603cd01e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -734,6 +734,7 @@ fn test_unstable_options_tracking_hash() { tracked!(drop_tracking, true); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); + tracked!(emit_thin_lto, false); tracked!(fewer_names, Some(true)); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 0f4973ebf7129..3aac4d83716cd 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -34,6 +34,7 @@ #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" +#include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/Transforms/Instrumentation.h" @@ -1638,13 +1639,17 @@ struct LLVMRustThinLTOBuffer { }; extern "C" LLVMRustThinLTOBuffer* -LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { +LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { auto Ret = std::make_unique(); { raw_string_ostream OS(Ret->data); { legacy::PassManager PM; - PM.add(createWriteThinLTOBitcodePass(OS)); + if (is_thin) { + PM.add(createWriteThinLTOBitcodePass(OS)); + } else { + PM.add(createBitcodeWriterPass(OS)); + } PM.run(*unwrap(M)); } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 01ff9e254f792..77c74a3022075 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1277,6 +1277,8 @@ options! { "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), + emit_thin_lto: bool = (true, parse_bool, [TRACKED], + "emit the bc module with thin LTO info (default: yes)"), fewer_names: Option = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), diff --git a/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile new file mode 100644 index 0000000000000..157edb20c30a5 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/Makefile @@ -0,0 +1,11 @@ +# needs-matching-clang + +# This test makes sure the embed bitcode in elf created with +# lto-embed-bitcode=optimized is valid llvm BC module. + +-include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) test.rs --target $(TARGET) -Clink-arg=-fuse-ld=lld -Clinker-plugin-lto -Clinker=$(CLANG) -Clink-arg=-Wl,--plugin-opt=-lto-embed-bitcode=optimized -Zemit-thin-lto=no + $(LLVM_BIN_DIR)/objcopy --dump-section .llvmbc=$(TMPDIR)/test.bc $(TMPDIR)/test + $(LLVM_BIN_DIR)/llvm-dis $(TMPDIR)/test.bc diff --git a/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs new file mode 100644 index 0000000000000..47ad8c634112b --- /dev/null +++ b/src/test/run-make-fulldeps/issue-84395-lto-embed-bitcode/test.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 7296b35788a9d..54c4de0e03187 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -35,6 +35,7 @@ -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform) -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) + -Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes) -Z fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no) -Z force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no) -Z fuel=val -- set the optimization fuel quota for a crate