blob: c443322259607e84bc6320c95a9f888a7115043b [file] [edit]
;; 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)))
)