Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clang generates mismatching wasm compiler-rt function signatures with -mmulti-value #59095

Closed
TerrorJack opened this issue Nov 20, 2022 · 10 comments
Assignees

Comments

@TerrorJack
Copy link

When -mmulti-value is added in wasi-sdk (the wasi-libc CFLAGS, and all CMAKE_C_FLAGS & CMAKE_CXX_FLAGS in the top-level makefile), clang generates mismatching wasm compiler-rt function signatures, as can be seen in the wasm-ld warning messages:

wasm-ld: warning: function signature mismatch: __udivti3
>>> defined as (i32, i64, i64, i64, i64) -> void in /home/gitpod/.ghc-wasm/wasi-sdk/lib/clang/15.0.5/lib/wasi/libclang_rt.builtins-wasm32.a(muloti4.c.obj)
>>> defined as (i64, i64, i64, i64) -> i64 in /home/gitpod/.ghc-wasm/wasi-sdk/lib/clang/15.0.5/lib/wasi/libclang_rt.builtins-wasm32.a(udivti3.c.obj)

wasm-ld: warning: function signature mismatch: __multi3
>>> defined as (i32, i64, i64, i64, i64) -> void in /home/gitpod/.ghc-wasm/wasi-sdk/bin/../share/wasi-sysroot/lib/wasm32-wasi/libc.a(intscan.o)
>>> defined as (i64, i64, i64, i64) -> i64 in /home/gitpod/.ghc-wasm/wasi-sdk/lib/clang/15.0.5/lib/wasi/libclang_rt.builtins-wasm32.a(multi3.c.obj)

wasm-ld: warning: function signature mismatch: __muloti4
>>> defined as (i32, i64, i64, i64, i64, i32) -> void in /home/gitpod/.ghc-wasm/wasi-sdk/bin/../share/wasi-sysroot/lib/wasm32-wasi/libc.a(pselect.o)
>>> defined as (i64, i64, i64, i64, i32) -> i64 in /home/gitpod/.ghc-wasm/wasi-sdk/lib/clang/15.0.5/lib/wasi/libclang_rt.builtins-wasm32.a(muloti4.c.obj)

Posting the bug early, and a self-contained minimal repro should come later.

@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2022

@llvm/issue-subscribers-backend-webassembly

@TerrorJack
Copy link
Author

Hi folks, I came up with the minimum repro that works for latest clang-15 official apt release on ubuntu-22.04:

