| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| ;; RUN: foreach %s %t wasm-opt -all --make-shared-objects -S -o - | filecheck %s |
| |
| (module |
| ;; Check lowering of basic heap types. |
| ;; CHECK: (type $0 (func (param (ref null (shared none))) (result (ref null (shared none))))) |
| |
| ;; CHECK: (type $1 (func (param (ref (shared none))) (result (ref (shared none))))) |
| |
| ;; CHECK: (type $2 (func (param (ref null (shared i31))) (result (ref null (shared i31))))) |
| |
| ;; CHECK: (type $3 (func (param (ref (shared i31))) (result (ref (shared i31))))) |
| |
| ;; CHECK: (type $4 (func (param (ref null (shared any))) (result (ref null (shared any))))) |
| |
| ;; CHECK: (type $5 (func (param (ref (shared any))) (result (ref (shared any))))) |
| |
| ;; CHECK: (type $6 (func (param (ref null (shared eq))) (result (ref null (shared eq))))) |
| |
| ;; CHECK: (type $7 (func (param (ref (shared eq))) (result (ref (shared eq))))) |
| |
| ;; CHECK: (type $8 (func (param (ref null (shared struct))) (result (ref null (shared struct))))) |
| |
| ;; CHECK: (type $9 (func (param (ref (shared struct))) (result (ref (shared struct))))) |
| |
| ;; CHECK: (type $10 (func (param (ref null (shared array))) (result (ref null (shared array))))) |
| |
| ;; CHECK: (type $11 (func (param (ref (shared array))) (result (ref (shared array))))) |
| |
| ;; CHECK: (func $funcref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $funcref (param funcref) (result funcref) |
| (local funcref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-funcref (type $3) (param $0 (ref (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref (shared i31))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-funcref (param (ref (shared func))) (result (ref (shared func))) |
| (local (ref (shared func))) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $nullfuncref (type $0) (param $0 (ref null (shared none))) (result (ref null (shared none))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared none))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $nullfuncref (param nullfuncref) (result nullfuncref) |
| (local nullfuncref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-nullfuncref (type $1) (param $0 (ref (shared none))) (result (ref (shared none))) |
| ;; CHECK-NEXT: (local $1 (ref (shared none))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-nullfuncref (param (ref (shared nofunc))) (result (ref (shared nofunc))) |
| (local (ref (shared nofunc))) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $anyref (type $4) (param $0 (ref null (shared any))) (result (ref null (shared any))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared any))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $anyref (param anyref) (result anyref) |
| (local anyref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-anyref (type $5) (param $0 (ref (shared any))) (result (ref (shared any))) |
| ;; CHECK-NEXT: (local $1 (ref (shared any))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-anyref (param (ref (shared any))) (result (ref (shared any))) |
| (local (ref (shared any))) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $eqref (type $6) (param $0 (ref null (shared eq))) (result (ref null (shared eq))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared eq))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $eqref (param eqref) (result eqref) |
| (local eqref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-eqref (type $7) (param $0 (ref (shared eq))) (result (ref (shared eq))) |
| ;; CHECK-NEXT: (local $1 (ref (shared eq))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-eqref (param (ref (shared eq))) (result (ref (shared eq))) |
| (local (ref (shared eq))) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $structref (type $8) (param $0 (ref null (shared struct))) (result (ref null (shared struct))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared struct))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $structref (param structref) (result structref) |
| (local structref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-structref (type $9) (param $0 (ref (shared struct))) (result (ref (shared struct))) |
| ;; CHECK-NEXT: (local $1 (ref (shared struct))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-structref (param (ref (shared struct))) (result (ref (shared struct))) |
| (local (ref (shared struct))) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $arrayref (type $10) (param $0 (ref null (shared array))) (result (ref null (shared array))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared array))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $arrayref (param arrayref) (result arrayref) |
| (local arrayref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-arrayref (type $11) (param $0 (ref (shared array))) (result (ref (shared array))) |
| ;; CHECK-NEXT: (local $1 (ref (shared array))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-arrayref (param (ref (shared array))) (result (ref (shared array))) |
| (local (ref (shared array))) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $nullref (type $0) (param $0 (ref null (shared none))) (result (ref null (shared none))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared none))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $nullref (param nullref) (result nullref) |
| (local nullref) |
| (local.get 0) |
| ) |
| |
| ;; CHECK: (func $shared-nullref (type $1) (param $0 (ref (shared none))) (result (ref (shared none))) |
| ;; CHECK-NEXT: (local $1 (ref (shared none))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $shared-nullref (param (ref (shared none))) (result (ref (shared none))) |
| (local (ref (shared none))) |
| (local.get 0) |
| ) |
| |
| ;; TODO: Handle exnref, contref. |
| ) |
| |
| ;; Recursive function types should be updated correctly. |
| (module |
| ;; CHECK: (type $func (func (param (ref (shared i31))) (result (ref (shared i31))))) |
| (type $func (func (param (ref $func)) (result (ref $func)))) |
| ;; CHECK: (func $f (type $func) (param $0 (ref (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref (shared i31))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $f (type $func) (param (ref $func)) (result (ref $func)) |
| (local (ref $func)) |
| (local.get 0) |
| ) |
| ) |
| |
| (module |
| ;; Struct and array types should become shared. Function references inside |
| ;; them should become shared i31refs. Shared struct and array types should |
| ;; remain shared. Function types should become unshared. Distinct shared and |
| ;; and unshared types can be merged, but that's ok because their values can |
| ;; never flow into the same locations. |
| (type $func (func)) |
| ;; CHECK: (type $array (shared (array (ref (shared i31))))) |
| |
| ;; CHECK: (type $shared-func (func)) |
| |
| ;; CHECK: (type $struct (shared (struct (field (ref (shared i31))) (field i32)))) |
| (type $struct (struct (field (ref $func)) (field i32))) |
| (type $array (array (ref (exact $func)))) |
| |
| (type $shared-func (shared (func))) |
| ;; CHECK: (type $shared-struct (shared (struct (field (ref null (shared i31)))))) |
| (type $shared-struct (shared (struct (field (ref null (exact $shared-func)))))) |
| (type $shared-array (shared (array (ref $shared-func)))) |
| |
| ;; CHECK: (type $4 (func (param (ref $struct) (ref $array) (ref $shared-struct) (ref $array)))) |
| |
| ;; CHECK: (func $use-types (type $4) (param $0 (ref $struct)) (param $1 (ref $array)) (param $2 (ref $shared-struct)) (param $3 (ref $array)) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $use-types (param (ref $struct) (ref $array) (ref $shared-struct) (ref $shared-array)) |
| (nop) |
| ) |
| ;; CHECK: (func $f (type $shared-func) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $f (type $func) |
| (nop) |
| ) |
| ;; CHECK: (func $f-shared (type $shared-func) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $f-shared (type $shared-func) |
| (nop) |
| ) |
| ) |
| |
| (module |
| ;; Rec groups containing mutually recursive struct, array, and function types |
| ;; should be preserved. |
| (rec |
| ;; CHECK: (rec |
| ;; CHECK-NEXT: (type $rec-func (func (param (ref $rec-struct)))) |
| (type $rec-func (func (param (ref $rec-struct)))) |
| ;; CHECK: (type $rec-struct (shared (struct (field (ref $rec-array)) (field (ref (shared i31)))))) |
| (type $rec-struct (struct (field (ref $rec-array)) (field (ref $rec-func)))) |
| ;; CHECK: (type $rec-array (shared (array (ref $rec-struct)))) |
| (type $rec-array (array (ref $rec-struct))) |
| ) |
| ;; CHECK: (type $3 (func (param (ref $rec-struct) (ref $rec-array) (ref (shared i31))))) |
| |
| ;; CHECK: (func $rec-group (type $3) (param $0 (ref $rec-struct)) (param $1 (ref $rec-array)) (param $2 (ref (shared i31))) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $rec-group (param (ref $rec-struct) (ref $rec-array) (ref $rec-func)) |
| (nop) |
| ) |
| ) |
| |
| (module |
| ;; Function supertypes are preserved. |
| ;; CHECK: (type $parent (sub (func))) |
| (type $parent (sub (shared (func)))) |
| ;; CHECK: (type $child (sub $parent (func))) |
| (type $child (sub $parent (shared (func)))) |
| ;; CHECK: (func $f1 (type $parent) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $f1 (type $parent) |
| (nop) |
| ) |
| ;; CHECK: (func $f2 (type $child) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $f2 (type $child) |
| (nop) |
| ) |
| ) |
| |
| (module |
| ;; Struct descriptor and described types become shared correctly. |
| (rec |
| ;; CHECK: (rec |
| ;; CHECK-NEXT: (type $struct (shared (descriptor $desc) (struct (field i32)))) |
| (type $struct (descriptor $desc) (struct (field i32))) |
| ;; CHECK: (type $desc (shared (describes $struct) (struct (field i32)))) |
| (type $desc (describes $struct) (struct (field i32))) |
| ) |
| ;; CHECK: (type $2 (func (param (ref $struct) (ref $desc)))) |
| |
| ;; CHECK: (func $descriptors (type $2) (param $0 (ref $struct)) (param $1 (ref $desc)) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $descriptors (param (ref $struct) (ref $desc)) |
| (nop) |
| ) |
| ) |
| |
| ;; Check that references to different functions are consistently assigned |
| ;; different indices. This module does not use the references with a call or |
| ;; cast, so it does not get the new table. |
| (module |
| ;; CHECK: (type $f (func)) |
| (type $f (func)) |
| ;; CHECK: (type $1 (func (result (ref null (shared none))))) |
| |
| ;; CHECK: (type $2 (func (result (ref null (shared i31))))) |
| |
| ;; CHECK: (type $3 (func (result (ref (shared i31))))) |
| |
| ;; CHECK: (func $target1 (type $f) |
| ;; CHECK-NEXT: ) |
| (func $target1 (type $f)) |
| ;; CHECK: (func $target2 (type $f) |
| ;; CHECK-NEXT: ) |
| (func $target2 (type $f)) |
| |
| ;; CHECK: (func $ref-null-nofunc (type $1) (result (ref null (shared none))) |
| ;; CHECK-NEXT: (ref.null (shared none)) |
| ;; CHECK-NEXT: ) |
| (func $ref-null-nofunc (result (ref null nofunc)) |
| ;; (ref.null nofunc) becomes (ref.null (shared none)). |
| (ref.null nofunc) |
| ) |
| |
| ;; CHECK: (func $ref-null-shared-nofunc (type $1) (result (ref null (shared none))) |
| ;; CHECK-NEXT: (ref.null (shared none)) |
| ;; CHECK-NEXT: ) |
| (func $ref-null-shared-nofunc (result (ref null (shared nofunc))) |
| ;; Same with a shared nofunc. |
| (ref.null (shared nofunc)) |
| ) |
| |
| ;; CHECK: (func $ref-func (type $2) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-func (result funcref) |
| ;; ref.func becomes a shared i31. |
| (ref.func $target1) |
| ) |
| |
| ;; CHECK: (func $other-ref-func (type $3) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $other-ref-func (result (ref (exact $f))) |
| ;; Different referenced function, different i31 value. |
| (ref.func $target2) |
| ) |
| |
| ;; CHECK: (func $multiple-ref-func (type $f) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $multiple-ref-func |
| ;; Mapping of functions to i31 values should be consistent. |
| (drop (ref.func $target1)) |
| (drop (ref.func $target1)) |
| (drop (ref.func $target2)) |
| ) |
| ) |
| |
| ;; Test replacement of references in module locations and lowering of calls. |
| (module |
| (type $sig (func (param i32) (result i32))) |
| ;; CHECK: (type $0 (func (result i32))) |
| |
| ;; CHECK: (type $shared-sig (func (param i32) (result i32))) |
| (type $shared-sig (shared (func (param i32) (result i32)))) |
| |
| ;; CHECK: (type $2 (func)) |
| |
| ;; CHECK: (type $struct (shared (struct (field (ref null (shared i31)))))) |
| (type $struct (struct (field (ref null func)))) |
| |
| (func $effect (import "" "") (result i32)) |
| |
| ;; CHECK: (type $4 (func (param (ref (shared i31)) i32) (result i32))) |
| |
| ;; CHECK: (type $5 (func (param (ref (shared i31))) (result i32))) |
| |
| ;; CHECK: (type $6 (func (param i32 i32) (result i32))) |
| |
| ;; CHECK: (import "" "" (func $effect (type $0) (result i32))) |
| |
| ;; CHECK: (global $g (ref null (shared i31)) (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: )) |
| (global $g (ref null func) (ref.func $a)) |
| |
| ;; CHECK: (global $g-struct (ref null $struct) (struct.new $struct |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: )) |
| (global $g-struct (ref null $struct) (struct.new $struct (ref.func $b))) |
| |
| ;; CHECK: (table $t-init 1 1 (ref null (shared i31)) (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: )) |
| (table $t-init 1 1 (ref null func) (ref.func $c)) |
| |
| ;; CHECK: (table $t 1 1 (ref null (shared i31))) |
| (table $t 1 1 (ref null $sig)) |
| ;; CHECK: (table $t-shared 1 1 (ref null (shared i31))) |
| (table $t-shared 1 1 (ref null (shared func))) |
| |
| ;; CHECK: (table $funcs 4 4 funcref) |
| |
| ;; CHECK: (elem $elem (ref null (shared i31)) (item (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ))) |
| (elem $elem funcref (ref.func $d)) |
| |
| ;; CHECK: (elem $funcs (table $funcs) (i32.const 0) func $a $b $d $c) |
| |
| ;; CHECK: (func $a (type $2) |
| ;; CHECK-NEXT: ) |
| (func $a) |
| ;; CHECK: (func $b (type $2) |
| ;; CHECK-NEXT: ) |
| (func $b) |
| ;; CHECK: (func $c (type $2) |
| ;; CHECK-NEXT: ) |
| (func $c) |
| ;; CHECK: (func $d (type $2) |
| ;; CHECK-NEXT: ) |
| (func $d) |
| |
| ;; CHECK: (func $call-ref (type $4) (param $0 (ref (shared i31))) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $call-ref (param (ref $sig) i32) (result i32) |
| (call_ref $sig (local.get 1) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $unreachable-call-ref (type $0) (result i32) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $unreachable-call-ref (result i32) |
| (call_ref $sig (i32.const 0) (unreachable)) |
| ) |
| |
| ;; CHECK: (func $unreachable-call-ref-effect (type $0) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $effect) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $unreachable-call-ref-effect (result i32) |
| (call_ref $sig (call $effect) (unreachable)) |
| ) |
| |
| ;; CHECK: (func $null-call-ref (type $0) (result i32) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $null-call-ref (result i32) |
| (call_ref $sig (i32.const 0) (ref.null nofunc)) |
| ) |
| |
| ;; CHECK: (func $null-call-ref-effect (type $0) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $effect) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $null-call-ref-effect (result i32) |
| (call_ref $sig (call $effect) (ref.null nofunc)) |
| ) |
| |
| ;; CHECK: (func $shared-call-ref (type $5) (param $0 (ref (shared i31))) (result i32) |
| ;; CHECK-NEXT: (call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shared-call-ref (param (ref $shared-sig)) (result i32) |
| (call_ref $shared-sig (i32.const 42) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $shared-unreachable-call-ref (type $0) (result i32) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $shared-unreachable-call-ref (result i32) |
| (call_ref $shared-sig (i32.const 0) (unreachable)) |
| ) |
| |
| ;; CHECK: (func $shared-unreachable-call-ref-effect (type $0) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $effect) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $shared-unreachable-call-ref-effect (result i32) |
| (call_ref $shared-sig (call $effect) (unreachable)) |
| ) |
| |
| ;; CHECK: (func $shared-null-call-ref (type $0) (result i32) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $shared-null-call-ref (result i32) |
| (call_ref $shared-sig (i32.const 0) (ref.null (shared nofunc))) |
| ) |
| |
| ;; CHECK: (func $shared-null-call-ref-effect (type $0) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $effect) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $shared-null-call-ref-effect (result i32) |
| (call_ref $shared-sig (call $effect) (ref.null (shared nofunc))) |
| ) |
| |
| ;; CHECK: (func $return-call-ref (type $4) (param $0 (ref (shared i31))) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (return_call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $return-call-ref (param (ref $sig) i32) (result i32) |
| (return_call_ref $sig (local.get 1) (local.get 0)) |
| ) |
| |
| ;; call_indirect lowering |
| ;; CHECK: (func $call-indirect (type $6) (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (table.get $t |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $call-indirect (param i32 i32) (result i32) |
| (call_indirect $t (type $sig) (local.get 0) (local.get 1)) |
| ) |
| |
| ;; Unreachable call_indirect lowering. |
| ;; CHECK: (func $unreachable-call-indirect (type $0) (result i32) |
| ;; CHECK-NEXT: (call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (table.get $t |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unreachable-call-indirect (result i32) |
| (call_indirect $t (type $sig) (i32.const 0) (unreachable)) |
| ) |
| |
| ;; call_indirect lowering of shared function. |
| ;; CHECK: (func $shared-call-indirect (type $shared-sig) (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (table.get $t-shared |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shared-call-indirect (param i32) (result i32) |
| (call_indirect $t-shared (type $shared-sig) (i32.const 42) (local.get 0)) |
| ) |
| |
| ;; unreachable call_indirect |
| ;; CHECK: (func $unreachable-param-call-indirect (type $shared-sig) (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (call_indirect $funcs (type $shared-sig) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (table.get $t |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unreachable-param-call-indirect (param i32) (result i32) |
| (call_indirect $t (type $sig) (unreachable) (local.get 0)) |
| ) |
| ) |
| |
| ;; Test lowering of ref.test and ref.cast. |
| (module |
| (type $sig (func (param i32) (result i32))) |
| ;; CHECK: (type $shared-sig (func (param i32) (result i32))) |
| (type $shared-sig (shared (func (param i32) (result i32)))) |
| ;; CHECK: (type $1 (func (param (ref null (shared i31))) (result i32))) |
| |
| ;; CHECK: (type $2 (func (param (ref null (shared i31))) (result (ref null (shared i31))))) |
| |
| ;; CHECK: (type $struct (shared (struct (field i32)))) |
| (type $struct (struct (field i32))) |
| |
| ;; ref.test of funcref |
| ;; CHECK: (type $4 (func (param (ref null (shared i31))) (result (ref (shared i31))))) |
| |
| ;; CHECK: (type $5 (func (param (ref (shared i31))) (result i32))) |
| |
| ;; CHECK: (type $6 (func (result i32))) |
| |
| ;; CHECK: (type $7 (func (param (ref null (shared i31))) (result (ref (shared none))))) |
| |
| ;; CHECK: (type $8 (func (param (ref null (shared i31))) (result (ref null (shared none))))) |
| |
| ;; CHECK: (type $9 (func (param (ref (shared i31))) (result (ref (shared i31))))) |
| |
| ;; CHECK: (type $10 (func (result (ref null (shared i31))))) |
| |
| ;; CHECK: (type $11 (func (param (ref null $struct)) (result i32))) |
| |
| ;; CHECK: (type $12 (func (param (ref null $struct)) (result (ref null $struct)))) |
| |
| ;; CHECK: (table $funcs 0 0 funcref) |
| |
| ;; CHECK: (elem $funcs (i32.const 0)) |
| |
| ;; CHECK: (func $ref-test-func (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-func (param funcref) (result i32) |
| (ref.test (ref func) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-funcref (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-funcref (param funcref) (result i32) |
| (ref.test (ref null func) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-nofunc (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-nofunc (param funcref) (result i32) |
| (ref.test (ref nofunc) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-null-nofunc (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-null-nofunc (param funcref) (result i32) |
| (ref.test (ref null nofunc) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-func (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-func (param (ref null (shared func))) (result i32) |
| (ref.test (ref (shared func)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-funcref (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-funcref (param (ref null (shared func))) (result i32) |
| (ref.test (ref null (shared func)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-nofunc (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-nofunc (param (ref null (shared func))) (result i32) |
| (ref.test (ref (shared nofunc)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-null-shared-nofunc (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-null-shared-nofunc (param (ref null (shared func))) (result i32) |
| (ref.test (ref null (shared nofunc)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-no-nulls (type $5) (param $0 (ref (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-no-nulls (param (ref func)) (result i32) |
| (ref.test (ref $sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-non-nullable (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-non-nullable (param funcref) (result i32) |
| (ref.test (ref $sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-nullable (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.test (ref null $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-nullable (param funcref) (result i32) |
| (ref.test (ref null $sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-nullable-exact (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.test (ref null (exact $shared-sig)) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-nullable-exact (param funcref) (result i32) |
| (ref.test (ref null (exact $sig)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-no-nulls (type $5) (param $0 (ref (shared i31))) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-no-nulls (param (ref (shared func))) (result i32) |
| (ref.test (ref $shared-sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-non-nullable (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-non-nullable (param (ref null (shared func))) (result i32) |
| (ref.test (ref $shared-sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-nullable (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.test (ref null $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-nullable (param (ref null (shared func))) (result i32) |
| (ref.test (ref null $shared-sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-test-shared-nullable-exact (type $1) (param $0 (ref null (shared i31))) (result i32) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.test (ref null (exact $shared-sig)) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-shared-nullable-exact (param (ref null (shared func))) (result i32) |
| (ref.test (ref null (exact $shared-sig)) (local.get 0)) |
| ) |
| |
| |
| ;; ref.test with null input |
| ;; CHECK: (func $ref-test-null-input (type $6) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null (shared none)) |
| ;; CHECK-NEXT: (ref.null (shared none)) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-null-input (result i32) |
| (ref.test (ref null $sig) (ref.null nofunc)) |
| ) |
| |
| ;; ref.test with unreachable input |
| ;; CHECK: (func $ref-test-unreachable-input (type $6) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null $shared-sig) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-unreachable-input (result i32) |
| (ref.test (ref null $sig) (unreachable)) |
| ) |
| |
| ;; ref.test of non-function type. |
| ;; CHECK: (func $ref-test-non-func (type $11) (param $0 (ref null $struct)) (result i32) |
| ;; CHECK-NEXT: (ref.test (ref null $struct) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-test-non-func (param (ref null $struct)) (result i32) |
| ;; This should not be changed. |
| (ref.test (ref null $struct) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-func (type $4) (param $0 (ref null (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.cast (ref (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-func (param funcref) (result (ref func)) |
| (ref.cast (ref func) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-funcref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.cast (ref null (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-funcref (param funcref) (result (ref null func)) |
| (ref.cast (ref null func) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-nofunc (type $7) (param $0 (ref null (shared i31))) (result (ref (shared none))) |
| ;; CHECK-NEXT: (ref.cast (ref (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-nofunc (param funcref) (result (ref nofunc)) |
| (ref.cast (ref nofunc) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-null-nofunc (type $8) (param $0 (ref null (shared i31))) (result (ref null (shared none))) |
| ;; CHECK-NEXT: (ref.cast (ref null (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-null-nofunc (param funcref) (result (ref null nofunc)) |
| (ref.cast (ref null nofunc) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-func (type $4) (param $0 (ref null (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.cast (ref (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-func (param (ref null (shared func))) (result (ref (shared func))) |
| (ref.cast (ref (shared func)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-funcref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.cast (ref null (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-funcref (param (ref null (shared func))) (result (ref null (shared func))) |
| (ref.cast (ref null (shared func)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-nofunc (type $7) (param $0 (ref null (shared i31))) (result (ref (shared none))) |
| ;; CHECK-NEXT: (ref.cast (ref (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-nofunc (param (ref null (shared func))) (result (ref (shared nofunc))) |
| (ref.cast (ref (shared nofunc)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-null-shared-nofunc (type $8) (param $0 (ref null (shared i31))) (result (ref null (shared none))) |
| ;; CHECK-NEXT: (ref.cast (ref null (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-null-shared-nofunc (param (ref null (shared func))) (result (ref null (shared nofunc))) |
| (ref.cast (ref null (shared nofunc)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-no-nulls (type $9) (param $0 (ref (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (ref.as_non_null |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-no-nulls (param (ref func)) (result (ref $sig)) |
| (ref.cast (ref $sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-non-nullable (type $4) (param $0 (ref null (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (ref.as_non_null |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-non-nullable (param funcref) (result (ref $sig)) |
| (ref.cast (ref $sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-nullable (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref null $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-nullable (param funcref) (result (ref null $sig)) |
| (ref.cast (ref null $sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-nullable-exact (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref null (exact $shared-sig)) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-nullable-exact (param funcref) (result (ref null (exact $sig))) |
| (ref.cast (ref null (exact $sig)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-no-nulls (type $9) (param $0 (ref (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (ref.as_non_null |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-no-nulls (param (ref (shared func))) (result (ref $shared-sig)) |
| (ref.cast (ref $shared-sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-non-nullable (type $4) (param $0 (ref null (shared i31))) (result (ref (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (ref.as_non_null |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-non-nullable (param (ref null (shared func))) (result (ref $shared-sig)) |
| (ref.cast (ref $shared-sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-nullable (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref null $shared-sig) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-nullable (param (ref null (shared func))) (result (ref null $shared-sig)) |
| (ref.cast (ref null $shared-sig) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-shared-nullable-exact (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (local $1 (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (if (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.test (ref null (exact $shared-sig)) |
| ;; CHECK-NEXT: (table.get $funcs |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-shared-nullable-exact (param (ref null (shared func))) (result (ref null $shared-sig)) |
| (ref.cast (ref null (exact $shared-sig)) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-null-input (type $10) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (ref.cast (ref null (shared none)) |
| ;; CHECK-NEXT: (ref.null (shared none)) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-null-input (result (ref null $sig)) |
| (ref.cast (ref null $sig) (ref.null nofunc)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-unreachable-input (type $10) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (block ;; (replaces unreachable RefCast we can't emit) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-unreachable-input (result (ref null $sig)) |
| (ref.cast (ref null $sig) (unreachable)) |
| ) |
| |
| ;; CHECK: (func $ref-cast-non-func (type $12) (param $0 (ref null $struct)) (result (ref null $struct)) |
| ;; CHECK-NEXT: (ref.cast (ref null $struct) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ref-cast-non-func (param (ref null $struct)) (result (ref null $struct)) |
| ;; This should not be changed. |
| (ref.cast (ref null $struct) (local.get 0)) |
| ) |
| |
| ;; CHECK: (func $br-on-cast-funcref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (block $label (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (br_on_cast $label (ref null (shared i31)) (ref null (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $br-on-cast-funcref (param funcref) (result funcref) |
| (block $label (result funcref) |
| (br_on_cast $label funcref funcref (local.get 0)) |
| ) |
| ) |
| |
| ;; CHECK: (func $br-on-cast-fail-funcref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (block $label (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (br_on_cast_fail $label (ref null (shared i31)) (ref null (shared i31)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $br-on-cast-fail-funcref (param funcref) (result funcref) |
| (block $label (result funcref) |
| (br_on_cast_fail $label funcref funcref (local.get 0)) |
| ) |
| ) |
| |
| ;; CHECK: (func $br-on-cast-nullfuncref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (block $label (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (br_on_cast $label (ref null (shared i31)) (ref null (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $br-on-cast-nullfuncref (param funcref) (result funcref) |
| (block $label (result funcref) |
| (br_on_cast $label funcref nullfuncref (local.get 0)) |
| ) |
| ) |
| |
| ;; CHECK: (func $br-on-cast-fail-nullfuncref (type $2) (param $0 (ref null (shared i31))) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (block $label (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (br_on_cast_fail $label (ref null (shared i31)) (ref null (shared none)) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $br-on-cast-fail-nullfuncref (param funcref) (result funcref) |
| (block $label (result funcref) |
| (br_on_cast_fail $label funcref nullfuncref (local.get 0)) |
| ) |
| ) |
| |
| ;; TODO: other br_on_cast{_fail} lowering |
| ) |
| |
| (module |
| (type $sig (func (param i32) (result i32))) |
| |
| ;; Test that types in if, loop, result |
| |
| ;; Test that function types in globals, tables, element segments, and tags are updated. |
| ;; CHECK: (type $0 (func (param (ref null (shared i31))))) |
| |
| ;; CHECK: (type $1 (func (param i32) (result (ref null (shared i31))))) |
| |
| ;; CHECK: (global $g (ref null (shared i31)) (ref.null (shared none))) |
| (global $g (ref null $sig) (ref.null $sig)) |
| ;; CHECK: (table $t 1 1 (ref null (shared i31)) (ref.null (shared none))) |
| (table $t 1 1 (ref null $sig) (ref.null $sig)) |
| ;; CHECK: (elem $e (ref null (shared i31)) (item (ref.null (shared none)))) |
| (elem $e (ref null $sig) (ref.null $sig)) |
| ;; CHECK: (tag $tag (type $0) (param (ref null (shared i31)))) |
| (tag $tag (param (ref null $sig))) |
| |
| ;; CHECK: (func $control-types (type $1) (param $0 i32) (result (ref null (shared i31))) |
| ;; CHECK-NEXT: (if (result (ref null (shared none))) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (ref.null (shared none)) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (ref.null (shared none)) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $control-types (param i32) (result (ref null $sig)) |
| (if (result (ref null $sig)) (local.get 0) |
| (then (ref.null $sig)) |
| (else (ref.null $sig)) |
| ) |
| ) |
| ) |
| |
| (module |
| ;; Name collisions with the "funcs" table and "funcs" elements segment are handled correctly. |
| ;; CHECK: (type $f (func)) |
| (type $f (func)) |
| ;; CHECK: (table $funcs 1 1 (ref null (shared i31))) |
| (table $funcs 1 1 funcref) |
| ;; CHECK: (table $funcs_1 1 1 funcref) |
| |
| ;; CHECK: (elem $funcs (table $funcs) (i32.const 0) (ref null (shared i31)) (item (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ))) |
| (elem $funcs (table $funcs) (i32.const 0) func $target) |
| ;; CHECK: (elem $funcs_1 (table $funcs_1) (i32.const 0) func $target) |
| |
| ;; CHECK: (func $target (type $f) |
| ;; CHECK-NEXT: ) |
| (func $target (type $f)) |
| |
| ;; CHECK: (func $name-collision (type $f) |
| ;; CHECK-NEXT: (call_indirect $funcs_1 (type $f) |
| ;; CHECK-NEXT: (i31.get_u |
| ;; CHECK-NEXT: (ref.i31_shared |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $name-collision |
| (call_ref $f (ref.func $target)) |
| ) |
| ) |
| |
| (module |
| ;; We want public types to be updated as well. |
| (type $sig (func)) |
| ;; CHECK: (import "" "" (global $g-funcref (ref null (shared i31)))) |
| (import "" "" (global $g-funcref funcref)) |
| ;; CHECK: (import "" "" (global $g-sig (ref null (shared i31)))) |
| (import "" "" (global $g-sig (ref null $sig))) |
| ) |