summaryrefslogtreecommitdiff
path: root/src/ir/branch-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/branch-utils.h')
-rw-r--r--src/ir/branch-utils.h43
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;