Content of muloti4.c (preprocessed & shrinked from https://github.com/llvm/llvm-project/blob/release/15.x/compiler-rt/lib/builtins/muloti4.c):

a, c;
__int128 b;
fn1() {
  if (b < 0)
    if (a > 8 / b)
      c = 0;
}

Content of udivti3.c (preprocessed from https://github.com/llvm/llvm-project/blob/release/15.x/compiler-rt/lib/builtins/udivti3.c):

# 1 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/udivti3.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 327 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/udivti3.c" 2
# 13 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/udivti3.c"
# 1 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 1
# 92 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h"
# 1 "/usr/lib/llvm-15/lib/clang/15.0.6/include/float.h" 1 3
# 93 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 2
# 1 "/usr/lib/llvm-15/lib/clang/15.0.6/include/limits.h" 1 3
# 21 "/usr/lib/llvm-15/lib/clang/15.0.6/include/limits.h" 3
# 1 "/tmp/wasi-sysroot/include/limits.h" 1 3



# 1 "/tmp/wasi-sysroot/include/features.h" 1 3
# 5 "/tmp/wasi-sysroot/include/limits.h" 2 3

# 1 "/tmp/wasi-sysroot/include/bits/alltypes.h" 1 3
# 269 "/tmp/wasi-sysroot/include/bits/alltypes.h" 3
# 1 "/tmp/wasi-sysroot/include/__struct_timeval.h" 1 3



# 1 "/tmp/wasi-sysroot/include/__typedef_time_t.h" 1 3




typedef long long time_t;
# 5 "/tmp/wasi-sysroot/include/__struct_timeval.h" 2 3
# 1 "/tmp/wasi-sysroot/include/__typedef_suseconds_t.h" 1 3





typedef long long suseconds_t;
# 6 "/tmp/wasi-sysroot/include/__struct_timeval.h" 2 3


struct timeval {
    time_t tv_sec;
    suseconds_t tv_usec;
};
# 270 "/tmp/wasi-sysroot/include/bits/alltypes.h" 2 3
# 1 "/tmp/wasi-sysroot/include/__struct_timespec.h" 1 3






struct timespec {
    time_t tv_sec;
    long tv_nsec;
};
# 271 "/tmp/wasi-sysroot/include/bits/alltypes.h" 2 3
# 402 "/tmp/wasi-sysroot/include/bits/alltypes.h" 3
# 1 "/tmp/wasi-sysroot/include/__struct_iovec.h" 1 3




# 1 "/usr/lib/llvm-15/lib/clang/15.0.6/include/stddef.h" 1 3
# 46 "/usr/lib/llvm-15/lib/clang/15.0.6/include/stddef.h" 3
typedef long unsigned int size_t;
# 6 "/tmp/wasi-sysroot/include/__struct_iovec.h" 2 3

struct iovec {
    void *iov_base;
    size_t iov_len;
};
# 403 "/tmp/wasi-sysroot/include/bits/alltypes.h" 2 3
# 7 "/tmp/wasi-sysroot/include/limits.h" 2 3
# 40 "/tmp/wasi-sysroot/include/limits.h" 3
# 1 "/tmp/wasi-sysroot/include/bits/limits.h" 1 3
# 1 "/tmp/wasi-sysroot/include/__macro_PAGESIZE.h" 1 3
# 2 "/tmp/wasi-sysroot/include/bits/limits.h" 2 3
# 41 "/tmp/wasi-sysroot/include/limits.h" 2 3
# 22 "/usr/lib/llvm-15/lib/clang/15.0.6/include/limits.h" 2 3
# 94 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 2
# 1 "/usr/lib/llvm-15/lib/clang/15.0.6/include/stdbool.h" 1 3
# 95 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 2
# 1 "/usr/lib/llvm-15/lib/clang/15.0.6/include/stdint.h" 1 3
# 52 "/usr/lib/llvm-15/lib/clang/15.0.6/include/stdint.h" 3
# 1 "/tmp/wasi-sysroot/include/stdint.h" 1 3
# 20 "/tmp/wasi-sysroot/include/stdint.h" 3
# 1 "/tmp/wasi-sysroot/include/bits/alltypes.h" 1 3
# 77 "/tmp/wasi-sysroot/include/bits/alltypes.h" 3
typedef unsigned long uintptr_t;
# 92 "/tmp/wasi-sysroot/include/bits/alltypes.h" 3
typedef long intptr_t;
# 130 "/tmp/wasi-sysroot/include/bits/alltypes.h" 3
typedef signed char int8_t;




typedef signed short int16_t;




typedef signed int int32_t;




typedef signed long long int64_t;




typedef signed long long intmax_t;




typedef unsigned char uint8_t;




typedef unsigned short uint16_t;




typedef unsigned int uint32_t;




typedef unsigned long long uint64_t;
# 180 "/tmp/wasi-sysroot/include/bits/alltypes.h" 3
typedef unsigned long long uintmax_t;
# 21 "/tmp/wasi-sysroot/include/stdint.h" 2 3

typedef int8_t int_fast8_t;
typedef int64_t int_fast64_t;

typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;

typedef uint8_t uint_fast8_t;
typedef uint64_t uint_fast64_t;

typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
# 95 "/tmp/wasi-sysroot/include/stdint.h" 3
# 1 "/tmp/wasi-sysroot/include/bits/stdint.h" 1 3
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
# 96 "/tmp/wasi-sysroot/include/stdint.h" 2 3
# 53 "/usr/lib/llvm-15/lib/clang/15.0.6/include/stdint.h" 2 3
# 96 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 2



# 1 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h" 1
# 19 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h"
# 1 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_endianness.h" 1
# 20 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h" 2





typedef int32_t si_int;
typedef uint32_t su_int;
# 37 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h"
typedef int64_t di_int;
typedef uint64_t du_int;

typedef union {
  di_int all;
  struct {

    su_int low;
    si_int high;




  } s;
} dwords;

typedef union {
  du_int all;
  struct {

    su_int low;
    su_int high;




  } s;
} udwords;
# 79 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h"
typedef int ti_int __attribute__((mode(TI)));
typedef unsigned tu_int __attribute__((mode(TI)));

typedef union {
  ti_int all;
  struct {

    du_int low;
    di_int high;




  } s;
} twords;

typedef union {
  tu_int all;
  struct {

    du_int low;
    du_int high;




  } s;
} utwords;

static inline ti_int make_ti(di_int h, di_int l) {
  twords r;
  r.s.high = h;
  r.s.low = l;
  return r.all;
}

static inline tu_int make_tu(du_int h, du_int l) {
  utwords r;
  r.s.high = h;
  r.s.low = l;
  return r.all;
}
# 133 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h"
typedef union {
  su_int u;
  float f;
} float_bits;

typedef union {
  udwords u;
  double f;
} double_bits;


typedef struct {

  udwords low;
  udwords high;




} uqwords;
# 169 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_types.h"
typedef union {
  uqwords u;
  long double f;
} long_double_bits;


typedef float _Complex Fcomplex;
typedef double _Complex Dcomplex;
typedef long double _Complex Lcomplex;
# 100 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 2


# 1 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_util.h" 1
# 23 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_util.h"
__attribute__((noreturn)) void __compilerrt_abort_impl(const char *file, int line,
                                      const char *function);
# 103 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/int_lib.h" 2

                int __paritysi2(si_int a);
                int __paritydi2(di_int a);

                di_int __divdi3(di_int a, di_int b);
                si_int __divsi3(si_int a, si_int b);
                su_int __udivsi3(su_int n, su_int d);

                su_int __udivmodsi4(su_int a, su_int b, su_int *rem);
                du_int __udivmoddi4(du_int a, du_int b, du_int *rem);

                int __clzti2(ti_int a);
                tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem);
# 14 "/workspace/wasi-sdk/src/llvm-project/compiler-rt/lib/builtins/udivti3.c" 2





                tu_int __udivti3(tu_int a, tu_int b) {
  return __udivmodti4(a, b, 0);
}

The command to compile and reproduce:

clang-15 --target=wasm32 -mmultivalue -O2 -o muloti4.c.obj -c muloti4.c
clang-15 --target=wasm32 -mmultivalue -o udivti3.c.obj -c udivti3.c
wasm-ld-15 -r muloti4.c.obj udivti3.c.obj -o combined.o

You can see the warning message about signature mismatch when -mmultivalue is enabled:

wasm-ld: warning: function signature mismatch: __udivti3
>>> defined as (i32, i64, i64, i64, i64) -> void in muloti4.c.obj
>>> defined as (i64, i64, i64, i64) -> i64 in udivti3.c.obj

I hope the example above helps in looking into this issue, thanks :)

