Rust's asm story currently has some big limitations related to defining globals from asm blocks. Specifically, there are two limitations:
- You have to pick the symbol name yourself. You cannot ask the compiler to pick a name using e.g. name mangling.
- Symbols have to be marked global because otherwise they cannot cross CGU boundaries.
The second problem is quite problematic. Let's say you tried to define a symbol like this:
extern "C" {
static MY_GLOBAL_U64: u64;
}
global_asm!(
"MY_GLOBAL_U64:",
".quad 17"
);
fn get_seventeen() -> u64 {
MY_GLOBAL_U64
}
Then if you compile with more than one CGU (code generation unit), then there's a chance that the global asm block and the get_seventeen() function end up in different CGUs. Since the symbol is only locally defined, this will lead to a linker error because get_seventeen() cannot find the MY_GLOBAL_U64 symbol.
Because of the above two issues, I propose adding the ability to place a defines {} block when using assembly in Rust.
global_asm!(
"{MY_GLOBAL_U64}:",
".quad 17",
defines {
static MY_GLOBAL_U64: u64;
}
);
fn get_seventeen() -> u64 {
MY_GLOBAL_U64
}
The behavior of the above code is like so:
- Because the
definesblock mentions aMY_GLOBAL_U64of typeu64, we can now writeMY_GLOBAL_U64to access said symbol. - Since the
staticis not marked#[no_mangle], the name is chosen using the usual name mangling rules. Exactly the same as if you had declared a normal static in the same location as the asm block. - Inside the asm block, you may use
{MY_GLOBAL_U64}to get the actual symbol name chosen for the static. - Since Rust knows that
MY_GLOBAL_U64is defined by thatglobal_asm!block, Rust can insert the appropriate exports from the CGUs to ensure that even ifget_seventeen()ends up in a different CGU, it will still work correctly.
A few other notes:
- You can place both statics and functions inside of
defines {}to allow defining either kind of symbol. - I also think it makes sense to allow
defines {}for inline asm blocks as well. In this case, we need to keep in mind that such blocks are duplicated by monomorphization and inlining, which means that such statics are not unique, and symbol mangling must choose unique names for each duplicate static.