-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Change __rust_no_alloc_shim_is_unstable to be a function #141061
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Do you have a link to the problems you are having? |
Yes, sorry, I was intending to add a full write-up to the description once I had done the PR builds to validate that this works with both MinGW and MSVC. I've updated the description now. |
YAML changes were for testing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we handle regular #[no_mangle]
statics that doesn't cause those linker warnings/errors?
library/alloc/src/alloc.rs
Outdated
#[rustc_nounwind] | ||
#[rustc_std_internal_symbol] | ||
#[cfg(not(bootstrap))] | ||
fn __rust_no_alloc_shim_is_unstable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the very least this symbol name will need to be changed to prevent UB when someone uses the old definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll rename it.
library/alloc/src/alloc.rs
Outdated
core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); | ||
#[cfg(not(bootstrap))] | ||
__rust_no_alloc_shim_is_unstable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would read_volatile(__rust_no_alloc_shim_is_unstable.addr().cast::<u8>())
(using the unstable FnPtr::addr
method) work? Or maybe one of OpenBSD's exploit mitigations would break with that. Do we even care about that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would work for most platforms.
I'm not sure about OpenBSD, but it would certainly cause issues in Xbox kernel-mode, as it loads binaries as Execute-Only (i.e., they are not readable).
Again, I suspect that the volatile read is more expensive than a tail call to empty function as it may generate load-acquire semantics.
I'm not sure if we could get away with just getting the address of the function and not reading from it? Backends might optimize that away though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe black_box(__rust_no_alloc_shim_is_unstable as fn())
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would read_volatile(__rust_no_alloc_shim_is_unstable.addr().cast::()) (using the unstable FnPtr::addr method) work?
Miri would definitely complain about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
black_box(__rust_no_alloc_shim_is_unstable as fn())
?
Doesn't work: we get the correct behavior where it is required for linking to work, but then the codegen tests fail as the compiler is not able to optimize away allocations.
if output.is_some() { | ||
block.end_with_return(None, ret); | ||
} else { | ||
block.end_with_void_return(None); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a fix for that done in the repo of cg_gcc, but since you change the same code anyway, I guess it would be better to have the fix here as well to make sure I don't forget it when fixing the merge conflict.
block.end_with_void_return(None); | |
block.add_eval(None, ret); | |
block.end_with_void_return(None); |
If the static is exported by one crate and referenced by another, then the compiler knows whether that static will be statically linked or dynamically imported since it can see the dependency chain between the current crate using the static and the declaring crate. If the static is referenced via an |
The Miri subtree was changed cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
If the static is defined inside an rlib, and we are currently compiling an rlib, rustc can't know if the static will be statically linked or dynamically imported. Only when we are linking the current rlib into something do we know if the other rlib was statically linked or dynamically linked. |
The warning is only emitted if something marked with |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The |
This fixes a long sequence of issues:
arm64ec-pc-windows-msvc
#138541#
but Rust was decorating statics as well.DATA
, thus they were being exported as functions not data.__rust_no_alloc_shim_is_unstable
. This is because the MSVC linker requires the declarations of statics imported from other dylibs to be marked withdllimport
(whereas it will happily link to functions imported from other dylibs whether they are markeddllimport
or not).__rust_no_alloc_shim_is_unstable
was marked asdllimport
, but the MSVC linker started emitting warnings that__rust_no_alloc_shim_is_unstable
was marked asdllimport
but was declared in an obj file. This is a harmless warning which is a performance hint: anything that's markeddllimport
must be indirected via an__imp
symbol so I added a linker arg in the target to suppress the warning.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.Taking a step back, a lot of these linker issues arise from the fact that
__rust_no_alloc_shim_is_unstable
is marked asextern "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 withdllimport
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 asdllimport
when dynamically imported which avoids the entire mess above.There may be a perf hit for changing the
volatile load
to be atail call
, so I'm happy to change that part back (although I question what the codegen of avolatile 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