1;;! target = "x86_64"
2;;! test = "optimize"
3
4;; Current WebAssembly toolchains represent source-language function pointers
5;; by constructing a single WebAssembly funcref table, initializing it with an
6;; element section, and never writing to it again. This test tracks what code
7;; we generate for that pattern.
8
9;; Motivated by https://github.com/bytecodealliance/wasmtime/issues/8195
10
11(module
12  (type $fn (func))
13  (table $fnptrs 2 2 funcref)
14  (func $callee)
15  (func $caller (param i32)
16        local.get 0
17        call_indirect $fnptrs (type $fn))
18  (elem $fnptrs (i32.const 1) func $callee)
19)
20
21;; function u0:0(i64 vmctx, i64) tail {
22;;     gv0 = vmctx
23;;     gv1 = load.i64 notrap aligned readonly gv0+8
24;;     gv2 = load.i64 notrap aligned gv1+24
25;;     stack_limit = gv2
26;;
27;;                                 block0(v0: i64, v1: i64):
28;; @002c                               jump block1
29;;
30;;                                 block1:
31;; @002c                               return
32;; }
33;;
34;; function u0:1(i64 vmctx, i64, i32) tail {
35;;     gv0 = vmctx
36;;     gv1 = load.i64 notrap aligned readonly gv0+8
37;;     gv2 = load.i64 notrap aligned gv1+24
38;;     gv3 = vmctx
39;;     gv4 = load.i64 notrap aligned readonly can_move gv3+48
40;;     sig0 = (i64 vmctx, i64) tail
41;;     sig1 = (i64 vmctx, i32, i64) -> i64 tail
42;;     fn0 = colocated u805306368:9 sig1
43;;     stack_limit = gv2
44;;
45;;                                 block0(v0: i64, v1: i64, v2: i32):
46;; @0031                               v3 = iconst.i32 2
47;; @0031                               v4 = icmp uge v2, v3  ; v3 = 2
48;; @0031                               v9 = iconst.i64 0
49;; @0031                               v6 = load.i64 notrap aligned readonly can_move v0+48
50;; @0031                               v5 = uextend.i64 v2
51;;                                     v26 = iconst.i64 3
52;; @0031                               v7 = ishl v5, v26  ; v26 = 3
53;; @0031                               v8 = iadd v6, v7
54;; @0031                               v10 = select_spectre_guard v4, v9, v8  ; v9 = 0
55;; @0031                               v11 = load.i64 user5 aligned table v10
56;;                                     v25 = iconst.i64 -2
57;; @0031                               v12 = band v11, v25  ; v25 = -2
58;; @0031                               brif v11, block3(v12), block2
59;;
60;;                                 block2 cold:
61;; @0031                               v14 = iconst.i32 0
62;; @0031                               v17 = call fn0(v0, v14, v5)  ; v14 = 0
63;; @0031                               jump block3(v17)
64;;
65;;                                 block3(v13: i64):
66;; @0031                               v21 = load.i32 user6 aligned readonly v13+16
67;; @0031                               v19 = load.i64 notrap aligned readonly can_move v0+40
68;; @0031                               v20 = load.i32 notrap aligned readonly can_move v19
69;; @0031                               v22 = icmp eq v21, v20
70;; @0031                               trapz v22, user7
71;; @0031                               v23 = load.i64 notrap aligned readonly v13+8
72;; @0031                               v24 = load.i64 notrap aligned readonly v13+24
73;; @0031                               call_indirect sig0, v23(v24, v0)
74;; @0034                               jump block1
75;;
76;;                                 block1:
77;; @0034                               return
78;; }
79