Mismatched ABI for f128 comparison builtins on wasm64-unknown-unknown
On `wasm64-unknown-unknown`, there seems to be an ABI mismatch for `f128` comparison builtins such as `__gttf2`, `__lttf2`, `__eqtf2`, etc.
`compiler-builtins` defines these builtins with `CmpResult = isize`, which becomes `i64` on `wasm64`. However, LLVM appears to lower `f128` comparisons (`>`, `<`, `==`, etc.) to runtime libcalls that expect an `i32` return value.
As a result, the produced contain inconsistent signatures for the same symbols, make it broken. I think this is actually an LLVM issue (I’ll make an issue with LLVM soon), but I am wondering whether `compiler-builtins` could special-case wasm64 here as a practical workaround.
Emscripten appears to special-case this behavior here: https://github.com/emscripten-core/emscripten/blob/88e0002141254cdb772b558f63d2c1ad9b215eb2/system/lib/compiler-rt/lib/builtins/fp_compare_impl.inc#L15
GCC's cmp_result is i32, there is also related LLVM issue here: https://github.com/llvm/llvm-project/issues/75302
If such a workaround is acceptable, I can make a PR.
Reproduce:
```rust
#![feature(f128)]
#[unsafe(no_mangle)]
pub fn issue(a: f128, b: f128) -> bool {
a > b
}
```
```
cargo +nightly build --target wasm64-unknown-unknown -Zbuild-std=panic_abort,std --release
warning: linker stderr: rust-lld: function signature mismatch: __gttf2
>>> defined as (i64, i64, i64, i64) -> i32 in /home/uharsn/repo/playground/target/wasm64-unknown-unknown/debug/deps/playground.27e5bot53bshdzky4drqb5i4f.0fmq2dj.rcgu.o
>>> defined as (i64, i64, i64, i64) -> i64 in /home/uharsn/repo/playground/target/wasm64-unknown-unknown/debug/deps/libcompiler_builtins-1ab02c0bce5b5843.rlib(compiler_builtins-1ab02c0bce
5b5843.compiler_builtins.76b268114ccd8a12-cgu.02.rcgu.o)
llvm-nm target/wasm64-unknown-unknown/release/playground.wasm
00000027 D __stack_pointer
00000075 T issue
00000071 t signature_mismatch:__gttf2
wasm-tools print target/wasm64-unknown-unknown/release/playground.wasm
(func $signature_mismatch:__gttf2 (;0;) (type 0) (param i64 i64 i64 i64) (result i32)
unreachable
)
(func $issue (;1;) (type 0) (param i64 i64 i64 i64) (result i32)
local.get 0
local.get 1
local.get 2
local.get 3
call $signature_mismatch:__gttf2
i32.const 0
i32.gt_s
)
```
1 条评论