diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index e22dd8373bd..e3d11cfaf4f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2164,8 +2164,14 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { && tcx.sess.opts.cg.prefer_dynamic) ); + // We need to generate _imp__ symbol if we are generating an rlib or we include one + // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve + // these, but it currently does not do so. + let can_have_static_objects = + tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib); + tcx.sess.target.is_like_windows && - tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib) && + can_have_static_objects && // ThinLTO can't handle this workaround in all cases, so we don't // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin LTO is enabled. diff --git a/tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs b/tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs new file mode 100644 index 00000000000..afb0dc42f44 --- /dev/null +++ b/tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs @@ -0,0 +1,13 @@ +use std::sync::atomic::{AtomicPtr, Ordering}; + +#[inline(always)] +pub fn memrchr() { + fn detect() {} + + static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ()); + + unsafe { + let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst); + std::mem::transmute::<*mut (), fn()>(fun)() + } +} diff --git a/tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs b/tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs new file mode 100644 index 00000000000..2d2d2e68125 --- /dev/null +++ b/tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs @@ -0,0 +1,5 @@ +extern crate issue_81408; + +fn main() { + issue_81408::memrchr(); +} diff --git a/tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs b/tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs new file mode 100644 index 00000000000..3db1ae3452d --- /dev/null +++ b/tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs @@ -0,0 +1,33 @@ +// This is a non-regression test for issue #81408 involving an lld bug and ThinLTO, on windows. +// MSVC's link.exe doesn't need any workarounds in rustc, but lld does, so we'll check that the +// binary runs successfully instead of using a codegen test. + +//@ only-x86_64-pc-windows-msvc +//@ needs-rust-lld +//@ ignore-cross-compile: the built binary is executed + +use run_make_support::{run, rustc}; + +fn test_with_linker(linker: &str) { + rustc().input("issue_81408.rs").crate_name("issue_81408").crate_type("lib").opt().run(); + rustc() + .input("main.rs") + .crate_type("bin") + .arg("-Clto=thin") + .opt() + .arg(&format!("-Clinker={linker}")) + .extern_("issue_81408", "libissue_81408.rlib") + .run(); + + // To make possible failures clearer, print an intro that will only be shown if the test does + // fail when running the binary. + eprint!("Running binary linked with {linker}... "); + run("main"); + eprintln!("ok"); +} + +fn main() { + // We want the reproducer to work when linked with both linkers. + test_with_linker("link"); + test_with_linker("rust-lld"); +}