[llvm] [WebAssembly] Implement lowering calls through funcref to call_ref when available (PR #162227)
Demetrius Kanios via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 11 13:10:02 PDT 2026
QuantumSegfault wrote:
> I mean, other than it needing rebasing, I guess there's no real reason to block this at all.
>
> If the existing thing I was trying to compare against doesn't work, than this is a solid improvement. I'll rebase and do a simple test to make sure it still works as intended.
Without #166820 I don't think it's possible to do this from C yet (func ptr => funcref for testing). But with IR:
```ll
target triple = "wasm32-unknown-unknown"
@__indirect_function_table = external addrspace(1) global [0 x ptr addrspace(20)]
declare ptr addrspace(20) @llvm.wasm.table.get.funcref(ptr addrspace(1), i32) nounwind
define hidden i32 @call_callback(ptr addrspace(20) %callback) {
entry:
%call = call addrspace(20) i32 %callback(i32 32)
ret i32 %call
}
define hidden i32 @times_two(i32 %x) {
entry:
%mul = mul nsw i32 %x, 2
ret i32 %mul
}
define i32 @test() {
entry:
%funcref = call ptr addrspace(20) @llvm.wasm.table.get.funcref(ptr addrspace(1) @__indirect_function_table, i32 ptrtoint (ptr @times_two to i32))
%call = call i32 @call_callback(ptr addrspace(20) %funcref)
ret i32 %call
}
```
```
$ wasm-ld --export=test --no-entry -o test.wasm <(bin/llc -filetype=obj -mattr=+reference-types,+gc -o - test.ll)
$ wasm-tools print test.wasm
(module $test.wasm
(type (;0;) (func (param i32) (result i32)))
(type (;1;) (func (param funcref) (result i32)))
(type (;2;) (func (result i32)))
(table (;0;) 2 2 funcref)
(memory (;0;) 1)
(export "memory" (memory 0))
(export "test" (func $test))
(elem (;0;) (i32.const 1) func $times_two)
(func $call_callback (;0;) (type 1) (param funcref) (result i32)
i32.const 32
local.get 0
ref.cast (ref 0)
call_ref 0
)
(func $times_two (;1;) (type 0) (param i32) (result i32)
local.get 0
i32.const 1
i32.shl
)
(func $test (;2;) (type 2) (result i32)
i32.const 1
table.get 0
call $call_callback
)
(@custom "target_features" (after code) "\09+\0bbulk-memory+\0fbulk-memory-opt+\16call-indirect-overlong+\02gc+\0amultivalue+\0fmutable-globals+\13nontrapping-fptoint+\0freference-types+\08sign-ext")
)
$ wasmtime run -W gc,function-references --invoke test test.wasm 32
64
```
It works, performance considerations aside.
https://github.com/llvm/llvm-project/pull/162227
More information about the llvm-commits
mailing list