Change __rust_no_alloc_shim_is_unstable to be a function by dpaoliello · Pull Request #141061 · rust-lang/rust (original) (raw)

This fixes a long sequence of issues:

  1. A customer reported that building for Arm64EC was broken: Linking error when compiled to arm64ec-pc-windows-msvc #138541
  2. This was caused by a bug in my original implementation of Arm64EC support, namely that only functions on Arm64EC need to be decorated with # but Rust was decorating statics as well.
  3. Once I corrected Rust to only decorate functions, I started linking failures where the linker couldn't find statics exported by dylib dependencies. This was caused by the compiler not marking exported statics in the generated DEF file with DATA, thus they were being exported as functions not data.
  4. Once I corrected the way that the DEF files were being emitted, the linker started failing saying that it couldn't find __rust_no_alloc_shim_is_unstable. This is because the MSVC linker requires the declarations of statics imported from other dylibs to be marked with dllimport (whereas it will happily link to functions imported from other dylibs whether they are marked dllimport or not).
  5. I then made a change to ensure that __rust_no_alloc_shim_is_unstable was marked as dllimport, but the MSVC linker started emitting warnings that __rust_no_alloc_shim_is_unstable was marked as dllimport but was declared in an obj file. This is a harmless warning which is a performance hint: anything that's marked dllimport must be indirected via an __imp symbol so I added a linker arg in the target to suppress the warning.
  6. A customer then reported a similar warning when using lld-link (Fix linking statics on Arm64EC #140176 (comment)). I don't think it was an implementation difference between the two linkers but rather that, depending on the obj that the declaration versus uses of __rust_no_alloc_shim_is_unstable landed in we would get different warnings, so I suppressed that warning as well: [win] Ignore MSVC linker warning 4217 #140954.
  7. Another customer reported that they weren't using the Rust compiler to invoke the linker, thus these warnings were breaking their build: Fix linking statics on Arm64EC #140176 (comment). At that point, my original change was reverted (Revert "Fix linking statics on Arm64EC #140176" #141024) leaving Arm64EC broken yet again.

Taking a step back, a lot of these linker issues arise from the fact that __rust_no_alloc_shim_is_unstable is marked as extern "Rust" in the standard library and, therefore, assumed to be a foreign item from a different crate BUT the Rust compiler may choose to generate it either in the current crate, some other crate that will be statically linked in OR some other crate that will by dynamically imported.

Worse yet, it is impossible while building a given crate to know if __rust_no_alloc_shim_is_unstable will statically linked or dynamically imported: it might be that one of its dependent crates is the one with an allocator kind set and thus that crate (which is compiled later) will decide depending if it has any dylib dependencies or not to import __rust_no_alloc_shim_is_unstable or generate it. Thus, there is no way to know if the declaration of __rust_no_alloc_shim_is_unstable should be marked with dllimport or not.

There is a simple fix for all this: there is no reason __rust_no_alloc_shim_is_unstable must be a static. It needs to be some symbol that must be linked in; thus, it could easily be a function instead. As a function, there is no need to mark it as dllimport when dynamically imported which avoids the entire mess above.

There may be a perf hit for changing the volatile load to be a tail call, so I'm happy to change that part back (although I question what the codegen of a volatile load would look like, and if the backend is going to try to use load-acquire semantics).

Build with this change applied BEFORE #140176 was reverted to demonstrate that there are no linking issues with either MSVC or MinGW: https://github.com/rust-lang/rust/actions/runs/15078657205

Incidentally, I fixed tests/run-make/no-alloc-shim to work with MSVC as I needed it to be able to test locally (FYI for #128602)

r? @bjorn3
cc @jieyouxu