@HerrCai0907
Copy link
Contributor

canditate D146271

@TerrorJack
Copy link
Author

@HerrCai0907 Thanks a lot for D146271! I tried cherry-picking it on top of 16.0.0 in my fork, enabling -mmultivalue in sysroot of wasi-sdk, then the test suite produced the following warnings and errors:

Testing printf-long-double-enabled.c...
Testing printf-long-double-enabled.c...
wasm-ld: warning: function signature mismatch: __subtf3
>>> defined as (i32, i64, i64, i64, i64) -> void in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi/libc-printscan-long-double.a(vfprintf.long-double.o)
>>> defined as (i64, i64, i64, i64) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(subtf3.c.obj)

wasm-ld: warning: function signature mismatch: __addtf3
>>> defined as (i32, i64, i64, i64, i64) -> void in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi/libc-printscan-long-double.a(vfprintf.long-double.o)
>>> defined as (i64, i64, i64, i64) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(addtf3.c.obj)

wasm-ld: warning: function signature mismatch: __ashlti3
>>> defined as (i64, i64, i32) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(addtf3.c.obj)
>>> defined as (i64, i64, i32) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(ashlti3.c.obj)

wasm-ld: warning: function signature mismatch: __floatunsitf
>>> defined as (i32, i32) -> void in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi/libc-printscan-long-double.a(vfprintf.long-double.o)
>>> defined as (i32) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(floatunsitf.c.obj)

