summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-05-09 00:43:28 +0000
committerbors <bors@rust-lang.org>2025-05-09 00:43:28 +0000
commitc8b7f32434c0306db5c1b974ee43443746098a92 (patch)
tree984e7d85ae78caddbd16e53670b7717d8bccf0df /compiler/rustc_codegen_llvm/src
parent667247db71ea18c4130dd018d060e7f09d589490 (diff)
parent6dabf7ea3a518a63d273a4d1bcd545ac7d29bd23 (diff)
downloadrust-c8b7f32434c0306db5c1b974ee43443746098a92.tar.gz
rust-c8b7f32434c0306db5c1b974ee43443746098a92.zip
Auto merge of #140176 - dpaoliello:arm64ecdec, r=wesleywiser
Fix linking statics on Arm64EC

Arm64EC builds recently started to fail due to the linker not finding a symbol:
```
symbols.o : error LNK2001: unresolved external symbol #_ZN3std9panicking11EMPTY_PANIC17hc8d2b903527827f1E (EC Symbol)
          C:\Code\hello-world\target\arm64ec-pc-windows-msvc\debug\deps\hello_world.exe : fatal error LNK1120: 1 unresolved externals
```

It turns out that `EMPTY_PANIC` is a new static variable that was being exported then imported from the standard library, but when exporting LLVM didn't prepend the name with `#` (as only functions are prefixed with this character), whereas Rust was prefixing with `#` when attempting to import it.

The fix is to have Rust not prefix statics with `#` when importing.

Adding tests discovered another issue: we need to correctly mark static exported from dylibs with `DATA`, otherwise MSVC's linker assumes they are functions and complains that there is no exit thunk for them.

CI found another bug: we only apply `DllImport` to non-local statics that aren't foreign items (i.e., in an `extern` block), that is we want to use `DllImport` for statics coming from other Rust crates. However, `__rust_no_alloc_shim_is_unstable` is a static generated by the Rust compiler if required, but downstream crates consider it a foreign item since it is declared in an `extern "Rust"` block, thus they do not apply `DllImport` to it and so fails to link if it is exported by the previous crate as `DATA`. The fix is to apply `DllImport` to foreign items that are marked with the `rustc_std_internal_symbol` attribute (i.e., we assume they aren't actually foreign and will be in some Rust crate).

Fixes #138541

---
try-job: dist-aarch64-msvc
try-job: dist-x86_64-msvc
try-job: x86_64-msvc-1
try-job: x86_64-msvc-2
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs7
1 files changed, 6 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index bf81eb648f8..cbac55c7153 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -364,7 +364,12 @@ impl<'ll> CodegenCx<'ll, '_> {
 
         if !def_id.is_local() {
             let needs_dll_storage_attr = self.use_dll_storage_attrs
-                && !self.tcx.is_foreign_item(def_id)
+                // If the symbol is a foreign item, then don't automatically apply DLLImport, as
+                // we'll rely on the #[link] attribute instead. BUT, if this is an internal symbol
+                // then it may be generated by the compiler in some crate, so we do need to apply
+                // DLLImport when linking with the MSVC linker.
+                && (!self.tcx.is_foreign_item(def_id)
+                    || (self.sess().target.is_like_msvc && fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)))
                 // Local definitions can never be imported, so we must not apply
                 // the DLLImport annotation.
                 && !dso_local