diff options
author | Alon Zakai <azakai@google.com> | 2021-03-01 15:04:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-01 07:04:54 -0800 |
commit | 27a841eec6ceb171caae2a2cbd7c92ecdf8d78eb (patch) | |
tree | 2d03ee70c25165ba319e1b98e780350553f44c9a | |
parent | 7d453930f1b211baf324b1c010924d3709ff12ba (diff) | |
download | binaryen-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.h | 45 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 3 | ||||
-rw-r--r-- | test/passes/inlining_all-features.txt | 26 | ||||
-rw-r--r-- | test/passes/inlining_all-features.wast | 21 |
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) + ) + ) + ) +) |