summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/example/type-builder.cpp39
-rw-r--r--test/example/type-builder.txt51
-rw-r--r--test/lit/passes/roundtrip-gc-types.wast27
3 files changed, 113 insertions, 4 deletions
diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp
index a228697e9..8d87c5054 100644
--- a/test/example/type-builder.cpp
+++ b/test/example/type-builder.cpp
@@ -103,6 +103,32 @@ void test_canonicalization() {
assert(built[3] == sig);
}
+// 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] == HeapType(Signature(Type::anyref, Type::i31ref)));
+ assert(built[1] == built[0]);
+ assert(built[2] == built[1]);
+ assert(built[3] == built[2]);
+ assert(built[4] == HeapType::any);
+ assert(built[5] == HeapType::i31);
+}
+
void test_recursive() {
std::cout << ";; Test recursive types\n";
@@ -467,8 +493,13 @@ void test_lub() {
}
int main() {
- test_builder();
- test_canonicalization();
- test_recursive();
- test_lub();
+ // Run the tests twice to ensure things still work when the global stores are
+ // already populated.
+ for (size_t i = 0; i < 2; ++i) {
+ test_builder();
+ test_canonicalization();
+ test_basic();
+ test_recursive();
+ test_lub();
+ }
}
diff --git a/test/example/type-builder.txt b/test/example/type-builder.txt
index d9f469461..a219816e6 100644
--- a/test/example/type-builder.txt
+++ b/test/example/type-builder.txt
@@ -21,6 +21,57 @@ After building types:
(rtt 0 $array) => (rtt 0 (array (mut externref)))
;; Test canonicalization
+;; Test basic
+;; Test recursive types
+(func (result (ref null ...1)))
+
+(func (result (ref null ...1)))
+(func (result (ref null ...1)))
+
+(func (result (ref null ...1)))
+(func (result (ref null ...1)))
+(func (result (ref null ...1)))
+(func (result (ref null ...1)))
+(func (result (ref null ...1)))
+
+(func (result (ref null ...1) (ref null (func))))
+(func (result (ref null ...1) (ref null (func))))
+(func)
+(func)
+(func (result (ref null (func (result ...1 (ref null (func)))))))
+(func (result (ref null (func (result ...1 (ref null (func)))))))
+
+(func (result (ref null ...1)))
+(func (result (ref null ...1)))
+
+(func (param anyref) (result (ref null ...1)))
+(func (param anyref) (result (ref null ...1)))
+
+;; Test LUBs
+;; Test TypeBuilder
+Before setting heap types:
+(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) => [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)))
+(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))
+(ref $array) => (ref (array (mut externref)))
+(ref null $array) => (ref null (array (mut externref)))
+(rtt 0 $array) => (rtt 0 (array (mut externref)))
+
+;; Test canonicalization
+;; Test basic
;; Test recursive types
(func (result (ref null ...1)))
diff --git a/test/lit/passes/roundtrip-gc-types.wast b/test/lit/passes/roundtrip-gc-types.wast
new file mode 100644
index 000000000..449df6639
--- /dev/null
+++ b/test/lit/passes/roundtrip-gc-types.wast
@@ -0,0 +1,27 @@
+;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s
+
+;; Regression test for an issue in which roundtripping failed to reproduce the
+;; original types because type canonicalization was incorrect when the canonical
+;; types already existed in the store.
+
+;; CHECK: (module
+;; CHECK-NEXT: (type $A (struct (field (ref $C))))
+;; CHECK-NEXT: (type $B (func (param (ref $A)) (result (ref $B))))
+;; CHECK-NEXT: (type $C (struct (field (mut (ref $B)))))
+;; CHECK-NEXT: (type $D (struct (field (ref $C)) (field (ref $A))))
+;; CHECK-NEXT: (global $g0 (rtt 0 $A) (rtt.canon $A))
+;; CHECK-NEXT: (global $g1 (rtt 1 $D) (rtt.sub $D
+;; CHECK-NEXT: (global.get $g0)
+;; CHECK-NEXT: ))
+;; CHECK-NEXT: )
+
+(module
+ (type $A (struct (field (ref $C))))
+ (type $B (func (param (ref $A)) (result (ref $B))))
+ (type $C (struct (field (mut (ref $B)))))
+ (type $D (struct (field (ref $C)) (field (ref $A))))
+ (global $g0 (rtt 0 $A) (rtt.canon $A))
+ (global $g1 (rtt 1 $D) (rtt.sub $D
+ (global.get $g0)
+ ))
+)