From fac32ecdf188ec922dcb2774c7c28964f8d50b52 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 10 Jul 2026 11:46:26 -0700 Subject: [PATCH 1/3] fix --- src/passes/Heap2Local.cpp | 6 +++- test/lit/passes/heap2local.wast | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/passes/Heap2Local.cpp b/src/passes/Heap2Local.cpp index ba4f3409164..74a239a5ae6 100644 --- a/src/passes/Heap2Local.cpp +++ b/src/passes/Heap2Local.cpp @@ -661,6 +661,11 @@ struct Struct2Local : PostWalker { return; } + if (curr->type == Type::unreachable) { + // We ended up with unreachable code, and have nothing to do. + return; + } + // Our allocation passes through this expr. We must turn its type into a // nullable one, because we will remove things like RefAsNonNull of it, // which means we may no longer have a non-nullable value as our input, @@ -668,7 +673,6 @@ struct Struct2Local : PostWalker { // of our parent, since we know very specifically that only safe things // will end up using our value, like a StructGet or a Drop, which do not // care about non-nullability. - assert(curr->type.isRef()); curr->type = Type(curr->type.getHeapType(), Nullable); } diff --git a/test/lit/passes/heap2local.wast b/test/lit/passes/heap2local.wast index ec1e06a4a1d..e37d18a72bf 100644 --- a/test/lit/passes/heap2local.wast +++ b/test/lit/passes/heap2local.wast @@ -4808,3 +4808,59 @@ ) ) ) + +(module + (type $array (array (mut i32))) + + ;; CHECK: (type $0 (func)) + + ;; CHECK: (func $unreachable-flow (type $0) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (local $3 i32) + ;; CHECK-NEXT: (local $4 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $3 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $4 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $unreachable-flow + ;; The return flows into the br_if. This should not cause errors as wel + ;; optimize out the allocation. + (drop + (block $block (result arrayref) + (br_if $block + (array.new_default $array + (i32.const 5) + ) + (return) + ) + ) + ) + ) +) + From a351145352d2dcd2da725ed9b2c3eb07ecde5569 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 10 Jul 2026 11:47:29 -0700 Subject: [PATCH 2/3] restore --- src/passes/Heap2Local.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/passes/Heap2Local.cpp b/src/passes/Heap2Local.cpp index 74a239a5ae6..7f8381e2a6c 100644 --- a/src/passes/Heap2Local.cpp +++ b/src/passes/Heap2Local.cpp @@ -673,6 +673,7 @@ struct Struct2Local : PostWalker { // of our parent, since we know very specifically that only safe things // will end up using our value, like a StructGet or a Drop, which do not // care about non-nullability. + assert(curr->type.isRef()); curr->type = Type(curr->type.getHeapType(), Nullable); } From a746e3d9bfdfba49d3715afeefd6a2065cadcb0d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 10 Jul 2026 11:48:26 -0700 Subject: [PATCH 3/3] typo --- test/lit/passes/heap2local.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit/passes/heap2local.wast b/test/lit/passes/heap2local.wast index e37d18a72bf..11d9659db5f 100644 --- a/test/lit/passes/heap2local.wast +++ b/test/lit/passes/heap2local.wast @@ -4849,7 +4849,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-flow - ;; The return flows into the br_if. This should not cause errors as wel + ;; The return flows into the br_if. This should not cause errors as we ;; optimize out the allocation. (drop (block $block (result arrayref)