summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2021-11-19 16:16:42 -0800
committerGitHub <noreply@github.com>2021-11-19 16:16:42 -0800
commitd532e3a4b02375fe85a2e81be336a181e6bdc10b (patch)
tree222e18bc63327c22b98c64e29a903a461d731c60 /test
parentbe672c057bcb39b27f34f4031eea747bd72161d2 (diff)
downloadbinaryen-d532e3a4b02375fe85a2e81be336a181e6bdc10b.tar.gz
binaryen-d532e3a4b02375fe85a2e81be336a181e6bdc10b.tar.bz2
binaryen-d532e3a4b02375fe85a2e81be336a181e6bdc10b.zip
Allow building basic HeapTypes in nominal mode (#4346)
As we work toward allowing nominal and structural types to coexist, any difference in how they can be built or used will be an inconvenient footgun that we will have to work around. In the spirit of reducing the differences between the type systems, allow TypeBuilder to construct basic HeapTypes in nominal mode just as it can in equirecursive mode. Although this change is a net increase in code complexity for not much benefit (wasm-opt never needs to build basic HeapTypes), it is also an incremental step toward getting rid of separate type system modes, so I expect it to simplify other PRs in the near future. This change also uncovered a bug in how the type fuzzer generated subtypes of basic HeapTypes. The generated subtypes did not necessarily have the intended `Kind`, which caused failures in nominal subtype validation in the fuzzer.
Diffstat (limited to 'test')
-rw-r--r--test/example/type-builder-nominal-new.cpp28
-rw-r--r--test/example/type-builder-nominal-new.txt2
-rw-r--r--test/example/type-builder-nominal.cpp35
-rw-r--r--test/example/type-builder-nominal.txt42
-rw-r--r--test/lit/fuzz-types/nominal.test43
5 files changed, 104 insertions, 46 deletions
diff --git a/test/example/type-builder-nominal-new.cpp b/test/example/type-builder-nominal-new.cpp
index d7fe83e5f..a8bef1eca 100644
--- a/test/example/type-builder-nominal-new.cpp
+++ b/test/example/type-builder-nominal-new.cpp
@@ -114,6 +114,33 @@ void test_canonicalization() {
assert(built[2] != built[3]);
}
+// Check that defined basic HeapTypes are handled correctly.
+void test_basic() {
+ std::cout << ";; Test basic\n";
+
+ TypeBuilder builder(6);
+ makeNominal(builder);
+
+ Type anyref = builder.getTempRefType(builder[4], Nullable);
+ Type i31ref = builder.getTempRefType(builder[5], NonNullable);
+
+ builder[0] = Signature(Type::anyref, Type::i31ref);
+ builder[1] = Signature(anyref, Type::i31ref);
+ builder[2] = Signature(Type::anyref, i31ref);
+ builder[3] = Signature(anyref, i31ref);
+ builder[4] = HeapType::any;
+ builder[5] = HeapType::i31;
+
+ std::vector<HeapType> built = builder.build();
+
+ assert(built[0].getSignature() == Signature(Type::anyref, Type::i31ref));
+ assert(built[1].getSignature() == built[0].getSignature());
+ assert(built[2].getSignature() == built[1].getSignature());
+ assert(built[3].getSignature() == built[2].getSignature());
+ assert(built[4] == HeapType::any);
+ assert(built[5] == HeapType::i31);
+}
+
void test_recursive() {
std::cout << ";; Test recursive types\n";
@@ -429,6 +456,7 @@ int main() {
for (size_t i = 0; i < 2; ++i) {
test_builder();
test_canonicalization();
+ test_basic();
test_recursive();
test_subtypes();
}
diff --git a/test/example/type-builder-nominal-new.txt b/test/example/type-builder-nominal-new.txt
index 036dd9374..6f0218e54 100644
--- a/test/example/type-builder-nominal-new.txt
+++ b/test/example/type-builder-nominal-new.txt
@@ -21,6 +21,7 @@ After building types:
(rtt 0 $array) => (rtt 0 (array (mut externref)))
;; Test canonicalization
+;; Test basic
;; Test recursive types
(func (result (ref null ...1)))
@@ -67,6 +68,7 @@ After building types:
(rtt 0 $array) => (rtt 0 (array (mut externref)))
;; Test canonicalization
+;; Test basic
;; Test recursive types
(func (result (ref null ...1)))
diff --git a/test/example/type-builder-nominal.cpp b/test/example/type-builder-nominal.cpp
index 1904bb7ee..5d3bcc17c 100644
--- a/test/example/type-builder-nominal.cpp
+++ b/test/example/type-builder-nominal.cpp
@@ -99,6 +99,32 @@ void test_canonicalization() {
assert(built[2] != built[3]);
}
+// Check that defined basic HeapTypes are handled correctly.
+void test_basic() {
+ std::cout << ";; Test basic\n";
+
+ TypeBuilder builder(6);
+
+ Type anyref = builder.getTempRefType(builder[4], Nullable);
+ Type i31ref = builder.getTempRefType(builder[5], NonNullable);
+
+ builder[0] = Signature(Type::anyref, Type::i31ref);
+ builder[1] = Signature(anyref, Type::i31ref);
+ builder[2] = Signature(Type::anyref, i31ref);
+ builder[3] = Signature(anyref, i31ref);
+ builder[4] = HeapType::any;
+ builder[5] = HeapType::i31;
+
+ std::vector<HeapType> built = builder.build();
+
+ assert(built[0].getSignature() == Signature(Type::anyref, Type::i31ref));
+ assert(built[1].getSignature() == built[0].getSignature());
+ assert(built[2].getSignature() == built[1].getSignature());
+ assert(built[3].getSignature() == built[2].getSignature());
+ assert(built[4] == HeapType::any);
+ assert(built[5] == HeapType::i31);
+}
+
// Check that signatures created with TypeBuilders are properly recorded as
// canonical.
void test_signatures(bool warm) {
@@ -106,14 +132,14 @@ void test_signatures(bool warm) {
TypeBuilder builder(2);
Type tempRef = builder.getTempRefType(builder[0], Nullable);
- builder[0] = Signature(Type::anyref, Type::i31ref);
+ builder[0] = Signature(Type::i31ref, Type::anyref);
builder[1] = Signature(tempRef, tempRef);
std::vector<HeapType> built = builder.build();
- HeapType small = Signature(Type::anyref, Type::i31ref);
+ HeapType small = Signature(Type::i31ref, Type::anyref);
HeapType big =
- Signature(Type(Signature(Type::anyref, Type::i31ref), Nullable),
- Type(Signature(Type::anyref, Type::i31ref), Nullable));
+ Signature(Type(Signature(Type::i31ref, Type::anyref), Nullable),
+ Type(Signature(Type::i31ref, Type::anyref), Nullable));
if (warm) {
assert(built[0] != small);
assert(built[1] != big);
@@ -416,6 +442,7 @@ int main() {
for (size_t i = 0; i < 2; ++i) {
test_builder();
test_canonicalization();
+ test_basic();
test_signatures(i == 1);
test_recursive();
test_subtypes();
diff --git a/test/example/type-builder-nominal.txt b/test/example/type-builder-nominal.txt
index 2ecb08c89..ff3e1c5fe 100644
--- a/test/example/type-builder-nominal.txt
+++ b/test/example/type-builder-nominal.txt
@@ -1,17 +1,17 @@
;; Test TypeBuilder
Before setting heap types:
-(ref $sig) => (ref [T](func))
-(ref $struct) => (ref [T](func))
-(ref $array) => (ref [T](func))
-(ref null $array) => (ref null [T](func))
-(rtt 0 $array) => (rtt 0 [T](func))
+(ref $sig) => [T](ref [T](func))
+(ref $struct) => [T](ref [T](func))
+(ref $array) => [T](ref [T](func))
+(ref null $array) => [T](ref null [T](func))
+(rtt 0 $array) => [T](rtt 0 [T](func))
After setting heap types:
-(ref $sig) => (ref [T](func (param (ref [T](struct (field (ref null [T](array (mut externref))) (mut (rtt 0 [T](array (mut externref)))))))) (result (ref [T](array (mut externref))) i32)))
-(ref $struct) => (ref [T](struct (field (ref null [T](array (mut externref))) (mut (rtt 0 [T](array (mut externref)))))))
-(ref $array) => (ref [T](array (mut externref)))
-(ref null $array) => (ref null [T](array (mut externref)))
-(rtt 0 $array) => (rtt 0 [T](array (mut externref)))
+(ref $sig) => [T](ref [T](func (param [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))) (result [T](ref [T](array (mut externref))) i32)))
+(ref $struct) => [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))
+(ref $array) => [T](ref [T](array (mut externref)))
+(ref null $array) => [T](ref null [T](array (mut externref)))
+(rtt 0 $array) => [T](rtt 0 [T](array (mut externref)))
After building types:
(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32)))
@@ -21,6 +21,7 @@ After building types:
(rtt 0 $array) => (rtt 0 (array (mut externref)))
;; Test canonicalization
+;; Test basic
;; Test canonical signatures
;; Test recursive types
(func (result (ref null ...1)))
@@ -47,18 +48,18 @@ After building types:
;; Test subtyping
;; Test TypeBuilder
Before setting heap types:
-(ref $sig) => (ref [T](func))
-(ref $struct) => (ref [T](func))
-(ref $array) => (ref [T](func))
-(ref null $array) => (ref null [T](func))
-(rtt 0 $array) => (rtt 0 [T](func))
+(ref $sig) => [T](ref [T](func))
+(ref $struct) => [T](ref [T](func))
+(ref $array) => [T](ref [T](func))
+(ref null $array) => [T](ref null [T](func))
+(rtt 0 $array) => [T](rtt 0 [T](func))
After setting heap types:
-(ref $sig) => (ref [T](func (param (ref [T](struct (field (ref null [T](array (mut externref))) (mut (rtt 0 [T](array (mut externref)))))))) (result (ref [T](array (mut externref))) i32)))
-(ref $struct) => (ref [T](struct (field (ref null [T](array (mut externref))) (mut (rtt 0 [T](array (mut externref)))))))
-(ref $array) => (ref [T](array (mut externref)))
-(ref null $array) => (ref null [T](array (mut externref)))
-(rtt 0 $array) => (rtt 0 [T](array (mut externref)))
+(ref $sig) => [T](ref [T](func (param [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))) (result [T](ref [T](array (mut externref))) i32)))
+(ref $struct) => [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))
+(ref $array) => [T](ref [T](array (mut externref)))
+(ref null $array) => [T](ref null [T](array (mut externref)))
+(rtt 0 $array) => [T](rtt 0 [T](array (mut externref)))
After building types:
(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32)))
@@ -68,6 +69,7 @@ After building types:
(rtt 0 $array) => (rtt 0 (array (mut externref)))
;; Test canonicalization
+;; Test basic
;; Test canonical signatures
;; Test recursive types
(func (result (ref null ...1)))
diff --git a/test/lit/fuzz-types/nominal.test b/test/lit/fuzz-types/nominal.test
index 92bfaa4e1..5b403c23a 100644
--- a/test/lit/fuzz-types/nominal.test
+++ b/test/lit/fuzz-types/nominal.test
@@ -1,24 +1,23 @@
;; RUN: wasm-fuzz-types --nominal -v --seed=0 | filecheck %s
-;; CHECK: Running with seed 0
-;; CHECK-NEXT: Built 20 types:
-;; CHECK-NEXT: 0: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32)))
-;; CHECK-NEXT: 1: (array (mut (ref null data)))
-;; CHECK-NEXT: 2: (func (result i64))
-;; CHECK-NEXT: 3: (func (result i64))
-;; CHECK-NEXT: 4: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32)))
-;; CHECK-NEXT: 5: (func (result i64))
-;; CHECK-NEXT: 6: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32)))
-;; CHECK-NEXT: 7: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32)))
-;; CHECK-NEXT: 8: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32) (mut (rtt eq)) (rtt (func (result i64))) (mut (rtt (func (result i64)))) (mut i16)))
-;; CHECK-NEXT: 9: (func (result i64))
-;; CHECK-NEXT: 10: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32) (mut (rtt eq)) (rtt (func (result i64))) (mut (rtt (func (result i64)))) (mut i16)))
-;; CHECK-NEXT: 11: (array (mut (ref null data)))
-;; CHECK-NEXT: 12: (struct (field (ref ...1) (mut f32)))
-;; CHECK-NEXT: 13: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32) (rtt 2 (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32)))) (mut (rtt 1 eq)) (mut i31ref)))
-;; CHECK-NEXT: 14: (func (result i64))
-;; CHECK-NEXT: 15: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32) (mut (rtt eq)) (rtt (func (result i64))) (mut (rtt (func (result i64)))) (mut i16)))
-;; CHECK-NEXT: 16: (func (result i64))
-;; CHECK-NEXT: 17: (array (mut (ref null data)))
-;; CHECK-NEXT: 18: (array (mut (ref null data)))
-;; CHECK-NEXT: 19: (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32) f64 eqref (mut (rtt 2 (struct (field (ref (struct (field ...1 (mut f32)))) (mut f32) (mut (rtt eq)) (rtt (func (result i64))) (mut (rtt (func (result i64)))) (mut i16)))))))
+;; CHECK: Built 20 types:
+;; CHECK-NEXT: 0: (struct (field (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...5 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...9 (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ..!))) i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!))))))
+;; CHECK-NEXT: 1: (func (param (rtt 0 (struct (field (ref null (struct (field (mut (rtt (func (param ...5)))) (ref (struct (field (mut (rtt (func (param ...7)))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param ...7)))) (ref (struct (field (mut (rtt (func (param ...9)))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param ...5)))) (ref (struct (field (mut (rtt (func (param ...7)))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param ...7)))) (ref (struct (field (mut (rtt (func (param ...9)))) ...1))))))) (mut f64) (mut (ref null (struct (field (mut (rtt (func (param ...7)))) (ref (struct (field (mut (rtt (func (param ...9)))) ...1)))))))))))))))
+;; CHECK-NEXT: 2: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null ...7)) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null ...7)) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null ...9)) (mut f64)))) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null ...9)) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1)))))
+;; CHECK-NEXT: 3: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64)))) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param ..!)))) ..!))))))) (mut f64)))
+;; CHECK-NEXT: 4: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref ...7) i32 (mut (ref null (struct (field (mut ...7) (ref ...9))))) (mut f64)))) (ref (struct (field (mut ...5) (ref ...7) i32 (mut (ref null (struct (field (mut ...7) (ref ...9))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref ...9))))))))))))))) (ref ...1)))
+;; CHECK-NEXT: 5: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref ...5)))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64)))) (ref ...7)))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64)))) (ref ...7)))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64)))) (ref ...9)))))))) ...1))))))) (mut f64) (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref ...7)))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut ..!) (mut f64)))) ..!))))))) ..!)))))))))
+;; CHECK-NEXT: 6: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64)))) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param ..!)))) ..!))))))) (mut f64)))
+;; CHECK-NEXT: 7: (struct (field (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...5 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...9 (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ..!))) i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!))))))
+;; CHECK-NEXT: 8: (struct (field (ref null (struct (field (mut (rtt (func (param (rtt 0 ...5))))) (ref (struct (field (mut (rtt (func (param (rtt 0 ...7))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 ...7))))) (ref (struct (field (mut (rtt (func (param (rtt 0 ...9))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 ...5))))) (ref (struct (field (mut (rtt (func (param (rtt 0 ...7))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 ...7))))) (ref (struct (field (mut (rtt (func (param (rtt 0 ...9))))) ...1))))))) (mut f64) (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 ...7))))) (ref (struct (field (mut (rtt (func (param (rtt 0 ...9))))) ...1))))))))))))
+;; CHECK-NEXT: 9: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...5) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...9) (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))
+;; CHECK-NEXT: 10: (struct (field (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...5) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...9) (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ..!) ..! i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!)))) (mut i31ref)))
+;; CHECK-NEXT: 11: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null ...7)))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64)))) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null ...9)))))))))))) ...1)))))
+;; CHECK-NEXT: 12: (struct (field (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...5 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...9 (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ..!))) i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!))))))
+;; CHECK-NEXT: 13: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64)))) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param ..!)))) ..!))))))) (mut f64) ..!))
+;; CHECK-NEXT: 14: (struct (field (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...5) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...9) (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ..!) ..! i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!)))) (mut i31ref) i8))
+;; CHECK-NEXT: 15: (func (param (rtt 0 (struct (field (ref null (struct (field (mut (rtt (func (param ...5)))) (ref (struct (field (mut (rtt (func (param ...7)))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param ...7)))) (ref (struct (field (mut (rtt (func (param ...9)))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param ...5)))) (ref (struct (field (mut (rtt (func (param ...7)))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param ...7)))) (ref (struct (field (mut (rtt (func (param ...9)))) ...1))))))) (mut f64) (mut (ref null (struct (field (mut (rtt (func (param ...7)))) (ref (struct (field (mut (rtt (func (param ...9)))) ...1)))))))))))))))
+;; CHECK-NEXT: 16: (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64)))) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64)))) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1)))))
+;; CHECK-NEXT: 17: (struct (field (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...5) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...7) (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null ...9) (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ..!) ..! i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!)))) (mut i31ref) i8 (mut dataref) (mut i16)))
+;; CHECK-NEXT: 18: (struct (field (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...5 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) ...7 i32 (mut (ref null (struct (field (mut ...7) ...9)))) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))) i32 (mut (ref null (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...7 (ref (struct (field (mut ...5) (ref (struct (field (mut ...7) ...1))) i32 (mut ...7) (mut f64) (mut (ref null (struct (field (mut ...7) (ref (struct (field (mut ...9) ...1))))))))))))))))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field ...9 (ref (struct (field (mut ...5) ...7 i32 (mut ...9) (mut f64) (mut (ref null (struct (field (mut ...7) ...9)))))))))))))) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt (func (param (rtt 0 (struct (field (ref null (struct (field (mut ...5) (ref (struct (field (mut ...7) ..!))) i32 (mut ..!) (mut f64)))) ..!))))))) ..! i32 (mut ..!) (mut f64) (mut ..!))))))
+;; CHECK-NEXT: 19: (func (param (rtt 0 (struct (field (ref null (struct (field (mut (rtt ...5)) (ref (struct (field (mut (rtt ...7)) ...1))) i32 (mut (ref null (struct (field (mut (rtt ...7)) (ref (struct (field (mut (rtt ...9)) ...1))))))) (mut f64)))) (ref (struct (field (mut (rtt ...5)) (ref (struct (field (mut (rtt ...7)) ...1))) i32 (mut (ref null (struct (field (mut (rtt ...7)) (ref (struct (field (mut (rtt ...9)) ...1))))))) (mut f64) (mut (ref null (struct (field (mut (rtt ...7)) (ref (struct (field (mut (rtt ...9)) ...1)))))))))))))))