summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-05-26 14:10:03 -0700
committerGitHub <noreply@github.com>2021-05-26 14:10:03 -0700
commit27a18f990e022cfe5b6a5485fd2eaca73b6dfbaa (patch)
tree9c37ba9241483c12ca511ee3b0d6cadf003cd68d /src
parent7f31823120ba25075d783df863f6be536543f805 (diff)
downloadbinaryen-27a18f990e022cfe5b6a5485fd2eaca73b6dfbaa.tar.gz
binaryen-27a18f990e022cfe5b6a5485fd2eaca73b6dfbaa.tar.bz2
binaryen-27a18f990e022cfe5b6a5485fd2eaca73b6dfbaa.zip
[Wasm GC] Implement CFGWalker support for BrOn* (#3908)
Without adding logic there, it simply ignored the branch, which could lead to bad optimizations (thinking code is unreachable when it was). There isn't a trivial way to add a static error to force us to add new classes to CFGWalker. But this PR generalizes the code there to handle all branches and all unreachable instructions in a generic way. The only thing we'll need to remember to do in the future is to add control flow structures. (And normally the fuzzer should quickly find such bugs, but we don't have full fuzzing enabled for GC yet.) Fixes #3907
Diffstat (limited to 'src')
-rw-r--r--src/cfg/cfg-traversal.h57
1 files changed, 17 insertions, 40 deletions
diff --git a/src/cfg/cfg-traversal.h b/src/cfg/cfg-traversal.h
index 3f2eecb88..f66dc8d3f 100644
--- a/src/cfg/cfg-traversal.h
+++ b/src/cfg/cfg-traversal.h
@@ -30,6 +30,7 @@
#ifndef cfg_traversal_h
#define cfg_traversal_h
+#include "ir/branch-utils.h"
#include "wasm-traversal.h"
#include "wasm.h"
@@ -203,11 +204,15 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
self->loopStack.pop_back();
}
- static void doEndBreak(SubType* self, Expression** currp) {
- auto* curr = (*currp)->cast<Break>();
- self->branches[self->findBreakTarget(curr->name)].push_back(
- self->currBasicBlock); // branch to the target
- if (curr->condition) {
+ static void doEndBranch(SubType* self, Expression** currp) {
+ auto* curr = *currp;
+ auto branchTargets = BranchUtils::getUniqueTargets(curr);
+ // Add branches to the targets.
+ for (auto target : branchTargets) {
+ self->branches[self->findBreakTarget(target)].push_back(
+ self->currBasicBlock);
+ }
+ if (curr->type != Type::unreachable) {
auto* last = self->currBasicBlock;
self->link(last, self->startBasicBlock()); // we might fall through
} else {
@@ -215,24 +220,6 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
}
}
- static void doEndSwitch(SubType* self, Expression** currp) {
- auto* curr = (*currp)->cast<Switch>();
- // we might see the same label more than once; do not spam branches
- std::set<Name> seen;
- for (Name target : curr->targets) {
- if (!seen.count(target)) {
- self->branches[self->findBreakTarget(target)].push_back(
- self->currBasicBlock); // branch to the target
- seen.insert(target);
- }
- }
- if (!seen.count(curr->default_)) {
- self->branches[self->findBreakTarget(curr->default_)].push_back(
- self->currBasicBlock); // branch to the target
- }
- self->startUnreachableBlock();
- }
-
static void doEndThrowingInst(SubType* self, Expression** currp) {
// Even if the instruction can possibly throw, we don't end the current
// basic block unless the instruction is within a try-catch, because the CFG
@@ -366,22 +353,6 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
self->pushTask(SubType::doEndLoop, currp);
break;
}
- case Expression::Id::BreakId: {
- self->pushTask(SubType::doEndBreak, currp);
- break;
- }
- case Expression::Id::SwitchId: {
- self->pushTask(SubType::doEndSwitch, currp);
- break;
- }
- case Expression::Id::ReturnId: {
- self->pushTask(SubType::doStartUnreachableBlock, currp);
- break;
- }
- case Expression::Id::UnreachableId: {
- self->pushTask(SubType::doStartUnreachableBlock, currp);
- break;
- }
case Expression::Id::CallId:
case Expression::Id::CallIndirectId: {
self->pushTask(SubType::doEndCall, currp);
@@ -405,7 +376,13 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
self->pushTask(SubType::doEndThrow, currp);
break;
}
- default: {}
+ default: {
+ if (Properties::isBranch(curr)) {
+ self->pushTask(SubType::doEndBranch, currp);
+ } else if (curr->type == Type::unreachable) {
+ self->pushTask(SubType::doStartUnreachableBlock, currp);
+ }
+ }
}
ControlFlowWalker<SubType, VisitorType>::scan(self, currp);