diff options
| author | bors <bors@rust-lang.org> | 2024-04-02 09:41:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-02 09:41:27 +0000 |
| commit | 0e682e9875458ebf811206a48b688e07d762d9bb (patch) | |
| tree | 6dc6c728a416545dfdccfb601ef951e35326ff75 /compiler | |
| parent | 2531d08e342f21f83eef90741c871f32ba7aa7d2 (diff) | |
| parent | 748dba2bafab14117f626348b716a824d301cffd (diff) | |
Auto merge of #123347 - saethlin:only-allow-upstream-llvm-calls, r=Nilstrieb
Only allow compiler_builtins to call LLVM intrinsics, not any link_name function
This is another case of accidental reliance on `inline(never)` like I rooted out in https://github.com/rust-lang/rust/pull/118770. Without this PR, attempting to build some large programs with `-Zcross-crate-inline-threshold=yes` with a sysroot also compiled with that flag will result in linker errors like this:
```
= note: /usr/bin/ld: /tmp/cargo-installNrfN4T/x86_64-unknown-linux-gnu/release/deps/libcompiler_builtins-d2a9b69f4e45b883.rlib(compiler_builtins-d2a9b69f4e45b883.compiler_builtins.dbbc6c2ca970faa4-cgu.0.rcgu.o): in function `core::panicking::panic_fmt':
/home/ben/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panicking.rs:72:(.text.unlikely._ZN4core9panicking9panic_fmt17ha407cc99e97c942fE+0x31): undefined reference to `rust_begin_unwind'
```
With `-Zcross-crate-inline-threshold=yes` we can inline `panic_fmt` into `compiler_builtins`. Then we end up with a call to an upstream monomorphization, but one that has a `link_name` set. But unlike LLVM's magic intrinsic names, this link name is going to make it to the linker, and then we have a problem.
This logic looks scuffed, but also we're doing this in 4 other places. Don't know if that means it's good or bad.
https://github.com/rust-lang/rust/blob/1684a753dbca5d23b2e03568e6fbbb48eb72d0e6/compiler/rustc_codegen_cranelift/src/abi/mod.rs#L386
https://github.com/rust-lang/rust/blob/1684a753dbca5d23b2e03568e6fbbb48eb72d0e6/compiler/rustc_ast_passes/src/feature_gate.rs#L306
https://github.com/rust-lang/rust/blob/1684a753dbca5d23b2e03568e6fbbb48eb72d0e6/compiler/rustc_codegen_ssa/src/codegen_attrs.rs#L609
https://github.com/rust-lang/rust/blob/1684a753dbca5d23b2e03568e6fbbb48eb72d0e6/compiler/rustc_codegen_gcc/src/declare.rs#L170
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_monomorphize/src/lib.rs | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 9c4a6e69a3c..2a91d69529a 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::adjustment::CustomCoerceUnsized; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::{self, Ty}; +use rustc_span::def_id::DefId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::ErrorGuaranteed; @@ -57,13 +58,24 @@ fn custom_coerce_unsize_info<'tcx>( /// linkers will optimize such that dead calls to unresolved symbols are not an error, but this is /// not guaranteed. So we used this function in codegen backends to ensure we do not generate any /// unlinkable calls. +/// +/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker. pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, ) -> bool { - !instance.def_id().is_local() + fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + if let Some(name) = tcx.codegen_fn_attrs(def_id).link_name { + name.as_str().starts_with("llvm.") + } else { + false + } + } + + let def_id = instance.def_id(); + !def_id.is_local() && tcx.is_compiler_builtins(LOCAL_CRATE) - && tcx.codegen_fn_attrs(instance.def_id()).link_name.is_none() + && !is_llvm_intrinsic(tcx, def_id) && !should_codegen_locally(tcx, instance) } |
