| ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. |
| |
| ;; Check that exact casts are only added when custom descriptors are enabled. |
| |
| ;; RUN: foreach %s %t wasm-opt -all --gufa-cast-all -S -o - \ |
| ;; RUN: | filecheck %s |
| |
| ;; RUN: foreach %s %t wasm-opt -all --disable-custom-descriptors --gufa-cast-all -S -o - \ |
| ;; RUN: | filecheck %s --check-prefix=NO_CD |
| |
| (module |
| ;; CHECK: (type $foo (struct)) |
| ;; NO_CD: (type $foo (struct)) |
| (type $foo (struct)) |
| |
| ;; CHECK: (import "" "" (global $g (ref (exact $foo)))) |
| ;; NO_CD: (import "" "" (global $g (ref (exact $foo)))) |
| (import "" "" (global $g (ref (exact $foo)))) |
| |
| ;; CHECK: (func $callee (type $1) (result (ref $foo)) |
| ;; CHECK-NEXT: (global.get $g) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $callee (type $1) (result (ref $foo)) |
| ;; NO_CD-NEXT: (global.get $g) |
| ;; NO_CD-NEXT: ) |
| (func $callee (result (ref $foo)) |
| (global.get $g) |
| ) |
| |
| ;; CHECK: (func $caller (type $2) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result (ref (exact $foo))) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.cast (ref (exact $foo)) |
| ;; CHECK-NEXT: (call $callee) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (global.get $g) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $caller (type $2) |
| ;; NO_CD-NEXT: (drop |
| ;; NO_CD-NEXT: (block (result (ref (exact $foo))) |
| ;; NO_CD-NEXT: (drop |
| ;; NO_CD-NEXT: (call $callee) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: (global.get $g) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $caller |
| (drop |
| (call $callee) |
| ) |
| ) |
| ) |
| |
| (module |
| ;; CHECK: (type $foo (struct)) |
| ;; NO_CD: (type $foo (struct)) |
| (type $foo (struct)) |
| |
| ;; CHECK: (import "" "a" (global $exact-a (ref (exact $foo)))) |
| ;; NO_CD: (import "" "a" (global $exact-a (ref (exact $foo)))) |
| (import "" "a" (global $exact-a (ref (exact $foo)))) |
| ;; CHECK: (import "" "b" (global $exact-b (ref (exact $foo)))) |
| ;; NO_CD: (import "" "b" (global $exact-b (ref (exact $foo)))) |
| (import "" "b" (global $exact-b (ref (exact $foo)))) |
| |
| ;; CHECK: (global $g (mut (ref $foo)) (global.get $exact-a)) |
| ;; NO_CD: (global $g (mut (ref $foo)) (global.get $exact-a)) |
| (global $g (mut (ref $foo)) (global.get $exact-a)) |
| |
| ;; CHECK: (func $set (type $1) |
| ;; CHECK-NEXT: (global.set $g |
| ;; CHECK-NEXT: (global.get $exact-b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $set (type $1) |
| ;; NO_CD-NEXT: (global.set $g |
| ;; NO_CD-NEXT: (global.get $exact-b) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $set |
| ;; $g can now hold two different exact $foo references. |
| (global.set $g |
| (global.get $exact-b) |
| ) |
| ) |
| |
| ;; CHECK: (func $get (type $2) (result (ref $foo)) |
| ;; CHECK-NEXT: (ref.cast (ref (exact $foo)) |
| ;; CHECK-NEXT: (ref.cast (ref (exact $foo)) |
| ;; CHECK-NEXT: (global.get $g) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $get (type $2) (result (ref $foo)) |
| ;; NO_CD-NEXT: (ref.cast (ref $foo) |
| ;; NO_CD-NEXT: (global.get $g) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $get (result (ref $foo)) |
| ;; We can only refine this cast target to be exact if custom descriptors are |
| ;; allowed. |
| (ref.cast (ref $foo) |
| (global.get $g) |
| ) |
| ) |
| ) |
| |
| (module |
| ;; CHECK: (type $foo (struct (field i32))) |
| ;; NO_CD: (type $foo (struct (field i32))) |
| (type $foo (struct (field i32))) |
| |
| ;; CHECK: (import "" "" (global $exact (ref (exact $foo)))) |
| ;; NO_CD: (import "" "" (global $exact (ref (exact $foo)))) |
| (import "" "" (global $exact (ref (exact $foo)))) |
| |
| ;; CHECK: (func $get (type $1) (result i32) |
| ;; CHECK-NEXT: (struct.get $foo 0 |
| ;; CHECK-NEXT: (select (result (ref null (exact $foo))) |
| ;; CHECK-NEXT: (global.get $exact) |
| ;; CHECK-NEXT: (ref.null none) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $get (type $1) (result i32) |
| ;; NO_CD-NEXT: (struct.get $foo 0 |
| ;; NO_CD-NEXT: (select (result (ref null (exact $foo))) |
| ;; NO_CD-NEXT: (global.get $exact) |
| ;; NO_CD-NEXT: (ref.null none) |
| ;; NO_CD-NEXT: (i32.const 0) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $get (result i32) |
| ;; Regression test for a bug where exactness was not preserved when combining |
| ;; nullness into cone types, resulting in a later assertion failure on the |
| ;; StructGet. |
| (struct.get $foo 0 |
| (select (result (ref null (exact $foo))) |
| (global.get $exact) |
| (ref.null none) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| |
| (module |
| ;; CHECK: (type $super (sub (struct))) |
| ;; NO_CD: (type $super (sub (struct))) |
| (type $super (sub (struct))) |
| (type $sub (sub $super (struct))) |
| |
| ;; CHECK: (import "" "a" (global $exact-a (ref (exact $super)))) |
| ;; NO_CD: (import "" "a" (global $exact-a (ref (exact $super)))) |
| (import "" "a" (global $exact-a (ref (exact $super)))) |
| ;; CHECK: (import "" "b" (global $exact-b (ref (exact $super)))) |
| ;; NO_CD: (import "" "b" (global $exact-b (ref (exact $super)))) |
| (import "" "b" (global $exact-b (ref (exact $super)))) |
| ;; CHECK: (import "" "x" (global $x i32)) |
| ;; NO_CD: (import "" "x" (global $x i32)) |
| (import "" "x" (global $x i32)) |
| |
| ;; CHECK: (func $get-exact (type $1) (result (ref $super)) |
| ;; CHECK-NEXT: (select (result (ref (exact $super))) |
| ;; CHECK-NEXT: (global.get $exact-a) |
| ;; CHECK-NEXT: (global.get $exact-b) |
| ;; CHECK-NEXT: (global.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $get-exact (type $1) (result (ref $super)) |
| ;; NO_CD-NEXT: (select (result (ref (exact $super))) |
| ;; NO_CD-NEXT: (global.get $exact-a) |
| ;; NO_CD-NEXT: (global.get $exact-b) |
| ;; NO_CD-NEXT: (global.get $x) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $get-exact (result (ref $super)) |
| (select (result (ref (exact $super))) |
| (global.get $exact-a) |
| (global.get $exact-b) |
| (global.get $x) |
| ) |
| ) |
| |
| ;; CHECK: (func $cast-sub (type $2) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.cast (ref (exact $super)) |
| ;; CHECK-NEXT: (call $get-exact) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $cast-sub (type $2) |
| ;; NO_CD-NEXT: (drop |
| ;; NO_CD-NEXT: (block |
| ;; NO_CD-NEXT: (drop |
| ;; NO_CD-NEXT: (call $get-exact) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: (unreachable) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $cast-sub |
| (drop |
| ;; We should be able to infer that this cast will not succeed and insert an |
| ;; unreachable after it. |
| (ref.cast (ref $sub) |
| (call $get-exact) |
| ) |
| ) |
| ) |
| ) |
| |
| (module |
| ;; CHECK: (type $foo (sub (struct (field i32)))) |
| ;; NO_CD: (type $foo (sub (struct (field i32)))) |
| (type $foo (sub (struct (field i32)))) |
| |
| ;; CHECK: (import "" "" (global $null-exact (ref null (exact $foo)))) |
| ;; NO_CD: (import "" "" (global $null-exact (ref null (exact $foo)))) |
| (import "" "" (global $null-exact (ref null (exact $foo)))) |
| |
| ;; CHECK: (func $as-non-null (type $1) (result i32) |
| ;; CHECK-NEXT: (struct.get $foo 0 |
| ;; CHECK-NEXT: (ref.as_non_null |
| ;; CHECK-NEXT: (global.get $null-exact) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; NO_CD: (func $as-non-null (type $1) (result i32) |
| ;; NO_CD-NEXT: (struct.get $foo 0 |
| ;; NO_CD-NEXT: (ref.as_non_null |
| ;; NO_CD-NEXT: (global.get $null-exact) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| ;; NO_CD-NEXT: ) |
| (func $as-non-null (result i32) |
| (struct.get $foo 0 |
| ;; Regression test for an assertion failure when the intersection here |
| ;; dropped exactness as well as nullness. |
| (ref.as_non_null |
| (global.get $null-exact) |
| ) |
| ) |
| ) |
| ) |