summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/lit/binary/annotated-array-len.test2
-rw-r--r--test/lit/gc-eh.wast16
-rw-r--r--test/lit/gc-read-write-effects.wast15
-rw-r--r--test/lit/heap-types.wast43
-rw-r--r--test/lit/isorecursive-good.wast1
-rw-r--r--test/lit/nominal-bad.wast29
-rw-r--r--test/lit/nominal-good.wast52
-rw-r--r--test/lit/parse-bad-supertype.wast2
-rw-r--r--test/lit/parse-double-unreachable.wast2
-rw-r--r--test/lit/parse-nominal-types-extends.wast50
-rw-r--r--test/lit/parse-nominal-types.wast50
-rw-r--r--test/lit/passes/abstract-type-refining.wast206
-rw-r--r--test/lit/passes/cfp.wast71
-rw-r--r--test/lit/subtype-chain.wast (renamed from test/lit/nominal-chain.wast)12
-rw-r--r--test/lit/subtypes.wast72
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)
+ )
+)