wasm-ld: warning: function signature mismatch: __extenddftf2
>>> defined as (i32, f64) -> void in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi/libc-printscan-long-double.a(vfprintf.long-double.o)
>>> defined as (f64) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(extenddftf2.c.obj)

wasm-ld: warning: function signature mismatch: __lshrti3
>>> defined as (i64, i64, i32) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(addtf3.c.obj)
>>> defined as (i64, i64, i32) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(lshrti3.c.obj)

wasm-ld: warning: function signature mismatch: __multf3
>>> defined as (i32, i64, i64, i64, i64) -> void in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi/libc.a(frexpl.o)
>>> defined as (i64, i64, i64, i64) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(multf3.c.obj)

wasm-ld: warning: function signature mismatch: __floatsitf
>>> defined as (i32, i32) -> void in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi/libc-printscan-long-double.a(vfprintf.long-double.o)
>>> defined as (i32) -> i64 in /builds/ghc/wasi-sdk/build/install/opt/wasi-sdk/lib/clang/16/lib/wasi/libclang_rt.builtins-wasm32.a(floatsitf.c.obj)
--- /dev/null
+++ printf-long-double-enabled.c.-O0.stderr.observed
@@ -0,0 +1,6 @@
+Error: failed to run main module `printf-long-double-enabled.c.-O0.wasm`
+
+Caused by:
+    0: failed to compile wasm function 36 (`pop_arg`) at offset 0x209e
+    1: WebAssembly translation error
+    2: Invalid input WebAssembly code at offset 8900: type mismatch: expected i32 but nothing on stack
make: *** [Makefile:48: check] Error 1

So it seems there are still some cases not covered by that patch. I'll try to come up with a more self-contained repro soon.

@TerrorJack
Copy link
Author

Here's a minimal repro for the signature mismatch of __subtf3, after applying D146271 on 16.0.0:

int a;
long double b;
int fn1() {
  a -= b;
  return 0;
}
$ build/install/opt/wasi-sdk/bin/clang -mmultivalue --target=wasm32-wasi -S -o floatscan.long-double.s floatscan.long-double.c

The above command would generate a call to __subtf3 with signature (i32, i64, i64, i64, i64) -> (), even if -mmultivalue has been passed.

long double __subtf3(long double, long double) {}
build/install/opt/wasi-sdk/bin/clang --target=wasm32-wasi -mmultivalue -o subtf3.s -S subtf3.c

The above command that compiles __subtf3 will generate a __subtf3 function with signature (i64, i64, i64, i64) -> (i64, i64). Which indeed is the expected behavior when -mmultivalue is enabled.

@HerrCai0907
Copy link
Contributor

It's caused by this code Table[RTLIB::SUB_F128] = func_iPTR_i64_i64_i64_i64;
Let me check the implement of those code.

@HerrCai0907
Copy link
Contributor

merge D146271.
fix long double in D146499

@TerrorJack
Copy link
Author

@HerrCai0907 Thanks a lot for the two patches! I tried applying both D146271 and D146499 on top of 16.0.0, and now I have another minimum repro for a signature mismatch of __lshrti3:

__uint128_t toRep();
void fromRep() {
  __uint128_t bRep = toRep(), bSignificand = bRep;
  int align = bRep;
  bSignificand = bSignificand >> align;
  if (bSignificand)
    fromRep();
}
$ build/install/opt/wasi-sdk/bin/clang --target=wasm32 -mmultivalue -o addtf3.s -S addtf3.c
$ grep -F '.functype	__lshrti3 (i64, i64, i32) -> (i64, i64, i64, i64)' addtf3.s
__int128 __lshrti3(__int128, int) {}
$ build/install/opt/wasi-sdk/bin/clang --target=wasm32 -mmultivalue -o lshrti3.s -S lshrti3.c
$ grep -F '.functype	__lshrti3 (i64, i64, i32) -> (i64, i64)' lshrti3.s

@HerrCai0907
Copy link
Contributor

current patch:
https://reviews.llvm.org/D146271 (merged)
https://reviews.llvm.org/D146499 (merged)
https://reviews.llvm.org/D146533 (merged)

Maybe you can try again. Thanks!

@TerrorJack
Copy link
Author

@HerrCai0907 I can now confirm the three patches fix all the compiler-rt function signature mismatches for the time being.

thankyou

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants