From 98d17931f403235688beb2d6bb1a7c28fec2aae0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 25 Sep 2025 11:40:00 -0700 Subject: [PATCH] fix --- src/passes/Heap2Local.cpp | 4 +++ test/lit/passes/heap2local-desc.wast | 54 +++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/passes/Heap2Local.cpp b/src/passes/Heap2Local.cpp index 239f2317dfa..cb81d7b8fa8 100644 --- a/src/passes/Heap2Local.cpp +++ b/src/passes/Heap2Local.cpp @@ -945,6 +945,10 @@ struct Struct2Local : PostWalker { auto descIndex = localIndexes[fields.size()]; Expression* value = builder.makeLocalGet(descIndex, descType); replaceCurrent(builder.blockify(builder.makeDrop(curr->ref), value)); + + // After removing the ref.get_desc, a null may be falling through, + // requiring refinalization to update parents. + refinalize = true; } void visitStructSet(StructSet* curr) { diff --git a/test/lit/passes/heap2local-desc.wast b/test/lit/passes/heap2local-desc.wast index 0bad74bd539..99bb7907a20 100644 --- a/test/lit/passes/heap2local-desc.wast +++ b/test/lit/passes/heap2local-desc.wast @@ -211,7 +211,7 @@ ;; CHECK-NEXT: (local $1 (ref (exact $sub.desc))) ;; CHECK-NEXT: (block (result (ref (exact $sub.desc))) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $super)) + ;; CHECK-NEXT: (block (result nullref) ;; CHECK-NEXT: (block (result nullref) ;; CHECK-NEXT: (local.set $1 ;; CHECK-NEXT: (struct.new_default $sub.desc) @@ -1004,3 +1004,55 @@ ) ) ) + +(module + (rec + (type $A (descriptor $B (struct))) + (type $B (sub (describes $A (struct)))) + ) + ;; CHECK: (type $0 (func)) + + ;; CHECK: (func $test (type $0) + ;; CHECK-NEXT: (local $0 (ref none)) + ;; CHECK-NEXT: (local $1 (ref none)) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_on_null $block + ;; CHECK-NEXT: (block (result (ref none)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test + ;; After removing the ref.get_desc, the null descriptor falls through, and + ;; we must update the br_on_null's type, or internal validation errors. + (block $block + (drop + (br_on_null $block + (ref.get_desc $A + (struct.new_default $A + (ref.null none) + ) + ) + ) + ) + (unreachable) + ) + ) +)