From acc2665f6e73211ccf2dd30c64f03099fd414656 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 28 Oct 2026 15:20:03 -0700 Subject: [PATCH 1/3] Fix Flatten on br_table with subtyping --- src/passes/Flatten.cpp | 12 ++++++------ test/lit/passes/flatten.wast | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index 10c791f609e..e8ec8ea72a7 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -259,7 +259,7 @@ struct Flatten if (type.isConcrete()) { // we are sending a value. use a local instead Type blockType = findBreakTarget(br->name)->type; - Index temp = getTempForBreakTarget(br->name, blockType); + Index temp = getTempForBreakTarget(br->name); ourPreludes.push_back(builder.makeLocalSet(temp, br->value)); // br_if leaves a value on the stack if not taken, which later can @@ -318,9 +318,8 @@ struct Flatten // we don't know which break target will be hit - assign to them all auto names = BranchUtils::getUniqueTargets(sw); for (auto name : names) { - ourPreludes.push_back( - builder.makeLocalSet(getTempForBreakTarget(name, type), - builder.makeLocalGet(temp, type))); + ourPreludes.push_back(builder.makeLocalSet( + getTempForBreakTarget(name), builder.makeLocalGet(temp, type))); } sw->value = nullptr; sw->finalize(); @@ -408,13 +407,14 @@ struct Flatten // get the temp local to be used for breaks to that target. allocates // one if there isn't one yet - Index getTempForBreakTarget(Name name, Type type) { + Index getTempForBreakTarget(Name name) { auto iter = breakTemps.find(name); if (iter != breakTemps.end()) { return iter->second; } else { return breakTemps[name] = - Builder(*getModule()).addVar(getFunction(), type); + Builder(*getModule()) + .addVar(getFunction(), findBreakTarget(name)->type); } } }; diff --git a/test/lit/passes/flatten.wast b/test/lit/passes/flatten.wast index 7e890d6aeb3..7b15be18451 100644 --- a/test/lit/passes/flatten.wast +++ b/test/lit/passes/flatten.wast @@ -18,4 +18,36 @@ ;; modified (local.get $0) ) + + ;; CHECK: (func $br_table-subtype (type $2) (result funcref) + ;; CHECK-NEXT: (local $0 nullfuncref) + ;; CHECK-NEXT: (local $1 funcref) + ;; CHECK-NEXT: (local $2 funcref) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null nofunc) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br_table $block $block + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br_table-subtype (result funcref) + (block $block (result funcref) + (br_table $block $block + (ref.null nofunc) + (i32.const 0) + ) + ) + ) ) From 72366ecf82239ec916d94d9bd1dd6762e0b3955e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 28 Oct 2026 15:21:49 -0700 Subject: [PATCH 2/3] simpl --- src/passes/Flatten.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index e8ec8ea72a7..b9af7eaccb0 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -258,7 +258,6 @@ struct Flatten auto type = br->value->type; if (type.isConcrete()) { // we are sending a value. use a local instead - Type blockType = findBreakTarget(br->name)->type; Index temp = getTempForBreakTarget(br->name); ourPreludes.push_back(builder.makeLocalSet(temp, br->value)); @@ -283,7 +282,7 @@ struct Flatten // with anyref type in case for flowing out. Here we create the // second 'flowing out' local in case two block's types are // different. - if (type != blockType) { + if (type != findBreakTarget(br->name)->type) { temp = builder.addVar(getFunction(), type); ourPreludes.push_back(builder.makeLocalSet( temp, ExpressionManipulator::copy(br->value, *getModule()))); From 4dbc96b620280a35ef02596c3d1d1043464b7042 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 28 Oct 2026 15:24:10 -0700 Subject: [PATCH 3/3] comment --- test/lit/passes/flatten.wast | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/lit/passes/flatten.wast b/test/lit/passes/flatten.wast index 7b15be18451..1e524d38c6b 100644 --- a/test/lit/passes/flatten.wast +++ b/test/lit/passes/flatten.wast @@ -43,6 +43,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $br_table-subtype (result funcref) + ;; The br_table's value is more refined than the place we branch to, so we + ;; need to be careful with the types of our temp locals. (block $block (result funcref) (br_table $block $block (ref.null nofunc)