diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index 10c791f609e..42e93b71c1b 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -318,8 +318,9 @@ 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) { + Type blockType = findBreakTarget(name)->type; ourPreludes.push_back( - builder.makeLocalSet(getTempForBreakTarget(name, type), + builder.makeLocalSet(getTempForBreakTarget(name, blockType), builder.makeLocalGet(temp, type))); } sw->value = nullptr; diff --git a/test/lit/passes/flatten.wast b/test/lit/passes/flatten.wast index 7e890d6aeb3..633343f4e40 100644 --- a/test/lit/passes/flatten.wast +++ b/test/lit/passes/flatten.wast @@ -18,4 +18,39 @@ ;; modified (local.get $0) ) + + ;; CHECK: (func $switch_subtype (type $2) (result funcref) + ;; CHECK-NEXT: (local $0 nullfuncref) + ;; CHECK-NEXT: (local $1 funcref) + ;; CHECK-NEXT: (local $2 funcref) + ;; CHECK-NEXT: (block $b + ;; 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 $b + ;; 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 $switch_subtype (result funcref) + ;; A br_table sending a subtype of its target block's result type should + ;; allocate the break target local with the target block's type, not the + ;; narrower sent value type. + (block $b (result funcref) + (br_table $b + (ref.null nofunc) + (i32.const 0) + ) + ) + ) )