From c086cb8e2d4432983ea6de41a7e4c00b8c788c8a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 8 Jun 2026 10:19:11 -0700 Subject: [PATCH 1/3] fix --- src/ir/possible-contents.cpp | 15 +++-- test/lit/passes/gufa-closed-open.wast | 82 +++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index a8a01841fd6..ef4f07fb923 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1161,11 +1161,12 @@ struct InfoCollector curr->ref, curr->index, curr->value, MemoryOrder::Unordered); visitArraySet(set); } - template void visitArrayInit(ArrayInit* curr) { + + void handleArrayWrite(Expression* ref) { // Check for both unreachability and a bottom type. In either case we have // no work to do, and would error on an assertion below in finding the array // type. - auto field = GCTypeUtils::getField(curr->ref->type); + auto field = GCTypeUtils::getField(ref->type); if (!field) { return; } @@ -1179,12 +1180,15 @@ struct InfoCollector Builder builder(*getModule()); auto* get = builder.makeLocalGet(-1, valueType); addRoot(get); + // The index does not matter, as we do not track array indexes yet TODO + Expression* index = builder.makeNop(); auto* set = - builder.makeArraySet(curr->ref, curr->index, get, MemoryOrder::Unordered); + builder.makeArraySet(ref, index, get, MemoryOrder::Unordered); visitArraySet(set); } - void visitArrayInitData(ArrayInitData* curr) { visitArrayInit(curr); } - void visitArrayInitElem(ArrayInitElem* curr) { visitArrayInit(curr); } + + void visitArrayInitData(ArrayInitData* curr) { handleArrayWrite(curr->ref); } + void visitArrayInitElem(ArrayInitElem* curr) { handleArrayWrite(curr->ref); } void visitArrayRMW(ArrayRMW* curr) { if (curr->ref->type == Type::unreachable) { return; @@ -1219,6 +1223,7 @@ struct InfoCollector } void visitStringEncode(StringEncode* curr) { // TODO: optimize when possible + handleArrayWrite(curr->array); addRoot(curr); } void visitStringConcat(StringConcat* curr) { diff --git a/test/lit/passes/gufa-closed-open.wast b/test/lit/passes/gufa-closed-open.wast index c87c811df84..ced1f9f9cbc 100644 --- a/test/lit/passes/gufa-closed-open.wast +++ b/test/lit/passes/gufa-closed-open.wast @@ -167,3 +167,85 @@ ) ) +;; Write to an array using string.encode. +(module + ;; OPEND: (type $array (array (mut i16))) + ;; CLOSE: (type $array (array (mut i16))) + (type $array (array (mut i16))) + + ;; OPEND: (type $1 (func)) + + ;; OPEND: (type $2 (func (result i32))) + + ;; OPEND: (global $global (ref $array) (array.new_default $array + ;; OPEND-NEXT: (i32.const 42) + ;; OPEND-NEXT: )) + ;; CLOSE: (type $1 (func)) + + ;; CLOSE: (type $2 (func (result i32))) + + ;; CLOSE: (global $global (ref $array) (array.new_default $array + ;; CLOSE-NEXT: (i32.const 42) + ;; CLOSE-NEXT: )) + (global $global (ref $array) (array.new_default $array + (i32.const 42) + )) + + ;; OPEND: (export "encode" (func $encode)) + + ;; OPEND: (export "read" (func $read)) + + ;; OPEND: (func $encode (type $1) + ;; OPEND-NEXT: (drop + ;; OPEND-NEXT: (string.encode_wtf16_array + ;; OPEND-NEXT: (string.const "hello") + ;; OPEND-NEXT: (global.get $global) + ;; OPEND-NEXT: (i32.const 0) + ;; OPEND-NEXT: ) + ;; OPEND-NEXT: ) + ;; OPEND-NEXT: ) + ;; CLOSE: (export "encode" (func $encode)) + + ;; CLOSE: (export "read" (func $read)) + + ;; CLOSE: (func $encode (type $1) + ;; CLOSE-NEXT: (drop + ;; CLOSE-NEXT: (string.encode_wtf16_array + ;; CLOSE-NEXT: (string.const "hello") + ;; CLOSE-NEXT: (global.get $global) + ;; CLOSE-NEXT: (i32.const 0) + ;; CLOSE-NEXT: ) + ;; CLOSE-NEXT: ) + ;; CLOSE-NEXT: ) + (func $encode (export "encode") + (drop + (string.encode_wtf16_array + (string.const "hello") + (global.get $global) + (i32.const 0) + ) + ) + ) + + ;; OPEND: (func $read (type $2) (result i32) + ;; OPEND-NEXT: (array.atomic.get_s $array + ;; OPEND-NEXT: (global.get $global) + ;; OPEND-NEXT: (i32.const 0) + ;; OPEND-NEXT: ) + ;; OPEND-NEXT: ) + ;; CLOSE: (func $read (type $2) (result i32) + ;; CLOSE-NEXT: (array.atomic.get_s $array + ;; CLOSE-NEXT: (global.get $global) + ;; CLOSE-NEXT: (i32.const 0) + ;; CLOSE-NEXT: ) + ;; CLOSE-NEXT: ) + (func $read (export "read") (result i32) + ;; We could infer what the value is here, since there is only one write. TODO + ;; Meanwhile, we should not infer a wrong value, even in closed world. + (array.atomic.get_s $array + (global.get $global) + (i32.const 0) + ) + ) +) + From 336b698912022708d775b323cb682a8836883109 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 8 Jun 2026 10:19:17 -0700 Subject: [PATCH 2/3] fix --- src/ir/possible-contents.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index ef4f07fb923..766409347e6 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1182,8 +1182,7 @@ struct InfoCollector addRoot(get); // The index does not matter, as we do not track array indexes yet TODO Expression* index = builder.makeNop(); - auto* set = - builder.makeArraySet(ref, index, get, MemoryOrder::Unordered); + auto* set = builder.makeArraySet(ref, index, get, MemoryOrder::Unordered); visitArraySet(set); } From 3392f55b85b4a515478c6525637a63f8119e696e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 8 Jun 2026 12:48:52 -0700 Subject: [PATCH 3/3] unatomic --- test/lit/passes/gufa-closed-open.wast | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/lit/passes/gufa-closed-open.wast b/test/lit/passes/gufa-closed-open.wast index ced1f9f9cbc..df6d4b05eb8 100644 --- a/test/lit/passes/gufa-closed-open.wast +++ b/test/lit/passes/gufa-closed-open.wast @@ -228,13 +228,13 @@ ) ;; OPEND: (func $read (type $2) (result i32) - ;; OPEND-NEXT: (array.atomic.get_s $array + ;; OPEND-NEXT: (array.get_s $array ;; OPEND-NEXT: (global.get $global) ;; OPEND-NEXT: (i32.const 0) ;; OPEND-NEXT: ) ;; OPEND-NEXT: ) ;; CLOSE: (func $read (type $2) (result i32) - ;; CLOSE-NEXT: (array.atomic.get_s $array + ;; CLOSE-NEXT: (array.get_s $array ;; CLOSE-NEXT: (global.get $global) ;; CLOSE-NEXT: (i32.const 0) ;; CLOSE-NEXT: ) @@ -242,7 +242,7 @@ (func $read (export "read") (result i32) ;; We could infer what the value is here, since there is only one write. TODO ;; Meanwhile, we should not infer a wrong value, even in closed world. - (array.atomic.get_s $array + (array.get_s $array (global.get $global) (i32.const 0) )