From c5b2e3f544b7abac2b46a46a56188b90d9abdafa Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2025 08:01:16 -0700 Subject: [PATCH 1/5] work --- src/passes/TypeMerging.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/passes/TypeMerging.cpp b/src/passes/TypeMerging.cpp index 186aa69080b..6bd06e040d6 100644 --- a/src/passes/TypeMerging.cpp +++ b/src/passes/TypeMerging.cpp @@ -224,6 +224,7 @@ bool shapeEq(HeapType a, HeapType b); bool shapeEq(const Struct& a, const Struct& b); bool shapeEq(Array a, Array b); bool shapeEq(Signature a, Signature b); +bool shapeEq(Continuation a, Continuation b); bool shapeEq(Field a, Field b); bool shapeEq(Type a, Type b); bool shapeEq(const Tuple& a, const Tuple& b); @@ -232,6 +233,7 @@ size_t shapeHash(HeapType a); size_t shapeHash(const Struct& a); size_t shapeHash(Array a); size_t shapeHash(Signature a); +size_t shapeHash(Continuation a); size_t shapeHash(Field a); size_t shapeHash(Type a); size_t shapeHash(const Tuple& a); @@ -690,7 +692,10 @@ bool shapeEq(HeapType a, HeapType b) { } break; case HeapTypeKind::Cont: - WASM_UNREACHABLE("TODO: cont"); + if (!shapeEq(a.getContinuation(), b.getContinuation())) { + return false; + } + break; case HeapTypeKind::Basic: WASM_UNREACHABLE("unexpected kind"); } @@ -719,7 +724,8 @@ size_t shapeHash(HeapType a) { hash_combine(digest, shapeHash(type.getArray())); continue; case HeapTypeKind::Cont: - WASM_UNREACHABLE("TODO: cont"); + hash_combine(digest, shapeHash(type.getContinuation())); + continue; case HeapTypeKind::Basic: continue; } @@ -762,6 +768,10 @@ size_t shapeHash(Signature a) { return digest; } +bool shapeEq(Continuation a, Continuation b) { return shapeEq(a.type, b.type); } + +size_t shapeHash(Continuation a) { return shapeHash(a.type); } + bool shapeEq(Field a, Field b) { return a.packedType == b.packedType && a.mutable_ == b.mutable_ && shapeEq(a.type, b.type); From 38df24614d3a46520a53d16a432ea82ed6d87977 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2025 08:28:18 -0700 Subject: [PATCH 2/5] test --- test/lit/passes/type-merging-cont.wast | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test/lit/passes/type-merging-cont.wast diff --git a/test/lit/passes/type-merging-cont.wast b/test/lit/passes/type-merging-cont.wast new file mode 100644 index 00000000000..76fde96384a --- /dev/null +++ b/test/lit/passes/type-merging-cont.wast @@ -0,0 +1,50 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: foreach %s %t wasm-opt -all --closed-world --preserve-type-order \ +;; RUN: --type-merging --remove-unused-types -S -o - | filecheck %s + +;; $A1 and $A2 can be merged, and $B1/$B2, as they have identical continuation +;; fields. But $A*/B* cannot be merged, as the continuations differ. + +(module + ;; CHECK: (rec + ;; CHECK-NEXT: (type $f (func)) + (type $f (func)) + ;; CHECK: (type $f_0 (func)) + + ;; CHECK: (type $k (cont $f_0)) + (type $k (cont $f)) + + (type $f-i32 (func (result i32))) + ;; CHECK: (type $f-i32_0 (func (result i32))) + + ;; CHECK: (type $k-i32 (cont $f-i32_0)) + (type $k-i32 (cont $f-i32)) + + (rec + ;; CHECK: (type $A1 (struct (field (ref $k)))) + (type $A1 (struct (ref $k))) + ;; CHECK: (type $A2 (struct (field (ref $k-i32)))) + (type $A2 (struct (ref $k-i32))) + (type $B1 (struct (ref $k))) + (type $B2 (struct (ref $k-i32))) + ) + + ;; CHECK: (func $test (type $f) + ;; CHECK-NEXT: (local $k (ref $k)) + ;; CHECK-NEXT: (local $k-i32 (ref $k-i32)) + ;; CHECK-NEXT: (local $a1 (ref $A1)) + ;; CHECK-NEXT: (local $a2 (ref $A2)) + ;; CHECK-NEXT: (local $b1 (ref $A1)) + ;; CHECK-NEXT: (local $b2 (ref $A2)) + ;; CHECK-NEXT: ) + (func $test + (local $k (ref $k)) + (local $k-i32 (ref $k-i32)) + (local $a1 (ref $A1)) + (local $a2 (ref $A2)) + (local $b1 (ref $B1)) + (local $b2 (ref $B2)) + ) +) + From efdb9a7ee7b5e2abd16013388961924fe6f4846a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2025 08:46:53 -0700 Subject: [PATCH 3/5] skip --- scripts/test/fuzzing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test/fuzzing.py b/scripts/test/fuzzing.py index 6907662d7ca..1afbb898833 100644 --- a/scripts/test/fuzzing.py +++ b/scripts/test/fuzzing.py @@ -118,6 +118,7 @@ 'cont_many_unhandled.wast', 'cont_export.wast', 'cont_export_throw.wast', + 'type-merging-cont.wast', # TODO: fix split_wast() on tricky escaping situations like a string ending # in \\" (the " is not escaped - there is an escaped \ before it) 'string-lifting-section.wast', From 8360dfcfc47185c9dd4769ce1fcfed90445d89a7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2025 09:48:42 -0700 Subject: [PATCH 4/5] Update test/lit/passes/type-merging-cont.wast Co-authored-by: Thomas Lively --- test/lit/passes/type-merging-cont.wast | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/lit/passes/type-merging-cont.wast b/test/lit/passes/type-merging-cont.wast index 76fde96384a..90e791c895b 100644 --- a/test/lit/passes/type-merging-cont.wast +++ b/test/lit/passes/type-merging-cont.wast @@ -25,8 +25,8 @@ ;; CHECK: (type $A1 (struct (field (ref $k)))) (type $A1 (struct (ref $k))) ;; CHECK: (type $A2 (struct (field (ref $k-i32)))) - (type $A2 (struct (ref $k-i32))) - (type $B1 (struct (ref $k))) + (type $A2 (struct (ref $k))) + (type $B1 (struct (ref $k-i32))) (type $B2 (struct (ref $k-i32))) ) From 5808c648e6897a2fdeacf4d48ef49bdfb2292ddf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2025 10:13:11 -0700 Subject: [PATCH 5/5] update --- test/lit/passes/type-merging-cont.wast | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/lit/passes/type-merging-cont.wast b/test/lit/passes/type-merging-cont.wast index 90e791c895b..e8f059345b1 100644 --- a/test/lit/passes/type-merging-cont.wast +++ b/test/lit/passes/type-merging-cont.wast @@ -24,8 +24,8 @@ (rec ;; CHECK: (type $A1 (struct (field (ref $k)))) (type $A1 (struct (ref $k))) - ;; CHECK: (type $A2 (struct (field (ref $k-i32)))) (type $A2 (struct (ref $k))) + ;; CHECK: (type $B1 (struct (field (ref $k-i32)))) (type $B1 (struct (ref $k-i32))) (type $B2 (struct (ref $k-i32))) ) @@ -34,9 +34,9 @@ ;; CHECK-NEXT: (local $k (ref $k)) ;; CHECK-NEXT: (local $k-i32 (ref $k-i32)) ;; CHECK-NEXT: (local $a1 (ref $A1)) - ;; CHECK-NEXT: (local $a2 (ref $A2)) - ;; CHECK-NEXT: (local $b1 (ref $A1)) - ;; CHECK-NEXT: (local $b2 (ref $A2)) + ;; CHECK-NEXT: (local $a2 (ref $A1)) + ;; CHECK-NEXT: (local $b1 (ref $B1)) + ;; CHECK-NEXT: (local $b2 (ref $B1)) ;; CHECK-NEXT: ) (func $test (local $k (ref $k))