Skip to content

Commit 74f600b

Browse files
committed
Auto merge of #98162 - nextsilicon:support_lto_embed_bitcode, r=davidtwco
Allow to disable thinLTO buffer to support lto-embed-bitcode lld feature Hello This change is to fix issue (#84395) in which passing "-lto-embed-bitcode=optimized" to lld when linking rust code via linker-plugin-lto doesn't produce the expected result. Instead of emitting a single unified module into a llvmbc section of the linked elf, it emits multiple submodules. This is caused because rustc emits the BC modules after running llvm `createWriteThinLTOBitcodePass` pass. Which in turn triggers a thinLTO linkage and causes the said issue. This patch allows via compiler flag (-Cemit-thin-lto=<bool>) to select between running `createWriteThinLTOBitcodePass` and `createBitcodeWriterPass`. Note this pattern of selecting between those 2 passes is common inside of LLVM code. The default is to match the old behavior.
2 parents ceeb5ad + 724c912 commit 74f600b

File tree

10 files changed

+32
-7
lines changed

10 files changed

+32
-7
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ pub(crate) fn run_thin(
199199

200200
pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
201201
let name = module.name.clone();
202-
let buffer = ThinBuffer::new(module.module_llvm.llmod());
202+
let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
203203
(name, buffer)
204204
}
205205

@@ -695,9 +695,9 @@ unsafe impl Send for ThinBuffer {}
695695
unsafe impl Sync for ThinBuffer {}
696696

697697
impl ThinBuffer {
698-
pub fn new(m: &llvm::Module) -> ThinBuffer {
698+
pub fn new(m: &llvm::Module, is_thin: bool) -> ThinBuffer {
699699
unsafe {
700-
let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
700+
let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin);
701701
ThinBuffer(buffer)
702702
}
703703
}

compiler/rustc_codegen_llvm/src/back/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ pub(crate) unsafe fn codegen(
790790
let _timer = cgcx
791791
.prof
792792
.generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name);
793-
let thin = ThinBuffer::new(llmod);
793+
let thin = ThinBuffer::new(llmod, config.emit_thin_lto);
794794
let data = thin.data();
795795

796796
if let Some(bitcode_filename) = bc_out.file_name() {

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2470,7 +2470,7 @@ extern "C" {
24702470
pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
24712471
pub fn LLVMRustModuleCost(M: &Module) -> u64;
24722472

2473-
pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> &'static mut ThinLTOBuffer;
2473+
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
24742474
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
24752475
pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
24762476
pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;

compiler/rustc_codegen_ssa/src/back/write.rs

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub struct ModuleConfig {
9999
pub emit_ir: bool,
100100
pub emit_asm: bool,
101101
pub emit_obj: EmitObj,
102+
pub emit_thin_lto: bool,
102103
pub bc_cmdline: String,
103104

104105
// Miscellaneous flags. These are mostly copied from command-line
@@ -218,6 +219,7 @@ impl ModuleConfig {
218219
false
219220
),
220221
emit_obj,
222+
emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto,
221223
bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(),
222224

223225
verify_llvm_ir: sess.verify_llvm_ir(),

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ fn test_unstable_options_tracking_hash() {
735735
tracked!(drop_tracking, true);
736736
tracked!(dual_proc_macros, true);
737737
tracked!(dwarf_version, Some(5));
738+
tracked!(emit_thin_lto, false);
738739
tracked!(fewer_names, Some(true));
739740
tracked!(force_unstable_if_unmarked, true);
740741
tracked!(fuel, Some(("abc".to_string(), 99)));

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "llvm/Transforms/Utils/AddDiscriminators.h"
3535
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
3636
#include "llvm/LTO/LTO.h"
37+
#include "llvm/Bitcode/BitcodeWriterPass.h"
3738
#include "llvm-c/Transforms/PassManagerBuilder.h"
3839

3940
#include "llvm/Transforms/Instrumentation.h"
@@ -1638,13 +1639,17 @@ struct LLVMRustThinLTOBuffer {
16381639
};
16391640

16401641
extern "C" LLVMRustThinLTOBuffer*
1641-
LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
1642+
LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
16421643
auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
16431644
{
16441645
raw_string_ostream OS(Ret->data);
16451646
{
16461647
legacy::PassManager PM;
1647-
PM.add(createWriteThinLTOBitcodePass(OS));
1648+
if (is_thin) {
1649+
PM.add(createWriteThinLTOBitcodePass(OS));
1650+
} else {
1651+
PM.add(createBitcodeWriterPass(OS));
1652+
}
16481653
PM.run(*unwrap(M));
16491654
}
16501655
}

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,8 @@ options! {
12791279
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
12801280
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
12811281
"emit a section containing stack size metadata (default: no)"),
1282+
emit_thin_lto: bool = (true, parse_bool, [TRACKED],
1283+
"emit the bc module with thin LTO info (default: yes)"),
12821284
fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
12831285
"reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
12841286
(default: no)"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# needs-matching-clang
2+
3+
# This test makes sure the embed bitcode in elf created with
4+
# lto-embed-bitcode=optimized is valid llvm BC module.
5+
6+
-include ../../run-make-fulldeps/tools.mk
7+
8+
all:
9+
$(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
10+
$(LLVM_BIN_DIR)/objcopy --dump-section .llvmbc=$(TMPDIR)/test.bc $(TMPDIR)/test
11+
$(LLVM_BIN_DIR)/llvm-dis $(TMPDIR)/test.bc
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("Hello World!");
3+
}

src/test/rustdoc-ui/z-help.stdout

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
-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.
3737
-Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
3838
-Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
39+
-Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
3940
-Z fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
4041
-Z force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
4142
-Z fuel=val -- set the optimization fuel quota for a crate

0 commit comments

Comments
 (0)