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.h48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/ir/branch-utils.h b/src/ir/branch-utils.h
index a9561ef07..8a4f02a58 100644
--- a/src/ir/branch-utils.h
+++ b/src/ir/branch-utils.h
@@ -40,9 +40,9 @@ inline bool isBranchReachable(Expression* expr) {
return true;
}
-// Perform a generic operation on uses of scope names (branch targets) in an
-// expression. The provided function receives a Name& which it can modify if it
-// needs to.
+// Perform a generic operation on uses of scope names (branch + delegate
+// targets) in an expression. The provided function receives a Name& which it
+// can modify if it needs to.
template<typename T> void operateOnScopeNameUses(Expression* expr, T func) {
#define DELEGATE_ID expr->_id
@@ -83,7 +83,7 @@ void operateOnScopeNameUsesAndSentTypes(Expression* expr, T func) {
} else if (auto* br = expr->dynCast<BrOn>()) {
func(name, br->getCastType());
} else {
- WASM_UNREACHABLE("bad br type");
+ assert(expr->is<Try>()); // delegate
}
});
}
@@ -135,6 +135,46 @@ inline bool replacePossibleTarget(Expression* branch, Name from, Name to) {
return worked;
}
+// Replace all delegate targets within the given AST.
+inline void replaceDelegateTargets(Expression* ast, Name from, Name to) {
+ struct Replacer
+ : public PostWalker<Replacer, UnifiedExpressionVisitor<Replacer>> {
+ Name from, to;
+ Replacer(Name from, Name to) : from(from), to(to) {}
+ void visitExpression(Expression* curr) {
+ if (curr->is<Try>()) {
+ operateOnScopeNameUses(curr, [&](Name& name) {
+ if (name == from) {
+ name = to;
+ }
+ });
+ }
+ }
+ };
+ Replacer replacer(from, to);
+ replacer.walk(ast);
+}
+
+// Replace all branch targets within the given AST.
+inline void replaceBranchTargets(Expression* ast, Name from, Name to) {
+ struct Replacer
+ : public PostWalker<Replacer, UnifiedExpressionVisitor<Replacer>> {
+ Name from, to;
+ Replacer(Name from, Name to) : from(from), to(to) {}
+ void visitExpression(Expression* curr) {
+ if (Properties::isBranch(curr)) {
+ operateOnScopeNameUses(curr, [&](Name& name) {
+ if (name == from) {
+ name = to;
+ }
+ });
+ }
+ }
+ };
+ Replacer replacer(from, to);
+ replacer.walk(ast);
+}
+
// Returns the set of targets to which we branch that are
// outside of an expression.
inline NameSet getExitingBranches(Expression* ast) {