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

Add more disassembly tests for call_indirect #8202

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions tests/disas/icall-loop.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
;;! target = "x86_64"
;;! test = "optimize"

;; When `call_indirect` is used in a loop with the same table index on every
;; iteration, we can hoist part of the work out of the loop. This test tracks
;; how much we're successfully pulling out.

(module
(type $fn (func (result i32)))
(table $fnptrs 2 2 funcref)
(func (param i32)
loop
local.get 0
call_indirect $fnptrs (type $fn)
br 0
end)
(func
loop
i32.const 1
call_indirect $fnptrs (type $fn)
br 0
end)
)

;; function u0:0(i64 vmctx, i64, i32) fast {
;; gv0 = vmctx
;; gv1 = load.i64 notrap aligned readonly gv0+8
;; gv2 = load.i64 notrap aligned gv1
;; gv3 = vmctx
;; gv4 = load.i64 notrap aligned gv3+72
;; sig0 = (i64 vmctx, i64) -> i32 fast
;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v
;; stack_limit = gv2
;;
;; block0(v0: i64, v1: i64, v2: i32):
;; v16 -> v0
;; v20 -> v0
;; v29 -> v0
;; v3 -> v2
;; v28 -> v3
;; @002b v4 = iconst.i32 2
;; @002b v5 = icmp uge v2, v4 ; v4 = 2
;; @002b v10 = iconst.i64 0
;; @002b v6 = uextend.i64 v2
;; v30 = iconst.i64 3
;; @002b v8 = ishl v6, v30 ; v30 = 3
;; v31 = iconst.i64 -2
;; @002b v17 = load.i64 notrap aligned readonly v0+56
;; @002b v18 = load.i64 notrap aligned readonly v17+72
;; @002b v15 = iconst.i32 0
;; @002b v21 = load.i64 notrap aligned readonly v0+64
;; @002b v22 = load.i32 notrap aligned readonly v21
;; @0027 jump block2
;;
;; block2:
;; @002b v7 = load.i64 notrap aligned v0+72
;; @002b v9 = iadd v7, v8
;; v32 = iconst.i64 0
;; v33 = select_spectre_guard v5, v32, v9 ; v32 = 0
;; @002b v12 = load.i64 table_oob aligned table v33
;; v34 = iconst.i64 -2
;; v35 = band v12, v34 ; v34 = -2
;; @002b brif v12, block5(v35), block4
;;
;; block4 cold:
;; v36 = iconst.i32 0
;; @002b v19 = call_indirect.i64 sig1, v18(v0, v36, v2) ; v36 = 0
;; @002b jump block5(v19)
;;
;; block5(v14: i64):
;; @002b v23 = load.i32 icall_null aligned readonly v14+24
;; @002b v24 = icmp eq v23, v22
;; @002b brif v24, block7, block6
;;
;; block6 cold:
;; @002b trap bad_sig
;;
;; block7:
;; @002b v25 = load.i64 notrap aligned readonly v14+16
;; @002b v26 = load.i64 notrap aligned readonly v14+32
;; @002b v27 = call_indirect sig0, v25(v26, v0)
;; @002e jump block2
;; }
;;
;; function u0:1(i64 vmctx, i64) fast {
;; gv0 = vmctx
;; gv1 = load.i64 notrap aligned readonly gv0+8
;; gv2 = load.i64 notrap aligned gv1
;; gv3 = vmctx
;; gv4 = load.i64 notrap aligned gv3+72
;; sig0 = (i64 vmctx, i64) -> i32 fast
;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v
;; stack_limit = gv2
;;
;; block0(v0: i64, v1: i64):
;; v15 -> v0
;; v19 -> v0
;; v27 -> v0
;; v38 = iconst.i64 8
;; v29 = iconst.i64 -2
;; @0038 v16 = load.i64 notrap aligned readonly v0+56
;; @0038 v17 = load.i64 notrap aligned readonly v16+72
;; @0038 v14 = iconst.i32 0
;; @0036 v2 = iconst.i32 1
;; @0038 v20 = load.i64 notrap aligned readonly v0+64
;; @0038 v21 = load.i32 notrap aligned readonly v20
;; @0034 jump block2
;;
;; block2:
;; @0038 v6 = load.i64 notrap aligned v0+72
;; v39 = iconst.i64 8
;; v40 = iadd v6, v39 ; v39 = 8
;; @0038 v11 = load.i64 table_oob aligned table v40
;; v41 = iconst.i64 -2
;; v42 = band v11, v41 ; v41 = -2
;; @0038 brif v11, block5(v42), block4
;;
;; block4 cold:
;; v43 = iconst.i32 0
;; v44 = iconst.i32 1
;; @0038 v18 = call_indirect.i64 sig1, v17(v0, v43, v44) ; v43 = 0, v44 = 1
;; @0038 jump block5(v18)
;;
;; block5(v13: i64):
;; @0038 v22 = load.i32 icall_null aligned readonly v13+24
;; @0038 v23 = icmp eq v22, v21
;; @0038 brif v23, block7, block6
;;
;; block6 cold:
;; @0038 trap bad_sig
;;
;; block7:
;; @0038 v24 = load.i64 notrap aligned readonly v13+16
;; @0038 v25 = load.i64 notrap aligned readonly v13+32
;; @0038 v26 = call_indirect sig0, v24(v25, v0)
;; @003b jump block2
;; }
91 changes: 91 additions & 0 deletions tests/disas/readonly-funcrefs.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
;;! target = "x86_64"
;;! test = "optimize"

