summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-03-01 15:04:54 +0000
committerGitHub <noreply@github.com>2021-03-01 07:04:54 -0800
commit27a841eec6ceb171caae2a2cbd7c92ecdf8d78eb (patch)
tree2d03ee70c25165ba319e1b98e780350553f44c9a
parent7d453930f1b211baf324b1c010924d3709ff12ba (diff)
downloadbinaryen-27a841eec6ceb171caae2a2cbd7c92ecdf8d78eb.tar.gz
binaryen-27a841eec6ceb171caae2a2cbd7c92ecdf8d78eb.tar.bz2
binaryen-27a841eec6ceb171caae2a2cbd7c92ecdf8d78eb.zip
[Wasm Exceptions] Properly ensure unique Try labels after an inlining (#3632)
The old code here just referred to Block and Loop. Refactor it to use the generic helper code that also handles Try. Also add validation of Try names in the validator. The testcase here would have $label appear twice before this fix. After the fix there is $label0 for one of them.
-rw-r--r--src/parsing.h45
-rw-r--r--src/wasm/wasm-validator.cpp3
-rw-r--r--test/passes/inlining_all-features.txt26
-rw-r--r--test/passes/inlining_all-features.wast21
4 files changed, 68 insertions, 27 deletions
diff --git a/src/parsing.h b/src/parsing.h
index 68647901a..9c3e0cd19 100644
--- a/src/parsing.h
+++ b/src/parsing.h
@@ -22,6 +22,7 @@
#include <sstream>
#include <string>
+#include "ir/branch-utils.h"
#include "mixed_arena.h"
#include "shared-constants.h"
#include "support/colors.h"
@@ -344,42 +345,32 @@ struct UniqueNameMapper {
// Given an expression, ensures all names are unique
static void uniquify(Expression* curr) {
- struct Walker : public ControlFlowWalker<Walker, Visitor<Walker>> {
+ struct Walker
+ : public ControlFlowWalker<Walker, UnifiedExpressionVisitor<Walker>> {
UniqueNameMapper mapper;
static void doPreVisitControlFlow(Walker* self, Expression** currp) {
- auto* curr = *currp;
- if (auto* block = curr->dynCast<Block>()) {
- if (block->name.is()) {
- block->name = self->mapper.pushLabelName(block->name);
+ BranchUtils::operateOnScopeNameDefs(*currp, [&](Name& name) {
+ if (name.is()) {
+ name = self->mapper.pushLabelName(name);
}
- } else if (auto* loop = curr->dynCast<Loop>()) {
- if (loop->name.is()) {
- loop->name = self->mapper.pushLabelName(loop->name);
- }
- }
+ });
}
+
static void doPostVisitControlFlow(Walker* self, Expression** currp) {
- auto* curr = *currp;
- if (auto* block = curr->dynCast<Block>()) {
- if (block->name.is()) {
- self->mapper.popLabelName(block->name);
- }
- } else if (auto* loop = curr->dynCast<Loop>()) {
- if (loop->name.is()) {
- self->mapper.popLabelName(loop->name);
+ BranchUtils::operateOnScopeNameDefs(*currp, [&](Name& name) {
+ if (name.is()) {
+ self->mapper.popLabelName(name);
}
- }
+ });
}
- void visitBreak(Break* curr) {
- curr->name = mapper.sourceToUnique(curr->name);
- }
- void visitSwitch(Switch* curr) {
- for (auto& target : curr->targets) {
- target = mapper.sourceToUnique(target);
- }
- curr->default_ = mapper.sourceToUnique(curr->default_);
+ void visitExpression(Expression* curr) {
+ BranchUtils::operateOnScopeNameUses(curr, [&](Name& name) {
+ if (name.is()) {
+ name = mapper.sourceToUnique(name);
+ }
+ });
}
};
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 97146a7c4..e95950bb5 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2098,6 +2098,9 @@ void FunctionValidator::visitTry(Try* curr) {
shouldBeTrue(getModule()->features.hasExceptionHandling(),
curr,
"try requires exception-handling to be enabled");
+ if (curr->name.is()) {
+ noteLabelName(curr->name);
+ }
if (curr->type != Type::unreachable) {
shouldBeSubTypeOrFirstIsUnreachable(
curr->body->type,
diff --git a/test/passes/inlining_all-features.txt b/test/passes/inlining_all-features.txt
index e23736fac..e0ecf57b5 100644
--- a/test/passes/inlining_all-features.txt
+++ b/test/passes/inlining_all-features.txt
@@ -53,3 +53,29 @@
)
)
)
+(module
+ (type $i32_=>_none (func (param i32)))
+ (type $none_=>_i32 (func (result i32)))
+ (import "a" "b" (func $foo (result i32)))
+ (event $event$0 (attr 0) (param i32))
+ (export "exported" (func $1))
+ (func $1 (param $x i32)
+ (loop $label
+ (block
+ (block $__inlined_func$0
+ (try $label0
+ (do
+ (nop)
+ )
+ (catch $event$0
+ (nop)
+ )
+ )
+ )
+ )
+ (br_if $label
+ (call $foo)
+ )
+ )
+ )
+)
diff --git a/test/passes/inlining_all-features.wast b/test/passes/inlining_all-features.wast
index 863daad9b..3890d63a1 100644
--- a/test/passes/inlining_all-features.wast
+++ b/test/passes/inlining_all-features.wast
@@ -43,3 +43,24 @@
(call $0)
)
)
+;; properly ensure unique try labels after an inlining
+(module
+ (import "a" "b" (func $foo (result i32)))
+ (event $event$0 (attr 0) (param i32))
+ (func $0
+ (try $label
+ (do)
+ (catch $event$0
+ (nop)
+ )
+ )
+ )
+ (func "exported" (param $x i32)
+ (loop $label ;; the same label as the try that will be inlined into here
+ (call $0)
+ (br_if $label
+ (call $foo)
+ )
+ )
+ )
+)