summaryrefslogtreecommitdiff
path: root/src/ir
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir')
-rw-r--r--src/ir/ExpressionAnalyzer.cpp7
-rw-r--r--src/ir/ExpressionManipulator.cpp18
-rw-r--r--src/ir/ReFinalize.cpp9
-rw-r--r--src/ir/branch-utils.h43
-rw-r--r--src/ir/effects.h5
-rw-r--r--src/ir/type-updating.h10
-rw-r--r--src/ir/utils.h8
7 files changed, 89 insertions, 11 deletions
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp
index 99c2798b0..f8f96d5c8 100644
--- a/src/ir/ExpressionAnalyzer.cpp
+++ b/src/ir/ExpressionAnalyzer.cpp
@@ -211,6 +211,13 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) {
visitor.visitInt(curr->op);
visitor.visitNonScopeName(curr->nameOperand);
}
+ void visitTry(Try* curr) {}
+ void visitThrow(Throw* curr) { visitor.visitNonScopeName(curr->event); }
+ void visitRethrow(Rethrow* curr) {}
+ void visitBrOnExn(BrOnExn* curr) {
+ visitor.visitScopeName(curr->name);
+ visitor.visitNonScopeName(curr->event);
+ }
void visitNop(Nop* curr) {}
void visitUnreachable(Unreachable* curr) {}
void visitPush(Push* curr) {}
diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp
index 817dce561..e650f40a7 100644
--- a/src/ir/ExpressionManipulator.cpp
+++ b/src/ir/ExpressionManipulator.cpp
@@ -219,6 +219,24 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
return ret;
}
+ Expression* visitTry(Try* curr) {
+ return builder.makeTry(
+ copy(curr->body), copy(curr->catchBody), curr->type);
+ }
+ Expression* visitThrow(Throw* curr) {
+ std::vector<Expression*> operands;
+ for (Index i = 0; i < curr->operands.size(); i++) {
+ operands.push_back(copy(curr->operands[i]));
+ }
+ return builder.makeThrow(curr->event, std::move(operands));
+ }
+ Expression* visitRethrow(Rethrow* curr) {
+ return builder.makeRethrow(copy(curr->exnref));
+ }
+ Expression* visitBrOnExn(BrOnExn* curr) {
+ return builder.makeBrOnExn(
+ curr->name, curr->event, copy(curr->exnref), curr->eventParams);
+ }
Expression* visitNop(Nop* curr) { return builder.makeNop(); }
Expression* visitUnreachable(Unreachable* curr) {
return builder.makeUnreachable();
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index 9e3b59c70..05abb76e1 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -62,6 +62,8 @@ void ReFinalize::visitBlock(Block* curr) {
auto type = iter->second;
if (type == none) {
// we need to fix this up. set the values to unreachables
+ // note that we don't need to handle br_on_exn here, because its value
+ // type is never none
for (auto* br : FindAll<Break>(curr).list) {
handleBranchForVisitBlock(br, curr->name, getModule());
}
@@ -155,6 +157,13 @@ void ReFinalize::visitSelect(Select* curr) { curr->finalize(); }
void ReFinalize::visitDrop(Drop* curr) { curr->finalize(); }
void ReFinalize::visitReturn(Return* curr) { curr->finalize(); }
void ReFinalize::visitHost(Host* curr) { curr->finalize(); }
+void ReFinalize::visitTry(Try* curr) { curr->finalize(); }
+void ReFinalize::visitThrow(Throw* curr) { curr->finalize(); }
+void ReFinalize::visitRethrow(Rethrow* curr) { curr->finalize(); }
+void ReFinalize::visitBrOnExn(BrOnExn* curr) {
+ curr->finalize();
+ updateBreakValueType(curr->name, curr->getSingleSentType());
+}
void ReFinalize::visitNop(Nop* curr) { curr->finalize(); }
void ReFinalize::visitUnreachable(Unreachable* curr) { curr->finalize(); }
void ReFinalize::visitPush(Push* curr) { curr->finalize(); }
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;
diff --git a/src/ir/effects.h b/src/ir/effects.h
index dac5b878a..e3997f5d2 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -374,6 +374,11 @@ struct EffectAnalyzer
// Atomics are also sequentially consistent with memory.grow.
isAtomic = true;
}
+ void visitTry(Try* curr) {}
+ // We safely model throws as branches
+ void visitThrow(Throw* curr) { branches = true; }
+ void visitRethrow(Rethrow* curr) { branches = true; }
+ void visitBrOnExn(BrOnExn* curr) { breakNames.insert(curr->name); }
void visitNop(Nop* curr) {}
void visitUnreachable(Unreachable* curr) { branches = true; }
void visitPush(Push* curr) { calls = true; }
diff --git a/src/ir/type-updating.h b/src/ir/type-updating.h
index ef9fe78e9..09b1b4bdc 100644
--- a/src/ir/type-updating.h
+++ b/src/ir/type-updating.h
@@ -65,6 +65,8 @@ struct TypeUpdater
blockInfos[target];
}
blockInfos[sw->default_];
+ } else if (auto* br = curr->dynCast<BrOnExn>()) {
+ blockInfos[br->name];
}
// add a break to the info, for break and switch
discoverBreaks(curr, +1);
@@ -151,6 +153,8 @@ struct TypeUpdater
noteBreakChange(br->name, change, br->value);
} else if (auto* sw = curr->dynCast<Switch>()) {
applySwitchChanges(sw, change);
+ } else if (auto* br = curr->dynCast<BrOnExn>()) {
+ noteBreakChange(br->name, change, br->getSingleSentType());
}
}
@@ -168,6 +172,10 @@ struct TypeUpdater
// note the addition of a node
void noteBreakChange(Name name, int change, Expression* value) {
+ noteBreakChange(name, change, value ? value->type : none);
+ }
+
+ void noteBreakChange(Name name, int change, Type type) {
auto iter = blockInfos.find(name);
if (iter == blockInfos.end()) {
return; // we can ignore breaks to loops
@@ -186,7 +194,7 @@ struct TypeUpdater
if (block->type != unreachable) {
return; // was already reachable, had a fallthrough
}
- changeTypeTo(block, value ? value->type : none);
+ changeTypeTo(block, type);
}
}
}
diff --git a/src/ir/utils.h b/src/ir/utils.h
index ae6368e3b..5c6a09290 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -144,6 +144,10 @@ struct ReFinalize
void visitDrop(Drop* curr);
void visitReturn(Return* curr);
void visitHost(Host* curr);
+ void visitTry(Try* curr);
+ void visitThrow(Throw* curr);
+ void visitRethrow(Rethrow* curr);
+ void visitBrOnExn(BrOnExn* curr);
void visitNop(Nop* curr);
void visitUnreachable(Unreachable* curr);
void visitPush(Push* curr);
@@ -203,6 +207,10 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitDrop(Drop* curr) { curr->finalize(); }
void visitReturn(Return* curr) { curr->finalize(); }
void visitHost(Host* curr) { curr->finalize(); }
+ void visitTry(Try* curr) { curr->finalize(); }
+ void visitThrow(Throw* curr) { curr->finalize(); }
+ void visitRethrow(Rethrow* curr) { curr->finalize(); }
+ void visitBrOnExn(BrOnExn* curr) { curr->finalize(); }
void visitNop(Nop* curr) { curr->finalize(); }
void visitUnreachable(Unreachable* curr) { curr->finalize(); }
void visitPush(Push* curr) { curr->finalize(); }