diff options
-rw-r--r-- | test/lit/binary/annotated-array-len.test | 2 | ||||
-rw-r--r-- | test/lit/gc-eh.wast | 16 | ||||
-rw-r--r-- | test/lit/gc-read-write-effects.wast | 15 | ||||
-rw-r--r-- | test/lit/heap-types.wast | 43 | ||||
-rw-r--r-- | test/lit/isorecursive-good.wast | 1 | ||||
-rw-r--r-- | test/lit/nominal-bad.wast | 29 | ||||
-rw-r--r-- | test/lit/nominal-good.wast | 52 | ||||
-rw-r--r-- | test/lit/parse-bad-supertype.wast | 2 | ||||
-rw-r--r-- | test/lit/parse-double-unreachable.wast | 2 | ||||
-rw-r--r-- | test/lit/parse-nominal-types-extends.wast | 50 | ||||
-rw-r--r-- | test/lit/parse-nominal-types.wast | 50 | ||||
-rw-r--r-- | test/lit/passes/abstract-type-refining.wast | 206 | ||||
-rw-r--r-- | test/lit/passes/cfp.wast | 71 | ||||
-rw-r--r-- | test/lit/subtype-chain.wast (renamed from test/lit/nominal-chain.wast) | 12 | ||||
-rw-r--r-- | test/lit/subtypes.wast | 72 |
15 files changed, 286 insertions, 337 deletions
diff --git a/test/lit/binary/annotated-array-len.test b/test/lit/binary/annotated-array-len.test index 62e51fcf3..9cf6eecbe 100644 --- a/test/lit/binary/annotated-array-len.test +++ b/test/lit/binary/annotated-array-len.test @@ -3,7 +3,7 @@ ;; Test the we can properly parse the annotated array.len format that we no ;; longer emit. -;; RUN: wasm-dis %s.wasm -all --nominal | filecheck %s +;; RUN: wasm-dis %s.wasm -all | filecheck %s ;; CHECK: (type $none_=>_i32 (func (result i32))) diff --git a/test/lit/gc-eh.wast b/test/lit/gc-eh.wast index df2f3b416..b037086ca 100644 --- a/test/lit/gc-eh.wast +++ b/test/lit/gc-eh.wast @@ -3,17 +3,14 @@ ;; Check that pops of GC types work correctly. ;; RUN: wasm-opt -all %s -S -o - | filecheck %s -;; RUN: wasm-opt -all --nominal %s -S -o - | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $A (struct (field (mut i32)))) - ;; NOMNL: (type $A (struct (field (mut i32)))) (type $A (struct (field (mut i32)) )) ;; CHECK: (tag $tagA (param (ref $A))) - ;; NOMNL: (tag $tagA (param (ref $A))) (tag $tagA (param (ref $A))) ;; CHECK: (func $foo (type $none_=>_ref?|$A|) (result (ref null $A)) @@ -29,19 +26,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $none_=>_ref?|$A|) (result (ref null $A)) - ;; NOMNL-NEXT: (try $try - ;; NOMNL-NEXT: (do - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (catch $tagA - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (pop (ref $A)) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null none) - ;; NOMNL-NEXT: ) (func $foo (result (ref null $A)) (try (do diff --git a/test/lit/gc-read-write-effects.wast b/test/lit/gc-read-write-effects.wast index da869e9b9..e05335554 100644 --- a/test/lit/gc-read-write-effects.wast +++ b/test/lit/gc-read-write-effects.wast @@ -4,11 +4,9 @@ ;; struct field. ;; RUN: wasm-opt -all --simplify-locals %s -S -o - | filecheck %s -;; RUN: wasm-opt -all --simplify-locals %s --nominal -S -o - | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $A (struct (field (mut i32)))) - ;; NOMNL: (type $A (struct (field (mut i32)))) (type $A (struct (field (mut i32)) )) @@ -37,19 +35,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $ref?|$A|_=>_i32) (param $x (ref null $A)) (result i32) - ;; NOMNL-NEXT: (local $y i32) - ;; NOMNL-NEXT: (local.set $y - ;; NOMNL-NEXT: (struct.get $A 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $A 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 10) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) (func $test (export "test") (param $x (ref null $A)) (result i32) (local $y i32) (local.set $y diff --git a/test/lit/heap-types.wast b/test/lit/heap-types.wast index 9dc8f11a8..9f0e43602 100644 --- a/test/lit/heap-types.wast +++ b/test/lit/heap-types.wast @@ -6,12 +6,10 @@ ;; type, and hit an error during --roundtrip. ;; RUN: foreach %s %t wasm-opt -all --roundtrip -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt -all --roundtrip -S --nominal -o - | filecheck %s --check-prefix NOMNL (module ;; CHECK: (type $struct.A (struct (field i32))) (type $struct.A (struct i32)) - ;; NOMNL: (type $struct.B (struct (field i32))) (type $struct.B (struct i32)) ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop @@ -20,13 +18,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test $struct.B - ;; NOMNL-NEXT: (ref.null none) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) (func $test (drop (ref.test $struct.B (ref.null $struct.A)) @@ -37,7 +28,6 @@ (module ;; CHECK: (type $struct.A (struct (field i32))) (type $struct.A (struct i32)) - ;; NOMNL: (type $struct.B (struct (field i32))) (type $struct.B (struct i32)) ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop @@ -46,13 +36,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast null $struct.B - ;; NOMNL-NEXT: (ref.null none) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) (func $test (drop (ref.cast null $struct.B (ref.null $struct.A)) @@ -62,18 +45,12 @@ (module ;; CHECK: (type $struct.A (struct (field i32))) - ;; NOMNL: (type $struct.A (struct (field i32))) (type $struct.A (struct i32)) ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.new_default $struct.A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.new_default $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) (func $test (drop (struct.new_default $struct.A) @@ -83,7 +60,6 @@ (module ;; CHECK: (type $vector (array (mut f64))) - ;; NOMNL: (type $vector (array (mut f64))) (type $vector (array (mut f64))) ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop @@ -93,14 +69,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (array.new $vector - ;; NOMNL-NEXT: (f64.const 3.14159) - ;; NOMNL-NEXT: (i32.const 3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) (func $test (drop (array.new $vector @@ -113,7 +81,6 @@ (module ;; CHECK: (type $vector (array (mut f64))) - ;; NOMNL: (type $vector (array (mut f64))) (type $vector (array (mut f64))) ;; CHECK: (func $test (type $none_=>_none) ;; CHECK-NEXT: (drop @@ -125,16 +92,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (array.new_fixed $vector - ;; NOMNL-NEXT: (f64.const 1) - ;; NOMNL-NEXT: (f64.const 2) - ;; NOMNL-NEXT: (f64.const 4) - ;; NOMNL-NEXT: (f64.const 8) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) (func $test (drop (array.new_fixed $vector diff --git a/test/lit/isorecursive-good.wast b/test/lit/isorecursive-good.wast index 0f5cbddf0..53631c92b 100644 --- a/test/lit/isorecursive-good.wast +++ b/test/lit/isorecursive-good.wast @@ -2,7 +2,6 @@ ;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s --check-prefix HYBRID ;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s --check-prefix HYBRID -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s --check-prefix NOMINAL (module (rec diff --git a/test/lit/nominal-bad.wast b/test/lit/nominal-bad.wast deleted file mode 100644 index 43a1eea95..000000000 --- a/test/lit/nominal-bad.wast +++ /dev/null @@ -1,29 +0,0 @@ -;; RUN: not wasm-opt %s -all --nominal -S -o - 2>&1 | filecheck %s - -;; CHECK: [wasm-validator error in function make-super-struct] function body type must match -;; CHECK: [wasm-validator error in function make-super-array] function body type must match - -(module - - (type $sub-struct (struct i32 i64)) - (type $super-struct (struct i32)) - - (type $sub-array (array (ref $sub-struct))) - (type $super-array (array (ref $super-struct))) - - (func $make-sub-struct (result (ref $sub-struct)) - (unreachable) - ) - - (func $make-super-struct (result (ref $super-struct)) - (call $make-sub-struct) - ) - - (func $make-sub-array (result (ref $sub-array)) - (unreachable) - ) - - (func $make-super-array (result (ref $super-array)) - (call $make-sub-array) - ) -) diff --git a/test/lit/nominal-good.wast b/test/lit/nominal-good.wast deleted file mode 100644 index 76863d637..000000000 --- a/test/lit/nominal-good.wast +++ /dev/null @@ -1,52 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s --check-prefix CHECK -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s --check-prefix CHECK -;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s - -;; Note that --hybrid and --nominal have the same output, so they share the CHECK prefix. - -(module - - ;; CHECK: (type $super-struct (struct (field i32))) - (type $super-struct (struct i32)) - - ;; CHECK: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) - (type $sub-struct (struct_subtype i32 i64 $super-struct)) - - ;; CHECK: (type $super-array (array (ref $super-struct))) - (type $super-array (array (ref $super-struct))) - - ;; CHECK: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - - ;; TODO: signature types as well, once functions store their HeapTypes. - - ;; CHECK: (func $make-super-struct (type $none_=>_ref|$super-struct|) (result (ref $super-struct)) - ;; CHECK-NEXT: (call $make-sub-struct) - ;; CHECK-NEXT: ) - (func $make-super-struct (result (ref $super-struct)) - (call $make-sub-struct) - ) - - ;; CHECK: (func $make-sub-struct (type $none_=>_ref|$sub-struct|) (result (ref $sub-struct)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $make-sub-struct (result (ref $sub-struct)) - (unreachable) - ) - - ;; CHECK: (func $make-super-array (type $none_=>_ref|$super-array|) (result (ref $super-array)) - ;; CHECK-NEXT: (call $make-sub-array) - ;; CHECK-NEXT: ) - (func $make-super-array (result (ref $super-array)) - (call $make-sub-array) - ) - - ;; CHECK: (func $make-sub-array (type $none_=>_ref|$sub-array|) (result (ref $sub-array)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $make-sub-array (result (ref $sub-array)) - (unreachable) - ) -) diff --git a/test/lit/parse-bad-supertype.wast b/test/lit/parse-bad-supertype.wast index 3a50efecf..cbb53c675 100644 --- a/test/lit/parse-bad-supertype.wast +++ b/test/lit/parse-bad-supertype.wast @@ -1,6 +1,6 @@ ;; Test that an invalid supertype results in a useful error message -;; RUN: not wasm-opt %s -all --nominal 2>&1 | filecheck %s +;; RUN: not wasm-opt %s -all 2>&1 | filecheck %s ;; CHECK: Fatal: Invalid type: Heap type has an invalid supertype at type $sub (module diff --git a/test/lit/parse-double-unreachable.wast b/test/lit/parse-double-unreachable.wast index 333eb6fa9..2abdd2e5b 100644 --- a/test/lit/parse-double-unreachable.wast +++ b/test/lit/parse-double-unreachable.wast @@ -1,6 +1,6 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s ;; Regression test for a bug in which we could pop the expression stack past an ;; unreachable if we were already in unreachable parsing mode. diff --git a/test/lit/parse-nominal-types-extends.wast b/test/lit/parse-nominal-types-extends.wast index e7641937d..ade4f5e6b 100644 --- a/test/lit/parse-nominal-types-extends.wast +++ b/test/lit/parse-nominal-types-extends.wast @@ -1,62 +1,66 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; Test that new-style nominal types are parsed correctly. -;; TODO: Remove --nominal below once nominal types are parsed as nominal by default. -;; RUN: foreach %s %t wasm-opt --nominal -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --nominal -all --roundtrip -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt -all --roundtrip -S -o - | filecheck %s ;; void function type (module - (type $sub (func) (extends $super)) - ;; CHECK: (type $super (func)) (type $super (func)) - ;; CHECK: (global $g (ref null $super) (ref.null nofunc)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (func_subtype $super)) + (type $sub (func) (extends $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null nofunc)) + (global $g (ref null $sub) (ref.null nofunc)) ) ;; function type with params and results (module - (type $sub (func (param i32) (result i32)) (extends $super)) - ;; CHECK: (type $super (func (param i32) (result i32))) (type $super (func (param i32) (result i32))) - ;; CHECK: (global $g (ref null $super) (ref.null nofunc)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (func_subtype (param i32) (result i32) $super)) + (type $sub (func (param i32) (result i32)) (extends $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null nofunc)) + (global $g (ref null $sub) (ref.null nofunc)) ) ;; empty struct type (module - (type $sub (struct) (extends $super)) - ;; CHECK: (type $super (struct )) (type $super (struct)) - ;; CHECK: (global $g (ref null $super) (ref.null none)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (struct_subtype $super)) + (type $sub (struct) (extends $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null none)) + (global $g (ref null $sub) (ref.null none)) ) ;; struct type with fields (module - (type $sub (struct i32 (field i64)) (extends $super)) - ;; CHECK: (type $super (struct (field i32) (field i64))) (type $super (struct (field i32) i64)) - ;; CHECK: (global $g (ref null $super) (ref.null none)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (struct_subtype (field i32) (field i64) $super)) + (type $sub (struct i32 (field i64)) (extends $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null none)) + (global $g (ref null $sub) (ref.null none)) ) ;; array type (module - (type $sub (array i8) (extends $super)) - ;; CHECK: (type $super (array i8)) (type $super (array i8)) - ;; CHECK: (global $g (ref null $super) (ref.null none)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (array_subtype i8 $super)) + (type $sub (array i8) (extends $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null none)) + (global $g (ref null $sub) (ref.null none)) ) diff --git a/test/lit/parse-nominal-types.wast b/test/lit/parse-nominal-types.wast index 45f110a36..46b27bc58 100644 --- a/test/lit/parse-nominal-types.wast +++ b/test/lit/parse-nominal-types.wast @@ -1,62 +1,66 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; Test that new-style nominal types are parsed correctly. -;; TODO: Remove --nominal below once nominal types are parsed as nominal by default. -;; RUN: foreach %s %t wasm-opt --nominal -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --nominal -all --roundtrip -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt -all --roundtrip -S -o - | filecheck %s ;; void function type (module - (type $sub (func_subtype $super)) - ;; CHECK: (type $super (func)) (type $super (func_subtype func)) - ;; CHECK: (global $g (ref null $super) (ref.null nofunc)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (func_subtype $super)) + (type $sub (func_subtype $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null nofunc)) + (global $g (ref null $sub) (ref.null nofunc)) ) ;; function type with params and results (module - (type $sub (func_subtype (param i32) (result i32) $super)) - ;; CHECK: (type $super (func (param i32) (result i32))) (type $super (func_subtype (param i32) (result i32) func)) - ;; CHECK: (global $g (ref null $super) (ref.null nofunc)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (func_subtype (param i32) (result i32) $super)) + (type $sub (func_subtype (param i32) (result i32) $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null nofunc)) + (global $g (ref null $sub) (ref.null nofunc)) ) ;; empty struct type (module - (type $sub (struct_subtype $super)) - ;; CHECK: (type $super (struct )) (type $super (struct_subtype data)) - ;; CHECK: (global $g (ref null $super) (ref.null none)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (struct_subtype $super)) + (type $sub (struct_subtype $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null none)) + (global $g (ref null $sub) (ref.null none)) ) ;; struct type with fields (module - (type $sub (struct_subtype i32 (field i64) $super)) - ;; CHECK: (type $super (struct (field i32) (field i64))) (type $super (struct_subtype (field i32) i64 data)) - ;; CHECK: (global $g (ref null $super) (ref.null none)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (struct_subtype (field i32) (field i64) $super)) + (type $sub (struct_subtype i32 (field i64) $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null none)) + (global $g (ref null $sub) (ref.null none)) ) ;; array type (module - (type $sub (array_subtype i8 $super)) - ;; CHECK: (type $super (array i8)) (type $super (array_subtype i8 data)) - ;; CHECK: (global $g (ref null $super) (ref.null none)) - (global $g (ref null $super) (ref.null $sub)) + ;; CHECK: (type $sub (array_subtype i8 $super)) + (type $sub (array_subtype i8 $super)) + + ;; CHECK: (global $g (ref null $sub) (ref.null none)) + (global $g (ref null $sub) (ref.null none)) ) diff --git a/test/lit/passes/abstract-type-refining.wast b/test/lit/passes/abstract-type-refining.wast index f373acd87..5fffa7972 100644 --- a/test/lit/passes/abstract-type-refining.wast +++ b/test/lit/passes/abstract-type-refining.wast @@ -1,7 +1,7 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --abstract-type-refining --traps-never-happen -all --closed-world --nominal -S -o - | filecheck %s --check-prefix=YESTNH -;; RUN: foreach %s %t wasm-opt --abstract-type-refining -all --closed-world --nominal -S -o - | filecheck %s --check-prefix=NO_TNH +;; RUN: foreach %s %t wasm-opt --abstract-type-refining --remove-unused-types --traps-never-happen -all --closed-world -S -o - | filecheck %s --check-prefix=YESTNH +;; RUN: foreach %s %t wasm-opt --abstract-type-refining --remove-unused-types -all --closed-world -S -o - | filecheck %s --check-prefix=NO_TNH ;; Run in both TNH and non-TNH mode. @@ -11,32 +11,34 @@ ;; actually refer to a subtype of them (that has a struct.new). As a result, in ;; TNH mode $A and $D will also not be emitted in the output anymore. (module - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $none_=>_none (func)) - ;; NO_TNH: (type $A (struct )) + ;; NO_TNH: (type $A (struct )) (type $A (struct)) - ;; YESTNH: (type $B (struct )) - ;; NO_TNH: (type $B (struct_subtype $A)) - (type $B (struct_subtype $A)) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $none_=>_none (func)) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) + ;; YESTNH: (type $B (struct )) + ;; NO_TNH: (type $B (struct_subtype $A)) + (type $B (struct_subtype $A)) - ;; YESTNH: (type $C (struct_subtype $B)) - ;; NO_TNH: (type $C (struct_subtype $B)) + ;; YESTNH: (type $C (struct_subtype $B)) + ;; NO_TNH: (type $C (struct_subtype $B)) (type $C (struct_subtype $B)) - ;; NO_TNH: (type $D (struct_subtype $C)) + ;; NO_TNH: (type $D (struct_subtype $C)) (type $D (struct_subtype $C)) - ;; YESTNH: (type $E (struct_subtype $C)) - ;; NO_TNH: (type $E (struct_subtype $D)) + ;; YESTNH: (type $E (struct_subtype $C)) + ;; NO_TNH: (type $E (struct_subtype $D)) (type $E (struct_subtype $D)) - ;; YESTNH: (type $none_=>_none (func)) + ;; YESTNH: (type $anyref_=>_none (func (param anyref))) ;; YESTNH: (global $global anyref (struct.new_default $B)) - ;; NO_TNH: (type $none_=>_none (func)) + ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) ;; NO_TNH: (global $global anyref (struct.new_default $B)) (global $global anyref (struct.new $B)) @@ -275,21 +277,27 @@ ;; $A has two subtypes. As a result, we cannot optimize it. (module - ;; YESTNH: (type $A (struct )) - ;; NO_TNH: (type $A (struct )) - (type $A (struct)) + (rec + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $A (struct )) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $A (struct )) + (type $A (struct)) - ;; YESTNH: (type $B (struct_subtype $A)) - ;; NO_TNH: (type $B (struct_subtype $A)) - (type $B (struct_subtype $A)) + ;; YESTNH: (type $B1 (struct_subtype $A)) + + ;; YESTNH: (type $anyref_=>_none (func (param anyref))) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) + ;; YESTNH: (type $B (struct_subtype $A)) + ;; NO_TNH: (type $B1 (struct_subtype $A)) - ;; YESTNH: (type $B1 (struct_subtype $A)) - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) + ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) - ;; NO_TNH: (type $B1 (struct_subtype $A)) - (type $B1 (struct_subtype $A)) ;; this is a new type + ;; NO_TNH: (type $B (struct_subtype $A)) + (type $B (struct_subtype $A)) + + (type $B1 (struct_subtype $A)) ;; this is a new type + ) ;; YESTNH: (global $global anyref (struct.new_default $B)) ;; NO_TNH: (global $global anyref (struct.new_default $B)) @@ -367,24 +375,28 @@ ;; As above, but now $B is never created, so we can optimize casts of $A to ;; $B1. (module - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) - - ;; NO_TNH: (type $A (struct )) - (type $A (struct)) + (rec + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $A (struct )) + (type $A (struct)) - (type $B (struct_subtype $A)) + (type $B (struct_subtype $A)) - ;; YESTNH: (type $B1 (struct )) - ;; NO_TNH: (type $B1 (struct_subtype $A)) - (type $B1 (struct_subtype $A)) ;; this is a new type + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $B1 (struct )) + ;; NO_TNH: (type $B1 (struct_subtype $A)) + (type $B1 (struct_subtype $A)) ;; this is a new type + ) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) + ;; YESTNH: (type $anyref_=>_none (func (param anyref))) ;; YESTNH: (func $new (type $anyref_=>_none) (param $x anyref) ;; YESTNH-NEXT: (drop ;; YESTNH-NEXT: (struct.new_default $B1) ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) + ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) + ;; NO_TNH: (func $new (type $anyref_=>_none) (param $x anyref) ;; NO_TNH-NEXT: (drop ;; NO_TNH-NEXT: (struct.new_default $B1) @@ -451,25 +463,27 @@ ;; A chain, $A :> $B :> $C, where we can optimize $A all the way to $C. (module - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) - - ;; NO_TNH: (type $A (struct )) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $A (struct )) (type $A (struct)) - ;; NO_TNH: (type $B (struct_subtype $A)) + ;; NO_TNH: (type $B (struct_subtype $A)) (type $B (struct_subtype $A)) - ;; YESTNH: (type $C (struct )) - ;; NO_TNH: (type $C (struct_subtype $B)) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $C (struct )) + ;; NO_TNH: (type $C (struct_subtype $B)) (type $C (struct_subtype $B)) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) + ;; YESTNH: (type $anyref_=>_none (func (param anyref))) ;; YESTNH: (func $new (type $anyref_=>_none) (param $x anyref) ;; YESTNH-NEXT: (drop ;; YESTNH-NEXT: (struct.new_default $C) ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) + ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) + ;; NO_TNH: (func $new (type $anyref_=>_none) (param $x anyref) ;; NO_TNH-NEXT: (drop ;; NO_TNH-NEXT: (struct.new_default $C) @@ -537,17 +551,20 @@ ;; More testing for cases where no types or subtypes are created. No type is ;; created here. No type needs to be emitted in the output. (module - (type $A (struct)) + (rec + (type $A (struct)) - (type $B (struct_subtype $A)) + (type $B (struct_subtype $A)) - (type $C1 (struct_subtype $B)) + (type $C1 (struct_subtype $B)) - (type $C2 (struct_subtype $B)) + (type $C2 (struct_subtype $B)) + ) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $none_=>_none (func)) - ;; YESTNH: (type $none_=>_none (func)) + ;; YESTNH: (type $anyref_=>_none (func (param anyref))) ;; YESTNH: (func $ref.cast (type $anyref_=>_none) (param $x anyref) ;; YESTNH-NEXT: (drop @@ -571,9 +588,10 @@ ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $none_=>_none (func)) - ;; NO_TNH: (type $none_=>_none (func)) + ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) ;; NO_TNH: (func $ref.cast (type $anyref_=>_none) (param $x anyref) ;; NO_TNH-NEXT: (drop @@ -817,23 +835,27 @@ ;; As above, but now $C1 is created. (module - ;; NO_TNH: (type $A (struct )) - (type $A (struct)) + (rec + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $anyref_=>_none (func (param anyref))) - ;; NO_TNH: (type $B (struct_subtype $A)) - (type $B (struct_subtype $A)) + ;; NO_TNH: (type $A (struct )) + (type $A (struct)) - ;; YESTNH: (type $C1 (struct )) - ;; NO_TNH: (type $C1 (struct_subtype $B)) - (type $C1 (struct_subtype $B)) + ;; NO_TNH: (type $B (struct_subtype $A)) + (type $B (struct_subtype $A)) - (type $C2 (struct_subtype $B)) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $anyref_=>_none (func (param anyref))) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) + ;; YESTNH: (type $C1 (struct )) + ;; NO_TNH: (type $C1 (struct_subtype $B)) + (type $C1 (struct_subtype $B)) - ;; YESTNH: (global $global anyref (struct.new_default $C1)) - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) + (type $C2 (struct_subtype $B)) + ) + ;; YESTNH: (global $global anyref (struct.new_default $C1)) ;; NO_TNH: (global $global anyref (struct.new_default $C1)) (global $global anyref (struct.new $C1)) @@ -978,25 +1000,27 @@ ;; Function subtyping, which is a TODO - for now we do nothing. (module - ;; YESTNH: (type $A (func)) - ;; NO_TNH: (type $A (func)) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $A (func)) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $A (func)) (type $A (func)) - ;; YESTNH: (type $funcref_=>_none (func (param funcref))) - - ;; YESTNH: (type $B (func_subtype $A)) - ;; NO_TNH: (type $funcref_=>_none (func (param funcref))) - - ;; NO_TNH: (type $B (func_subtype $A)) + ;; YESTNH: (type $B (func_subtype $A)) + ;; NO_TNH: (type $B (func_subtype $A)) (type $B (func_subtype $A)) - ;; YESTNH: (type $C (func_subtype $B)) - ;; NO_TNH: (type $C (func_subtype $B)) + ;; YESTNH: (type $C (func_subtype $B)) + ;; NO_TNH: (type $C (func_subtype $B)) (type $C (func_subtype $B)) + ;; YESTNH: (type $funcref_=>_none (func (param funcref))) + ;; YESTNH: (func $A (type $A) ;; YESTNH-NEXT: (nop) ;; YESTNH-NEXT: ) + ;; NO_TNH: (type $funcref_=>_none (func (param funcref))) + ;; NO_TNH: (func $A (type $A) ;; NO_TNH-NEXT: (nop) ;; NO_TNH-NEXT: ) @@ -1074,16 +1098,20 @@ ;; NO_TNH: (type $A (func)) (type $A (func)) - ;; YESTNH: (type $B (func_subtype $A)) - ;; NO_TNH: (type $B (func_subtype $A)) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $funcref_=>_none (func (param funcref))) + + ;; YESTNH: (type $B (func_subtype $A)) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $funcref_=>_none (func (param funcref))) + + ;; NO_TNH: (type $B (func_subtype $A)) (type $B (func_subtype $A)) - ;; YESTNH: (type $C (func_subtype $B)) - ;; NO_TNH: (type $C (func_subtype $B)) + ;; YESTNH: (type $C (func_subtype $B)) + ;; NO_TNH: (type $C (func_subtype $B)) (type $C (func_subtype $B)) - ;; YESTNH: (type $funcref_=>_none (func (param funcref))) - ;; YESTNH: (elem declare func $A $C) ;; YESTNH: (export "A" (func $A)) @@ -1093,8 +1121,6 @@ ;; YESTNH-NEXT: (ref.func $A) ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) - ;; NO_TNH: (type $funcref_=>_none (func (param funcref))) - ;; NO_TNH: (elem declare func $A $C) ;; NO_TNH: (export "A" (func $A)) @@ -1184,26 +1210,28 @@ ;; Array subtyping, which is a TODO - for now we do nothing. (module - ;; YESTNH: (type $A (array (mut i32))) - ;; NO_TNH: (type $A (array (mut i32))) + ;; YESTNH: (rec + ;; YESTNH-NEXT: (type $anyref_=>_none (func (param anyref))) + + ;; YESTNH: (type $A (array (mut i32))) + ;; NO_TNH: (rec + ;; NO_TNH-NEXT: (type $anyref_=>_none (func (param anyref))) + + ;; NO_TNH: (type $A (array (mut i32))) (type $A (array (mut i32))) - ;; YESTNH: (type $B (array_subtype (mut i32) $A)) - ;; NO_TNH: (type $B (array_subtype (mut i32) $A)) + ;; YESTNH: (type $B (array_subtype (mut i32) $A)) + ;; NO_TNH: (type $B (array_subtype (mut i32) $A)) (type $B (array_subtype (mut i32) $A)) - ;; YESTNH: (type $C (array_subtype (mut i32) $B)) - ;; NO_TNH: (type $C (array_subtype (mut i32) $B)) + ;; YESTNH: (type $C (array_subtype (mut i32) $B)) + ;; NO_TNH: (type $C (array_subtype (mut i32) $B)) (type $C (array_subtype (mut i32) $B)) - ;; YESTNH: (type $anyref_=>_none (func (param anyref))) - ;; YESTNH: (global $A (ref $A) (array.new $A ;; YESTNH-NEXT: (i32.const 10) ;; YESTNH-NEXT: (i32.const 20) ;; YESTNH-NEXT: )) - ;; NO_TNH: (type $anyref_=>_none (func (param anyref))) - ;; NO_TNH: (global $A (ref $A) (array.new $A ;; NO_TNH-NEXT: (i32.const 10) ;; NO_TNH-NEXT: (i32.const 20) diff --git a/test/lit/passes/cfp.wast b/test/lit/passes/cfp.wast index 4647599e0..48b1210b7 100644 --- a/test/lit/passes/cfp.wast +++ b/test/lit/passes/cfp.wast @@ -1,5 +1,7 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --remove-unused-names --cfp -all -S -o - | filecheck %s + +;; RUN: foreach %s %t wasm-opt --remove-unused-names --cfp -all -S -o - | filecheck %s + ;; (remove-unused-names is added to test fallthrough values without a block ;; name getting in the way) @@ -454,10 +456,10 @@ ;; Test a function reference instead of a number. (module - ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) - ;; CHECK: (type $struct (struct (field funcref))) (type $struct (struct funcref)) + ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) + ;; CHECK: (elem declare func $test) ;; CHECK: (func $test (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) @@ -549,11 +551,11 @@ ;; CHECK: (type $struct (struct (field i32))) (type $struct (struct i32)) - ;; CHECK: (type $ref?|$substruct|_=>_none (func (param (ref null $substruct)))) - ;; CHECK: (type $substruct (struct_subtype (field i32) $struct)) (type $substruct (struct_subtype i32 $struct)) + ;; CHECK: (type $ref?|$substruct|_=>_none (func (param (ref null $substruct)))) + ;; CHECK: (func $create (type $none_=>_none) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.new $struct @@ -596,11 +598,11 @@ (type $struct (struct (mut i32))) ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) - ;; CHECK: (type $ref?|$substruct|_=>_none (func (param (ref null $substruct)))) - ;; CHECK: (type $substruct (struct_subtype (field (mut i32)) $struct)) (type $substruct (struct_subtype (mut i32) $struct)) + ;; CHECK: (type $ref?|$substruct|_=>_none (func (param (ref null $substruct)))) + ;; CHECK: (func $create (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.new $struct @@ -651,12 +653,11 @@ ;; CHECK: (type $none_=>_none (func)) ;; CHECK: (type $struct (struct (field i32))) + (type $struct (struct i32)) ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) (type $substruct (struct_subtype i32 f64 $struct)) - (type $struct (struct i32)) - ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) ;; CHECK: (func $create (type $none_=>_none) @@ -815,13 +816,13 @@ ;; shared between the types, but we only create the substruct with ;; one value, so we can optimize. (module + ;; CHECK: (type $struct (struct (field i32))) + (type $struct (struct i32)) ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) (type $substruct (struct_subtype i32 f64 $struct)) - (type $struct (struct i32)) - ;; CHECK: (type $none_=>_none (func)) ;; CHECK: (type $ref?|$substruct|_=>_none (func (param (ref null $substruct)))) @@ -939,16 +940,14 @@ ;; supertype but all the way as needed. (module ;; CHECK: (type $struct1 (struct (field i32))) + (type $struct1 (struct i32)) ;; CHECK: (type $struct2 (struct_subtype (field i32) (field f64) $struct1)) + (type $struct2 (struct_subtype i32 f64 $struct1)) ;; CHECK: (type $struct3 (struct_subtype (field i32) (field f64) (field anyref) $struct2)) (type $struct3 (struct_subtype i32 f64 anyref $struct2)) - (type $struct2 (struct_subtype i32 f64 $struct1)) - - (type $struct1 (struct i32)) - ;; CHECK: (type $none_=>_none (func)) ;; CHECK: (type $ref?|$struct1|_ref?|$struct2|_ref?|$struct3|_=>_none (func (param (ref null $struct1) (ref null $struct2) (ref null $struct3)))) @@ -1076,16 +1075,14 @@ ;; not the middle one. (module ;; CHECK: (type $struct1 (struct (field i32) (field i32))) + (type $struct1 (struct i32 i32)) ;; CHECK: (type $struct2 (struct_subtype (field i32) (field i32) (field f64) (field f64) $struct1)) + (type $struct2 (struct_subtype i32 i32 f64 f64 $struct1)) ;; CHECK: (type $struct3 (struct_subtype (field i32) (field i32) (field f64) (field f64) (field anyref) (field anyref) $struct2)) (type $struct3 (struct_subtype i32 i32 f64 f64 anyref anyref $struct2)) - (type $struct1 (struct i32 i32)) - - (type $struct2 (struct_subtype i32 i32 f64 f64 $struct1)) - ;; CHECK: (type $anyref_=>_none (func (param anyref))) ;; CHECK: (type $ref?|$struct1|_ref?|$struct2|_ref?|$struct3|_=>_none (func (param (ref null $struct1) (ref null $struct2) (ref null $struct3)))) @@ -1403,13 +1400,13 @@ ;; As above, but add not just a new of the middle class with a different value ;; but also a set. That prevents all optimizations. (module + ;; CHECK: (type $struct1 (struct (field (mut i32)))) + (type $struct1 (struct (mut i32))) ;; CHECK: (type $struct2 (struct_subtype (field (mut i32)) (field f64) $struct1)) (type $struct2 (struct_subtype (mut i32) f64 $struct1)) - (type $struct1 (struct (mut i32))) - ;; CHECK: (type $struct3 (struct_subtype (field (mut i32)) (field f64) (field anyref) $struct2)) (type $struct3 (struct_subtype (mut i32) f64 anyref $struct2)) @@ -1631,16 +1628,14 @@ ;; apply to it, preventing optimization. (module ;; CHECK: (type $A (struct (field (mut i32)))) + (type $A (struct (mut i32))) ;; CHECK: (type $B (struct_subtype (field (mut i32)) $A)) + (type $B (struct_subtype (mut i32) $A)) ;; CHECK: (type $C (struct_subtype (field (mut i32)) $B)) (type $C (struct_subtype (mut i32) $B)) - (type $A (struct (mut i32))) - - (type $B (struct_subtype (mut i32) $A)) - ;; CHECK: (type $none_=>_none (func)) ;; CHECK: (type $ref|$A|_=>_none (func (param (ref $A)))) @@ -1748,11 +1743,11 @@ (module ;; CHECK: (type $struct (struct (field (mut f32)) (field (mut i32)))) (type $struct (struct (mut f32) (mut i32))) - ;; CHECK: (type $ref?|$struct|_ref?|$other|_=>_none (func (param (ref null $struct) (ref null $other)))) - ;; CHECK: (type $other (struct (field (mut f64)) (field (mut i32)))) (type $other (struct (mut f64) (mut i32))) + ;; CHECK: (type $ref?|$struct|_ref?|$other|_=>_none (func (param (ref null $struct) (ref null $other)))) + ;; CHECK: (func $test (type $ref?|$struct|_ref?|$other|_=>_none) (param $struct (ref null $struct)) (param $other (ref null $other)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.new_default $struct) @@ -2064,11 +2059,10 @@ ;; Test a global type other than i32. Arrays of structs are a realistic case ;; as they are used to implement itables. - ;; CHECK: (type $itable (array (ref $vtable))) - ;; CHECK: (type $vtable (struct (field funcref))) (type $vtable (struct funcref)) + ;; CHECK: (type $itable (array (ref $vtable))) (type $itable (array (ref $vtable))) ;; CHECK: (type $object (struct (field $itable (ref $itable)))) @@ -2138,14 +2132,17 @@ ;; Test we handle packed fields properly. (module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $A_8 (struct (field i8))) - (type $A_8 (struct (field i8))) - ;; CHECK: (type $A_16 (struct (field i16))) - (type $A_16 (struct (field i16))) - ;; CHECK: (type $B_16 (struct (field i16))) - (type $B_16 (struct (field i16))) + (rec + ;; CHECK: (type $none_=>_none (func)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $A_8 (struct (field i8))) + (type $A_8 (struct (field i8))) + ;; CHECK: (type $A_16 (struct (field i16))) + (type $A_16 (struct (field i16))) + ;; CHECK: (type $B_16 (struct (field i16))) + (type $B_16 (struct (field i16))) + ) ;; CHECK: (import "a" "b" (global $g i32)) (import "a" "b" (global $g i32)) diff --git a/test/lit/nominal-chain.wast b/test/lit/subtype-chain.wast index 7a1b3c933..03d0ec81f 100644 --- a/test/lit/nominal-chain.wast +++ b/test/lit/subtype-chain.wast @@ -1,6 +1,6 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s +;; RUN: wasm-opt %s -all -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s ;; Check that intermediate types in subtype chains are also included in the ;; output module, even if there are no other references to those intermediate @@ -16,15 +16,15 @@ ;; CHECK: (type $twig (struct_subtype (field i32) (field i64) (field f32) $branch)) ;; CHECK: (type $leaf (struct_subtype (field i32) (field i64) (field f32) (field f64) $twig)) - (type $leaf (struct_subtype i32 i64 f32 f64 $twig)) + (type $root (struct)) - (type $twig (struct_subtype i32 i64 f32 $branch)) + (type $trunk (struct_subtype i32 $root)) (type $branch (struct_subtype i32 i64 $trunk)) - (type $trunk (struct_subtype i32 $root)) + (type $twig (struct_subtype i32 i64 f32 $branch)) - (type $root (struct)) + (type $leaf (struct_subtype i32 i64 f32 f64 $twig)) ;; CHECK: (func $make-root (type $ref|$leaf|_=>_ref?|$root|) (param $leaf (ref $leaf)) (result (ref null $root)) ;; CHECK-NEXT: (local.get $leaf) diff --git a/test/lit/subtypes.wast b/test/lit/subtypes.wast new file mode 100644 index 000000000..75618ab0a --- /dev/null +++ b/test/lit/subtypes.wast @@ -0,0 +1,72 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + +;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s + +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $super-struct (struct (field i32))) + (type $super-struct (struct i32)) + ;; CHECK: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) + (type $sub-struct (struct_subtype i32 i64 $super-struct)) + ) + + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $super-array (array (ref $super-struct))) + (type $super-array (array (ref $super-struct))) + ;; CHECK: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) + (type $sub-array (array_subtype (ref $sub-struct) $super-array)) + ) + + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $super-func (func (param (ref $sub-array)) (result (ref $super-array)))) + (type $super-func (func (param (ref $sub-array)) (result (ref $super-array)))) + ;; CHECK: (type $sub-func (func_subtype (param (ref $super-array)) (result (ref $sub-array)) $super-func)) + (type $sub-func (func_subtype (param (ref $super-array)) (result (ref $sub-array)) $super-func)) + ) + + ;; CHECK: (func $make-super-struct (type $none_=>_ref|$super-struct|) (result (ref $super-struct)) + ;; CHECK-NEXT: (call $make-sub-struct) + ;; CHECK-NEXT: ) + (func $make-super-struct (result (ref $super-struct)) + (call $make-sub-struct) + ) + + ;; CHECK: (func $make-sub-struct (type $none_=>_ref|$sub-struct|) (result (ref $sub-struct)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $make-sub-struct (result (ref $sub-struct)) + (unreachable) + ) + + ;; CHECK: (func $make-super-array (type $none_=>_ref|$super-array|) (result (ref $super-array)) + ;; CHECK-NEXT: (call $make-sub-array) + ;; CHECK-NEXT: ) + (func $make-super-array (result (ref $super-array)) + (call $make-sub-array) + ) + + ;; CHECK: (func $make-sub-array (type $none_=>_ref|$sub-array|) (result (ref $sub-array)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $make-sub-array (result (ref $sub-array)) + (unreachable) + ) + + ;; CHECK: (func $make-super-func (type $none_=>_ref|$super-func|) (result (ref $super-func)) + ;; CHECK-NEXT: (call $make-sub-func) + ;; CHECK-NEXT: ) + (func $make-super-func (result (ref $super-func)) + (call $make-sub-func) + ) + + ;; CHECK: (func $make-sub-func (type $none_=>_ref|$sub-func|) (result (ref $sub-func)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $make-sub-func (result (ref $sub-func)) + (unreachable) + ) +) |