llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.98k stars 11.94k forks source link

wasm-ld: error on signature mismatch in direct call? #41062

Open sunfishcode opened 5 years ago

sunfishcode commented 5 years ago
Bugzilla Link 41717
Version unspecified
OS other
CC @sbc100,@yowl,@smithp35

Extended Description

Forwarding a report from here:

https://github.com/CraneStation/wasi-sysroot/pull/21#issuecomment-488501838

The user had code which was calling qsort and srand with implicit declarations. This works on native plaforms, but fails on wasm, because the actual definitions have a "void" return type, while an implicit declaration has an "i32" return type, so the wasm signatures don't match.

wasm-ld correctly printed a warning here, but it seems like it could issue a hard error here, in the case of a direct call to a callee with a different signature, because that leads to a wasm module that doesn't even validate.

yowl commented 4 years ago

Have created llvm/llvm-bugzilla-archive#44381 . But not sure it's really a bug.

sbc100 commented 4 years ago

I can't reproduce your specific issue. I tried using the code from https://github.com/WebAssembly/binaryen/issues/2126 and wasm-ld produced a binary that didn't have in errors when run through wasm-dis or wasm-validate.

Can you post your updated test case and failure mode perhaps?

Also, I'm not sure this is the same issue that was originally reported to it might make sense to open a separate issue.

yowl commented 4 years ago

Trying this again today and still present. For more details there is https://github.com/WebAssembly/binaryen/issues/2126. The problem is no quite the same but it still invalid wasm, https://github.com/emscripten-core/emscripten/issues/10108. Can I change the priority from enhancement to normal, as I'm blocked a bit?

yowl commented 5 years ago

Believe I've got a similar problem. The complete llvm bc is large at 45MB and the wasm 18MB, but I can upload them somewhere if you'd like. I debugged wasm2wat to get the function that was causing wasm2wat to emit

test.wasm:08ae2bb: error: type mismatch in function, expected [] but got [i32]

and its:

define void @​S_P_CoreLib_System_Runtime_RuntimeImports__memset(i8, i8, i32, i32) { Prolog: %memarg0 = alloca i8 store i8 %1, i8* %memarg0 %valuearg1 = alloca i32 store i32 %2, i32 %valuearg1 %sizearg2 = alloca i32 store i32 %3, i32* %sizearg2 br label %Block0

Block0: ; preds = %Prolog %Loadarg0_ = load i8*, i8 %memarg0 %Loadarg1_ = load i32, i32 %valuearg1 %Loadarg2_ = load i32, i32 %sizearg2 %shadowStackTop = getelementptr i8, i8 %0, i32 0 store i8 %shadowStackTop, i8 @​tpShadowStackTop %PInvokeTransitionFrame = alloca { i8, i8, i8 } call void @​RhpPInvoke2({ i8, i8, i8 } %PInvokeTransitionFrame) call void @​memset(i8 %Loadarg0, i32 %Loadarg1, i32 %Loadarg2) call void @​RhpPInvokeReturn2({ i8, i8, i8 } %PInvokeTransitionFrame) ret void }

If I run

d:\llvm9\release\bin\wasm-ld.exe -o test.wasm --allow-undefined --import-memory --import-table --lto-O0 --whole-archive HelloWasm.bc --no-whole-archive -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --no-gc-sections --export-dynamic --export wasm_call_ctors --export data_end --export main --export malloc --export free --export setThrew --export __errno_location --export fflush -shared

On this and then wasm2wat I get the above error. If I run wasm2wat with --no-check I get the wat:

(func $S_P_CoreLib_System_Runtime_RuntimeImports__memset (type 10) (param i32 i32 i32 i32) (local i32) global.get 0 i32.const 32 i32.sub local.tee 4 global.set 0 global.get 1 i32.const 256 i32.add local.get 0 i32.store local.get 4 local.get 2 i32.store offset=24 local.get 4 local.get 1 i32.store offset=28 local.get 4 local.get 3 i32.store offset=20 local.get 4 i32.const 8 i32.add call $RhpPInvoke2 local.get 1 local.get 2 local.get 3 call $memset local.get 4 i32.const 8 i32.add call $RhpPInvokeReturn2 local.get 4 i32.const 32 i32.add global.set 0)

The signatures of the called methods are

(import "env" "RhpPInvoke2" (func $RhpPInvoke2 (type 2))) (import "env" "RhpPInvokeReturn2" (func $RhpPInvokeReturn2 (type 2))) (import "env" "memset" (func $memset (type 11)))

Where those types are

(type (;2;) (func (param i32))) (type (;11;) (func (param i32 i32 i32) (result i32)))

This last one is odd (at least to me) as its declared void in the llvm:

declare void @​memset(i8*, i32, i32)

Let me know if I can do anything else.

sbc100 commented 5 years ago

I agree that wasm-ld should never produce an invalid wasm module. I'll take a look.