diff options
Diffstat (limited to 'src/ir/branch-utils.h')
-rw-r--r-- | src/ir/branch-utils.h | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/src/ir/branch-utils.h b/src/ir/branch-utils.h index ce7d7b0f6..976dd72ec 100644 --- a/src/ir/branch-utils.h +++ b/src/ir/branch-utils.h @@ -37,20 +37,22 @@ inline bool isBranchReachable(Switch* sw) { sw->condition->type != unreachable; } +inline bool isBranchReachable(BrOnExn* br) { + return br->exnref->type != unreachable; +} + inline bool isBranchReachable(Expression* expr) { if (auto* br = expr->dynCast<Break>()) { return isBranchReachable(br); } else if (auto* sw = expr->dynCast<Switch>()) { return isBranchReachable(sw); + } else if (auto* br = expr->dynCast<BrOnExn>()) { + return isBranchReachable(br); } WASM_UNREACHABLE(); } -inline std::set<Name> getUniqueTargets(Break* br) { - std::set<Name> ret; - ret.insert(br->name); - return ret; -} +inline std::set<Name> getUniqueTargets(Break* br) { return {br->name}; } inline std::set<Name> getUniqueTargets(Switch* sw) { std::set<Name> ret; @@ -61,6 +63,8 @@ inline std::set<Name> getUniqueTargets(Switch* sw) { return ret; } +inline std::set<Name> getUniqueTargets(BrOnExn* br) { return {br->name}; } + // If we branch to 'from', change that to 'to' instead. inline bool replacePossibleTarget(Expression* branch, Name from, Name to) { bool worked = false; @@ -80,6 +84,11 @@ inline bool replacePossibleTarget(Expression* branch, Name from, Name to) { sw->default_ = to; worked = true; } + } else if (auto* br = branch->dynCast<BrOnExn>()) { + if (br->name == from) { + br->name = to; + worked = true; + } } else { WASM_UNREACHABLE(); } @@ -99,6 +108,7 @@ inline std::set<Name> getExitingBranches(Expression* ast) { } targets.insert(curr->default_); } + void visitBrOnExn(BrOnExn* curr) { targets.insert(curr->name); } void visitBlock(Block* curr) { if (curr->name.is()) { targets.erase(curr->name); @@ -153,15 +163,15 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { BranchSeeker(Name target) : target(target) {} - void noteFound(Expression* value) { + void noteFound(Expression* value) { noteFound(value ? value->type : none); } + + void noteFound(Type type) { found++; if (found == 1) { valueType = unreachable; } - if (!value) { - valueType = none; - } else if (value->type != unreachable) { - valueType = value->type; + if (type != unreachable) { + valueType = type; } } @@ -202,6 +212,19 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { } } + void visitBrOnExn(BrOnExn* curr) { + if (!named) { + // ignore an unreachable br_on_exn + if (curr->exnref->type == unreachable) { + return; + } + } + // check the br_on_exn + if (curr->name == target) { + noteFound(curr->getSingleSentType()); + } + } + static bool hasReachable(Expression* tree, Name target) { if (!target.is()) { return false; |