;; Current WebAssembly toolchains represent source-language function pointers
;; by constructing a single WebAssembly funcref table, initializing it with an
;; element section, and never writing to it again. This test tracks what code
;; we generate for that pattern.

;; Motivated by https://github.com/bytecodealliance/wasmtime/issues/8195

(module
(type $fn (func))
(table $fnptrs 2 2 funcref)
(func $callee)
(func $caller (param i32)
local.get 0
call_indirect $fnptrs (type $fn))
(elem $fnptrs (i32.const 1) func $callee)
)

;; function u0:0(i64 vmctx, i64) fast {
;; gv0 = vmctx
;; gv1 = load.i64 notrap aligned readonly gv0+8
;; gv2 = load.i64 notrap aligned gv1
;; sig0 = (i64 vmctx, i32 uext, i32 uext) -> i32 uext system_v
;; sig1 = (i64 vmctx, i32 uext) -> i32 uext system_v
;; stack_limit = gv2
;;
;; block0(v0: i64, v1: i64):
;; @002c jump block1
;;
;; block1:
;; @002c return
;; }
;;
;; function u0:1(i64 vmctx, i64, i32) fast {
;; gv0 = vmctx
;; gv1 = load.i64 notrap aligned readonly gv0+8
;; gv2 = load.i64 notrap aligned gv1
;; gv3 = vmctx
;; gv4 = load.i64 notrap aligned gv3+72
;; sig0 = (i64 vmctx, i64) fast
;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v
;; sig2 = (i64 vmctx, i32 uext, i32 uext) -> i32 uext system_v
;; sig3 = (i64 vmctx, i32 uext) -> i32 uext system_v
;; stack_limit = gv2
;;
;; block0(v0: i64, v1: i64, v2: i32):
;; v15 -> v0
;; v19 -> v0
;; v26 -> v0
;; @0031 v6 = load.i64 notrap aligned v0+72
;; @0031 v3 = iconst.i32 2
;; @0031 v4 = icmp uge v2, v3 ; v3 = 2
;; @0031 v9 = iconst.i64 0
;; @0031 v5 = uextend.i64 v2
;; v27 = iconst.i64 3
;; @0031 v7 = ishl v5, v27 ; v27 = 3
;; @0031 v8 = iadd v6, v7
;; @0031 v10 = select_spectre_guard v4, v9, v8 ; v9 = 0
;; @0031 v11 = load.i64 table_oob aligned table v10
;; v28 = iconst.i64 -2
;; @0031 v12 = band v11, v28 ; v28 = -2
;; @0031 brif v11, block3(v12), block2
;;
;; block2 cold:
;; @0031 v16 = load.i64 notrap aligned readonly v0+56
;; @0031 v17 = load.i64 notrap aligned readonly v16+72
;; @0031 v14 = iconst.i32 0
;; @0031 v18 = call_indirect sig1, v17(v0, v14, v2) ; v14 = 0
;; @0031 jump block3(v18)
;;
;; block3(v13: i64):
;; @0031 v22 = load.i32 icall_null aligned readonly v13+24
;; @0031 v20 = load.i64 notrap aligned readonly v0+64
;; @0031 v21 = load.i32 notrap aligned readonly v20
;; @0031 v23 = icmp eq v22, v21
;; @0031 brif v23, block5, block4
;;
;; block4 cold:
;; @0031 trap bad_sig
;;
;; block5:
;; @0031 v24 = load.i64 notrap aligned readonly v13+16
;; @0031 v25 = load.i64 notrap aligned readonly v13+32
;; @0031 call_indirect sig0, v24(v25, v0)
;; @0034 jump block1
;;
;; block1:
;; @0034 return
;; }