From 1b90a3ece6a5a5ced9a488635479d8884eeb4dd2 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Mon, 5 Jan 2026 19:56:57 -0800 Subject: [PATCH] Remove incorrect assertion in IRBuilder IRBuilder has to handle the case where a branching instruction like br_on_null sends a value to its target label, even though we cannot directly represent such a value being sent in our IR. To do so, it adds an extra trampoline label that fetches the sent value out of scratch locals before branching to the original target. We previously had an assertion that the scratch local used to hold such extra values had the same type as the expression with the destination label. This is usually true, but it is possible that the destination label is on an If with an unreachable condition, in which case the destination has type unreachable and the scratch local has the original concrete label type. Remove the incorrect assertion. Fixes #8096. --- src/wasm/wasm-ir-builder.cpp | 1 - test/lit/wat-kitchen-sink.wast | 62 +++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index a60dd6edc57..120428cec4c 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -1166,7 +1166,6 @@ IRBuilder::fixExtraOutput(ScopeCtx& scope, Name label, Expression* curr) { // If all the received values are in the scratch local, just fetch them out. if (receivedType == Type::none) { - assert(extraType == labelType); curr = builder.makeSequence( curr, builder.makeLocalGet(extraLocal, extraType), extraType); continue; diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 47ac2a5e448..547278be4a0 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -5139,7 +5139,7 @@ ) ;; The if is unreachable except through the break; make sure this is - ;; parse correctly + ;; parsed correctly ;; CHECK: (func $if-else-br-return (type $27) (param $a i32) (result i32) ;; CHECK-NEXT: (block $label ;; CHECK-NEXT: (if @@ -5168,6 +5168,66 @@ (i32.const 1) ) + ;; CHECK: (func $if-else-unreachable-br-extra (type $1) (result i32) + ;; CHECK-NEXT: (local $scratch nullref) + ;; CHECK-NEXT: (local $scratch_1 i32) + ;; CHECK-NEXT: (local $scratch_2 i32) + ;; CHECK-NEXT: (local $scratch_3 (ref none)) + ;; CHECK-NEXT: (local $scratch_4 i32) + ;; CHECK-NEXT: (block $l (result i32) + ;; CHECK-NEXT: (block $l0 + ;; CHECK-NEXT: (br $l + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $scratch_1 + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $scratch_2 + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $scratch + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $scratch_3 + ;; CHECK-NEXT: (br_on_null $l0 + ;; CHECK-NEXT: (local.get $scratch) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $scratch_4 + ;; CHECK-NEXT: (local.get $scratch_1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $scratch_3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i32.const 1337) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-else-unreachable-br-extra (result i32) + ;; The condition is unreachable, making the if unreachable. + unreachable + if $l (result i32) + ;; Send an extra i32. We should not get confused because the if is + ;; unreachable. + i32.const 42 + ref.null none + br_on_null $l + drop + else $l + i32.const 1337 + end $l + ) + ;; CHECK: (func $try-br-catch-all-return (type $0) ;; CHECK-NEXT: (block $label ;; CHECK-NEXT: (try