blob: 151f9e9d32bda74fbd4e3b182067ac8ca603dc86 [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s -all --optimize-instructions -S -o - | filecheck %s
;; RUN: wasm-opt %s -all --optimize-instructions -tnh -S -o - | filecheck %s --check-prefix=NTRAP
(module
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $struct (sub (descriptor $desc) (struct)))
;; NTRAP: (rec
;; NTRAP-NEXT: (type $struct (sub (descriptor $desc) (struct)))
(type $struct (sub (descriptor $desc) (struct)))
;; CHECK: (type $desc (sub (describes $struct) (struct)))
;; NTRAP: (type $desc (sub (describes $struct) (struct)))
(type $desc (sub (describes $struct) (struct)))
)
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $sub (sub $struct (descriptor $sub.desc) (struct)))
;; NTRAP: (rec
;; NTRAP-NEXT: (type $sub (sub $struct (descriptor $sub.desc) (struct)))
(type $sub (sub $struct (descriptor $sub.desc) (struct)))
;; CHECK: (type $sub.desc (sub $desc (describes $sub) (struct)))
;; NTRAP: (type $sub.desc (sub $desc (describes $sub) (struct)))
(type $sub.desc (sub $desc (describes $sub) (struct)))
)
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $struct-i32 (descriptor $struct-i32.desc) (struct (field i32)))
;; NTRAP: (rec
;; NTRAP-NEXT: (type $struct-i32 (descriptor $struct-i32.desc) (struct (field i32)))
(type $struct-i32 (descriptor $struct-i32.desc) (struct (field i32)))
;; CHECK: (type $struct-i32.desc (describes $struct-i32) (struct))
;; NTRAP: (type $struct-i32.desc (describes $struct-i32) (struct))
(type $struct-i32.desc (describes $struct-i32) (struct))
)
;; CHECK: (import "" "" (func $effect (type $4)))
;; NTRAP: (import "" "" (func $effect (type $4)))
(import "" "" (func $effect))
;; CHECK: (func $trap-null-desc (type $10) (result (ref (exact $struct)))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; NTRAP: (func $trap-null-desc (type $10) (result (ref (exact $struct)))
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
(func $trap-null-desc (result (ref (exact $struct)))
(struct.new_desc $struct
(ref.null none)
)
)
;; CHECK: (func $trap-null-desc-fallthrough (type $10) (result (ref (exact $struct)))
;; CHECK-NEXT: (local $desc (ref null (exact $desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $desc
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; NTRAP: (func $trap-null-desc-fallthrough (type $10) (result (ref (exact $struct)))
;; NTRAP-NEXT: (local $desc (ref null (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (local.tee $desc
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
(func $trap-null-desc-fallthrough (result (ref (exact $struct)))
(local $desc (ref null (exact $desc)))
(struct.new_desc $struct
(local.tee $desc
(ref.null none)
)
)
)
;; CHECK: (func $nonnull-cast-desc-eq (type $19) (param $desc (ref null (exact $desc))) (result (ref (exact $struct)))
;; CHECK-NEXT: (struct.new_default_desc $struct
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $nonnull-cast-desc-eq (type $19) (param $desc (ref null (exact $desc))) (result (ref (exact $struct)))
;; NTRAP-NEXT: (struct.new_default_desc $struct
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $nonnull-cast-desc-eq (param $desc (ref null (exact $desc))) (result (ref (exact $struct)))
(struct.new_desc $struct
(ref.as_non_null
(local.get $desc)
)
)
)
;; Test that when we optimize a struct.new to a struct.new_default, we drop
;; the field operands but keep the descriptor.
;; CHECK: (func $new-default-keep-desc (type $11) (result anyref)
;; CHECK-NEXT: (struct.new_default_desc $struct-i32
;; CHECK-NEXT: (block (result (ref (exact $struct-i32.desc)))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (struct.new_default $struct-i32.desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $new-default-keep-desc (type $11) (result anyref)
;; NTRAP-NEXT: (struct.new_default_desc $struct-i32
;; NTRAP-NEXT: (block (result (ref (exact $struct-i32.desc)))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (struct.new_default $struct-i32.desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $new-default-keep-desc (result anyref)
(struct.new_desc $struct-i32
(i32.const 0)
(block (result (ref (exact $struct-i32.desc)))
;; This would cause the descriptor to be dropped if it were dropped with
;; the other children.
(call $effect)
(struct.new_default $struct-i32.desc)
)
)
)
;; CHECK: (func $cast-desc-eq-null-desc (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-null-desc (type $4)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-null-desc
(drop
(ref.cast_desc_eq (ref (exact $struct))
(struct.new_desc $struct
(struct.new $desc)
)
(ref.null none)
)
)
)
;; CHECK: (func $cast-desc-eq-no-glb (type $9) (param $nn-sub (ref $sub)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (local.get $nn-sub)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-no-glb (type $9) (param $nn-sub (ref $sub)) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (local.get $nn-sub)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-no-glb (param $nn-sub (ref $sub)) (param $desc (ref $desc))
(drop
;; We cannot improve the cast target heap type, but we can improve the
;; nullability. With traps-never-happen we can optimize fully.
(ref.cast_desc_eq (ref null $struct)
(local.get $nn-sub)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-improve-nullability (type $20) (param $nn-any (ref any)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (local.get $nn-any)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-improve-nullability (type $20) (param $nn-any (ref any)) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $struct)
;; NTRAP-NEXT: (local.get $nn-any)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-improve-nullability (param $nn-any (ref any)) (param $desc (ref $desc))
(drop
;; Like above, but the ref isn't a subtype of the cast type. We can still
;; improve the nullability.
(ref.cast_desc_eq (ref null $struct)
(local.get $nn-any)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-only-improve-nullability (type $8) (param $any anyref) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (local.get $any)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-only-improve-nullability (type $8) (param $any anyref) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $struct)
;; NTRAP-NEXT: (local.get $any)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-only-improve-nullability (param $any anyref) (param $desc (ref $desc))
(drop
;; Now the cast target is already non-nullable. We shouldn't make it
;; nullable.
(ref.cast_desc_eq (ref $struct)
(local.get $any)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-unrelated-type (type $12) (param $struct (ref $struct)) (param $desc-i32 (ref (exact $struct-i32.desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-unrelated-type (type $12) (param $struct (ref $struct)) (param $desc-i32 (ref (exact $struct-i32.desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-unrelated-type (param $struct (ref $struct)) (param $desc-i32 (ref (exact $struct-i32.desc)))
(drop
;; We know this cast will fail so we can optimize.
(ref.cast_desc_eq (ref (exact $struct-i32))
(local.get $struct)
(local.get $desc-i32)
)
)
)
;; CHECK: (func $cast-desc-eq-unrelated-type-effects (type $12) (param $struct (ref $struct)) (param $desc-i32 (ref (exact $struct-i32.desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result (ref $struct))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result (ref (exact $struct-i32.desc)))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc-i32)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-unrelated-type-effects (type $12) (param $struct (ref $struct)) (param $desc-i32 (ref (exact $struct-i32.desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $struct))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $struct)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref (exact $struct-i32.desc)))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc-i32)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-unrelated-type-effects (param $struct (ref $struct)) (param $desc-i32 (ref (exact $struct-i32.desc)))
(drop
;; As above, but now with effects we need to keep.
(ref.cast_desc_eq (ref (exact $struct-i32))
(block (result (ref $struct))
(call $effect)
(local.get $struct)
)
(block (result (ref (exact $struct-i32.desc)))
(call $effect)
(local.get $desc-i32)
)
)
)
)
;; CHECK: (func $cast-desc-eq-unrelated-type-nullable (type $13) (param $struct-i32 (ref null $struct-i32)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref null $struct)
;; CHECK-NEXT: (local.get $struct-i32)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-unrelated-type-nullable (type $13) (param $struct-i32 (ref null $struct-i32)) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-unrelated-type-nullable (param $struct-i32 (ref null $struct-i32)) (param $desc (ref $desc))
(drop
;; Same as above, but now we allow nulls. We can optimize with traps-never-happen.
(ref.cast_desc_eq (ref null $struct)
(local.get $struct-i32)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-unrelated-type-nullable-effects (type $13) (param $struct-i32 (ref null $struct-i32)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref null $struct)
;; CHECK-NEXT: (block (result (ref null $struct-i32))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $struct-i32)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref $desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-unrelated-type-nullable-effects (type $13) (param $struct-i32 (ref null $struct-i32)) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref null $struct-i32))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $struct-i32)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-unrelated-type-nullable-effects (param $struct-i32 (ref null $struct-i32)) (param $desc (ref $desc))
(drop
;; Same as above, but now with effects we cannot drop.
(ref.cast_desc_eq (ref null $struct)
(block (result (ref null $struct-i32))
(call $effect)
(local.get $struct-i32)
)
(block (result (ref $desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-wrong-desc (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref (exact $struct))
;; CHECK-NEXT: (struct.new_default_desc $struct
;; CHECK-NEXT: (struct.new_default $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: (struct.new_default $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-wrong-desc (type $4)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref (exact $struct)))
;; NTRAP-NEXT: (struct.new_default_desc $struct
;; NTRAP-NEXT: (struct.new_default $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-wrong-desc
(drop
;; With traps-never-happen we assume the cast will succeed and optimize it
;; out, even even though it would actually fail.
;; TODO: We could see that the descriptor used in the allocation and the
;; descriptor used in the cast are different and optimize without TNH.
(ref.cast_desc_eq (ref (exact $struct))
(struct.new_desc $struct
(struct.new $desc)
)
(struct.new $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-wrong-desc-effects (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref (exact $struct))
;; CHECK-NEXT: (block (result (ref (exact $struct)))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (struct.new_default_desc $struct
;; CHECK-NEXT: (struct.new_default $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref (exact $desc)))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (struct.new_default $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-wrong-desc-effects (type $4)
;; NTRAP-NEXT: (local $0 (ref (exact $struct)))
;; NTRAP-NEXT: (local $1 (ref (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref (exact $struct)))
;; NTRAP-NEXT: (local.set $0
;; NTRAP-NEXT: (block (result (ref (exact $struct)))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (struct.new_default_desc $struct
;; NTRAP-NEXT: (struct.new_default $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.set $1
;; NTRAP-NEXT: (block (result (ref (exact $desc)))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (struct.new_default $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $0)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-wrong-desc-effects
(drop
;; Same, but with effects.
(ref.cast_desc_eq (ref (exact $struct))
(block (result (ref (exact $struct)))
(call $effect)
(struct.new_desc $struct
(struct.new $desc)
)
)
(block (result (ref (exact $desc)))
(call $effect)
(struct.new $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-weaker-nondesc-child (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $sub)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-weaker-nondesc-child (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $sub)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-weaker-nondesc-child (param $ref anyref) (param $desc (ref $sub.desc))
(drop
;; Optimize out the weaker child cast.
(ref.cast_desc_eq (ref $sub)
(ref.cast (ref any)
(local.get $ref)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-weaker-nondesc-child-effects (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $sub)
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref $sub.desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-weaker-nondesc-child-effects (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $sub)
;; NTRAP-NEXT: (ref.as_non_null
;; NTRAP-NEXT: (block (result anyref)
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (block (result (ref $sub.desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-weaker-nondesc-child-effects (param $ref anyref) (param $desc (ref $sub.desc))
(drop
;; Same, but with effects. Due to ordering, we cannot remove the inner
;; cast (which turns into ref.as_non_null).
(ref.cast_desc_eq (ref $sub)
(ref.cast (ref any)
(block (result anyref)
(call $effect)
(local.get $ref)
)
)
(block (result (ref $sub.desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-nondesc-child (type $8) (param $ref anyref) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (ref.cast (ref $sub)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-nondesc-child (type $8) (param $ref anyref) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (ref.cast (ref $sub)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-nondesc-child (param $ref anyref) (param $desc (ref $desc))
(drop
;; With traps-never-happen we assume the outer cast will succeed and
;; optimize it out.
(ref.cast_desc_eq (ref $struct)
(ref.cast (ref $sub)
(local.get $ref)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-nondesc-child-effects (type $8) (param $ref anyref) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (ref.cast (ref $sub)
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref $desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-nondesc-child-effects (type $8) (param $ref anyref) (param $desc (ref $desc))
;; NTRAP-NEXT: (local $2 (ref $sub))
;; NTRAP-NEXT: (local $3 (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (local.set $2
;; NTRAP-NEXT: (ref.cast (ref $sub)
;; NTRAP-NEXT: (block (result anyref)
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.set $3
;; NTRAP-NEXT: (block (result (ref $desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $2)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-nondesc-child-effects (param $ref anyref) (param $desc (ref $desc))
(drop
;; Same, but with effects.
(ref.cast_desc_eq (ref $struct)
(ref.cast (ref $sub)
(block (result anyref)
(call $effect)
(local.get $ref)
)
)
(block (result (ref $desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-weaker-desc-child (type $15) (param $ref anyref) (param $desc (ref $desc)) (param $sub.desc (ref $sub.desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $sub)
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $sub.desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-weaker-desc-child (type $15) (param $ref anyref) (param $desc (ref $desc)) (param $sub.desc (ref $sub.desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $sub)
;; NTRAP-NEXT: (block (result anyref)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $sub.desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-weaker-desc-child (param $ref anyref) (param $desc (ref $desc)) (param $sub.desc (ref $sub.desc))
(drop
;; We can only optimize the weaker child cast with traps-never-happen
;; because it might fail due to an incorrect descriptor even when the
;; parent cast would succeed.
(ref.cast_desc_eq (ref $sub)
(ref.cast_desc_eq (ref $struct)
(local.get $ref)
(local.get $desc)
)
(local.get $sub.desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-desc-child (type $15) (param $ref anyref) (param $desc (ref $desc)) (param $sub.desc (ref $sub.desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (ref.cast_desc_eq (ref $sub)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $sub.desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-desc-child (type $15) (param $ref anyref) (param $desc (ref $desc)) (param $sub.desc (ref $sub.desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $sub)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: (local.get $sub.desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-desc-child (param $ref anyref) (param $desc (ref $desc)) (param $sub.desc (ref $sub.desc))
(drop
;; Like above, but now when we optimize with traps-never-happen we replace
;; the parent with the child.
(ref.cast_desc_eq (ref $struct)
(ref.cast_desc_eq (ref $sub)
(local.get $ref)
(local.get $sub.desc)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough (type $9) (param $sub (ref $sub)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (local.get $sub)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough (type $9) (param $sub (ref $sub)) (param $desc (ref $desc))
;; NTRAP-NEXT: (local $2 (ref $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (local.tee $2
;; NTRAP-NEXT: (local.get $sub)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $2)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough (param $sub (ref $sub)) (param $desc (ref $desc))
(drop
;; Like above, but now the stronger child is deeper. We use a tee to
;; extract it.
(ref.cast_desc_eq (ref $struct)
(block (result anyref)
(local.get $sub)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-effects (type $9) (param $sub (ref $sub)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $sub)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref $desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-effects (type $9) (param $sub (ref $sub)) (param $desc (ref $desc))
;; NTRAP-NEXT: (local $2 (ref $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.tee $2
;; NTRAP-NEXT: (local.get $sub)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $2)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-effects (param $sub (ref $sub)) (param $desc (ref $desc))
(drop
;; Like above, but now with effects we cannot drop.
(ref.cast_desc_eq (ref $struct)
(block (result anyref)
(call $effect)
(local.get $sub)
)
(block (result (ref $desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-nullck (type $16) (param $sub (ref null $sub)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (local.get $sub)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-nullck (type $16) (param $sub (ref null $sub)) (param $desc (ref $desc))
;; NTRAP-NEXT: (local $2 (ref null $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref null $sub))
;; NTRAP-NEXT: (local.tee $2
;; NTRAP-NEXT: (local.get $sub)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (ref.as_non_null
;; NTRAP-NEXT: (local.get $2)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-nullck (param $sub (ref null $sub)) (param $desc (ref $desc))
(drop
;; Like above, but now we also need a null check.
(ref.cast_desc_eq (ref $struct)
(block (result anyref)
(local.get $sub)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-nullck-effects (type $16) (param $sub (ref null $sub)) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $sub)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref $desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-nullck-effects (type $16) (param $sub (ref null $sub)) (param $desc (ref $desc))
;; NTRAP-NEXT: (local $2 (ref null $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $sub))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref null $sub))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.tee $2
;; NTRAP-NEXT: (local.get $sub)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (ref.as_non_null
;; NTRAP-NEXT: (local.get $2)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-nullck-effects (param $sub (ref null $sub)) (param $desc (ref $desc))
(drop
;; Like above, but now with effects.
(ref.cast_desc_eq (ref $struct)
(block (result anyref)
(call $effect)
(local.get $sub)
)
(block (result (ref $desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-null (type $17) (param $null nullref) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-null (type $17) (param $null nullref) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-null (param $null nullref) (param $desc (ref $desc))
(drop
;; Like above, but now the value itself is null and we allow it.
(ref.cast_desc_eq (ref null $struct)
(block (result anyref)
(local.get $null)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-null-effects (type $17) (param $null nullref) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $null)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result (ref $desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-null-effects (type $17) (param $null nullref) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $null)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-null-effects (param $null nullref) (param $desc (ref $desc))
(drop
;; Like above, but now with effects.
(ref.cast_desc_eq (ref null $struct)
(block (result anyref)
(call $effect)
(local.get $null)
)
(block (result (ref $desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-null-null-desc (type $18) (param $null nullref) (param $desc (ref null $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-null-null-desc (type $18) (param $null nullref) (param $desc (ref null $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-null-null-desc (param $null nullref) (param $desc (ref null $desc))
(drop
;; Like above, but now the descriptor is nullable so we have to add a null
;; check to it.
(ref.cast_desc_eq (ref null $struct)
(block (result anyref)
(local.get $null)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-stronger-fallthrough-null-null-desc-effects (type $18) (param $null nullref) (param $desc (ref null $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $null)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (block (result (ref null $desc))
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-stronger-fallthrough-null-null-desc-effects (type $18) (param $null nullref) (param $desc (ref null $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $null)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref null $desc))
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-stronger-fallthrough-null-null-desc-effects (param $null nullref) (param $desc (ref null $desc))
(drop
;; Like above, but now with effects.
(ref.cast_desc_eq (ref null $struct)
(block (result anyref)
(call $effect)
(local.get $null)
)
(block (result (ref null $desc))
(call $effect)
(local.get $desc)
)
)
)
)
;; CHECK: (func $cast-desc-eq-ref-as-non-null (type $8) (param $any anyref) (param $desc (ref $desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (local.get $any)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-ref-as-non-null (type $8) (param $any anyref) (param $desc (ref $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref $struct)
;; NTRAP-NEXT: (local.get $any)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-ref-as-non-null (param $any anyref) (param $desc (ref $desc))
(drop
;; We can roll the ref.as_non_null into the cast.
(ref.cast_desc_eq (ref null $struct)
(ref.as_non_null
(local.get $any)
)
(local.get $desc)
)
)
)
;; CHECK: (func $cast-desc-eq-unreachable-desc (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-unreachable-desc (type $4)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-unreachable-desc
(drop
;; Don't crash on an unreachable descriptor.
(ref.cast_desc_eq (ref $struct)
(ref.null none)
(unreachable)
)
)
)
;; CHECK: (func $ref.get_desc-skip-non-null (type $21) (param $ref (ref null $struct)) (result anyref)
;; CHECK-NEXT: (ref.get_desc $struct
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $ref.get_desc-skip-non-null (type $21) (param $ref (ref null $struct)) (result anyref)
;; NTRAP-NEXT: (ref.get_desc $struct
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $ref.get_desc-skip-non-null (param $ref (ref null $struct)) (result anyref)
(ref.get_desc $struct
;; This is not needed, as the parent traps on null anyhow.
(ref.as_non_null
(local.get $ref)
)
)
)
;; CHECK: (func $ref.get_desc-trap-on-null (type $11) (result anyref)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; NTRAP: (func $ref.get_desc-trap-on-null (type $11) (result anyref)
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
(func $ref.get_desc-trap-on-null (result anyref)
;; This traps.
(ref.get_desc $struct
(block (result (ref null $struct))
(ref.null $struct)
)
)
)
;; CHECK: (func $cast-desc-eq-skip-non-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref (exact $struct))
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-eq-skip-non-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref (exact $struct))
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $cast-desc-eq-skip-non-null (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
(drop
(ref.cast_desc_eq (ref (exact $struct))
(local.get $ref)
;; This is not needed, as the parent traps on null anyhow.
(ref.as_non_null
(local.get $desc)
)
)
)
)
;; CHECK: (func $br_on_cast_desc_eq-skip-non-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l (result (ref null $struct))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (br_on_cast_desc_eq $l (ref null $struct) (ref null (exact $struct))
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $br_on_cast_desc_eq-skip-non-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block $l (result (ref null $struct))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (br_on_cast_desc_eq $l (ref null $struct) (ref null (exact $struct))
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (return)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $br_on_cast_desc_eq-skip-non-null (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
(drop
(block $l (result (ref null $struct))
(br_on_cast_desc_eq $l anyref (ref null $struct)
(local.get $ref)
;; This is not needed, as the parent traps on null anyhow.
(ref.as_non_null
(local.get $desc)
)
)
(return)
)
)
)
;; CHECK: (func $br_on_cast_desc_eq_fail-skip-non-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l (result (ref null $struct))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (br_on_cast_desc_eq_fail $l (ref null $struct) (ref null (exact $struct))
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $br_on_cast_desc_eq_fail-skip-non-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block $l (result (ref null $struct))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (br_on_cast_desc_eq_fail $l (ref null $struct) (ref null (exact $struct))
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: (local.get $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (return)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $br_on_cast_desc_eq_fail-skip-non-null (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
(drop
(block $l (result (ref null $struct))
(br_on_cast_desc_eq_fail $l anyref (ref null $struct)
(local.get $ref)
;; This is not needed, as the parent traps on null anyhow.
(ref.as_non_null
(local.get $desc)
)
)
(return)
)
)
)
;; CHECK: (func $br_on_cast_desc_eq-trap-on-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l (result (ref none))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $br_on_cast_desc_eq-trap-on-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block $l (result (ref none))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (return)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $br_on_cast_desc_eq-trap-on-null (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
(drop
(block $l (result (ref null $struct))
(br_on_cast_desc_eq $l anyref (ref null $struct)
(local.get $ref)
(block (result (ref null $desc))
(ref.null $desc)
)
)
(return)
)
)
)
;; CHECK: (func $br_on_cast_desc_eq_fail-trap-on-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l (result (ref null $struct))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $br_on_cast_desc_eq_fail-trap-on-null (type $7) (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block $l (result (ref null $struct))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result nullref)
;; NTRAP-NEXT: (ref.null none)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (return)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $br_on_cast_desc_eq_fail-trap-on-null (param $ref (ref null $struct)) (param $desc (ref null (exact $desc)))
(drop
(block $l (result (ref null $struct))
(br_on_cast_desc_eq_fail $l anyref (ref null $struct)
(local.get $ref)
(block (result (ref null $desc))
(ref.null $desc)
)
)
(return)
)
)
)
;; CHECK: (func $ref.cast_desc_eq-ref.as_non_null (type $4)
;; CHECK-NEXT: (local $null (ref null $struct))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref $struct)
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (local.get $null)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref null $desc))
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc_eq (ref (exact $struct))
;; CHECK-NEXT: (local.get $null)
;; CHECK-NEXT: (struct.new_default $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $ref.cast_desc_eq-ref.as_non_null (type $4)
;; NTRAP-NEXT: (local $null (ref null $struct))
;; NTRAP-NEXT: (local $1 (ref $struct))
;; NTRAP-NEXT: (local $2 (ref null $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $struct))
;; NTRAP-NEXT: (local.set $1
;; NTRAP-NEXT: (ref.as_non_null
;; NTRAP-NEXT: (local.get $null)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.set $2
;; NTRAP-NEXT: (block (result (ref null $desc))
;; NTRAP-NEXT: (return)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $1)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc_eq (ref (exact $struct))
;; NTRAP-NEXT: (local.get $null)
;; NTRAP-NEXT: (struct.new_default $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $ref.cast_desc_eq-ref.as_non_null
(local $null (ref null $struct))
;; We read a null local and cast it to non-null, trapping. The ref.cast_desc_eq
;; would trap on null anyhow, so it seems we can remove the ref.as_non_null,
;; but doing so would allow us to reach the block, which returns *before* the
;; ref.cast_desc_eq would trap.
(drop
(ref.cast_desc_eq (ref $struct)
(ref.as_non_null
(local.get $null)
)
;; Hide the return in a block, otherwise we'd skip unreachable code.
(block (result (ref null $desc))
(return)
)
)
)
;; As above, but without dangerous effects: we can remove the
;; ref.as_non_null.
(drop
(ref.cast_desc_eq (ref $struct)
(ref.as_non_null
(local.get $null)
)
(struct.new $desc)
)
)
)
)