-
Notifications
You must be signed in to change notification settings - Fork 248
Description
The problem
Some symbols, like the __aeabi_* ones, are defined as "aliases" of others in the C implementation of compiler-rt. For example: __aeabi_dadd is an alias of __adddf3. This means that both symbols, the original and its alias, refer to the same routine and use of either will result in a call to the same routine.
Rust doesn't have a mechanism for aliasing symbols and right now we are "emulating" aliases like this:
#[no_mangle]
pub extern fn __aeabi_dadd(a: f64, b: f64) -> f64 {
__adddf3(a, b)
}Although this works (calling that "alias" does the right thing), it also incurrs in an extra function call everytime the alias is used:
00000a8c <__aeabi_dadd>:
a8c: ea00001a b afc <__adddf3>
Attempted solutions
Use #[link_args] to ask the linker to duplicate the symbol. See #39. Sadly, this didn't work because #[link_args] is not propagated through crates and also that feature is slated for removal so we can't rely on it anyway.
Possible non-ideal solutions
export_name
Most (all?) ARM builtins have the form __aeabi_*. compiler-rt implements them as aliases to the non-aeabi symbols. For example: __aeabi_dadd is an alias of __adddf3 and both symbols appear in libcompiler-rt.a. Given that ARM executables never use the non-aeabi symbols, we could simply expose the __adddf3 routine as the __aeabi_dadd symbol without providing the __adddf3 symbol. In Rust code this would look like this:
#[cfg_attr(target = "arm", export_name = "__aeabi_dadd")]
#[cfg_attr(not(target = "arm"), no_mangle)]
pub extern fn __adddf3(a: f64, b: f64) -> f64 { ... }The result would be:
rustc_builtinson x86 exposes the__adddf3symbolrustc_builtinson ARM exposes the__aeabi_daddsymbol
In contrast, libcompiler-rt.a on ARM exposes both the __adddf3 and the __aeabi_dadd symbols
This approach can only be used if the implementation resides in rustc-builtins. For instance, we can't use this to expose the __aeabi_memcpy* symbols which are all aliases to memcpy.
Just duplicate the routine
#[no_mangle]
pub extern fn __adddf3(a: f64, b: f64) -> f64 { impl!() }
#[no_mangle]
pub extern fn __aeabi_dadd(a: f64, b: f64) -> f64 { impl!() }This would get rid of the extra function call in the "alias" but would probably result in duplicate code/instructions in the final executable (unless LLVM is smart enough to deduplicate two routines that have the same instructions)
Anyone has any other idea about how to solve this?