summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm-ir-builder.h1
-rw-r--r--src/wasm/wasm-ir-builder.cpp12
2 files changed, 11 insertions, 2 deletions
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h
index d9075952d..9b8ae043f 100644
--- a/src/wasm-ir-builder.h
+++ b/src/wasm-ir-builder.h
@@ -239,6 +239,7 @@ private:
// The branch label name for this scope. Always fresh, never shadowed.
Name label;
+ bool labelUsed = false;
std::vector<Expression*> exprStack;
// Whether we have seen an unreachable instruction and are in
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index 964676ff9..dfbf156b2 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -584,10 +584,17 @@ Result<> IRBuilder::visitEnd() {
CHECK_ERR(expr);
// If the scope expression cannot be directly labeled, we may need to wrap it
- // in a block.
+ // in a block. It's possible that the scope expression becomes typed
+ // unreachable when it is finalized, but if the wrapper block is targeted by
+ // any branches, the target block needs to have the original non-unreachable
+ // type of the scope expression.
+ auto originalScopeType = scope.getResultType();
auto maybeWrapForLabel = [&](Expression* curr) -> Expression* {
if (scope.label) {
- return builder.makeBlock(scope.label, {curr}, scope.getResultType());
+ return builder.makeBlock(scope.label,
+ {curr},
+ scope.labelUsed ? originalScopeType
+ : scope.getResultType());
}
return curr;
};
@@ -638,6 +645,7 @@ Result<Name> IRBuilder::getLabelName(Index label) {
// The scope does not already have a name, so we need to create one.
scopeLabel = makeFresh("label");
}
+ (*scope)->labelUsed = true;
return scopeLabel;
}