Skip to content

Mismatched ABI for f128 comparison builtins on wasm64-unknown-unknown #1199

@Spxg

Description

@Spxg

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: llvm/llvm-project#75302

If such a workaround is acceptable, I can make a PR.

Reproduce:

#![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
  )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions