| ;; 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) |
| ) |
| ) |
| ) |
| ) |