Closed
Description
#![feature(asm_sym)]
use std::arch::global_asm;
#[no_mangle]
fn my_func() {}
global_asm!("call_foobar: jmp {}", sym foobar);
fn foobar() {}
fn main() {
extern "Rust" {
fn call_foobar();
}
unsafe { call_foobar() };
}
This code will fail to link because foobar
is merged into my_func
.
Since global asms in LLVM can't reference symbols natively, we currently will add the mangled name to the string and pass it to LLVM. To prevent the file being optimized away, we add it to llvm.compiler.used
.
A few issues exist:
rustc_monomorphize
does not handle these functions specially, and thereforefoobar
above is considered as internal function and haveinternal
attribute attached.- LLVM believes that it is allowed to merge internal functions into an exported function despite present in
llvm.compiler.used
. I think LLVM should be allowed to this because we emit the internal linkage, and from my understanding renaming a local symbol should probably be allowed. @tmiasko argues otherwise and says thatllvm.compiler.used
shouldn't touch the symbol. - The symbols are added
llvm.compiler.used
, but it wouldn't show up as used in the exported symbol list, so it can still be stripped while doing LTO.
We should do the following:
- Ensure that these functions are not emitted with internal linkage
- Ensrue that the functions used will be marked as used in
exported_symbols/linked_symbols
and thus reach the linker/LTO. - Ask LLVM to clarify the behaviour of combining
llvm.compiler.used
+internal
.
cc @Amanieu @tmiasko
@rustbot label: +A-inline-assembly +F-asm
This will block #93333