-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Description
I’m working on a pure Rust Wii/GameCube bare metal runtime, and in order to get the Dolphin emulator to output debug information to stdout
I need to have a function named a certain way which gets replaced at runtime with code from outside the sandbox.
In order to do so, #[inline(never)]
seemed the perfect match, but I couldn’t get it to actually force the function to never be inlined, which kind of defeats its purpose.
I found a workaround in having an empty asm!()
call, which also needs to receive the registers, otherwise rustc
won’t even emit the code putting the correct values for the arguments before the call. This has the downside of allocating and deallocating 16 bytes on the stack, I’m really not sure why as the assembly doesn’t actually do anything.
I tried this code:
#![feature(asm)]
#[no_mangle]
#[inline(never)]
unsafe extern "C" fn do_foo(arg: u32) {
// Comment out this line and this function becomes a noop, and never gets
// called.
asm!("/* {0} */", in(reg) arg);
}
fn main() {
unsafe { do_foo(4) };
unsafe { do_foo(12) };
}
I expected to see this happen: codegen should be exactly the same with and without the asm!()
call on line 8, due to the #[inline(never)]
which requests do_foo()
calls to stay as calls and not be inlined.
Instead, this happened: when line 8 is commented out, rustc
detects do_foo
is a noop and inlines it in main
as such, which then contains a single blr
instruction (equivalent of ret
on x86). This renders #[inline(never)]
useless.
Meta
rustc --version --verbose
:
rustc 1.58.0-nightly (65f3f8b22 2021-11-21)
binary: rustc
commit-hash: 65f3f8b220f020e562c5dd848ff7319257a7ba45
commit-date: 2021-11-21
host: x86_64-unknown-linux-gnu
release: 1.58.0-nightly
LLVM version: 13.0.0
I’m building for PowerPC, but this bug also reproduces on x86.