diff options
Diffstat (limited to 'src/ir')
-rw-r--r-- | src/ir/ExpressionAnalyzer.cpp | 7 | ||||
-rw-r--r-- | src/ir/ExpressionManipulator.cpp | 18 | ||||
-rw-r--r-- | src/ir/ReFinalize.cpp | 9 | ||||
-rw-r--r-- | src/ir/branch-utils.h | 43 | ||||
-rw-r--r-- | src/ir/effects.h | 5 | ||||
-rw-r--r-- | src/ir/type-updating.h | 10 | ||||
-rw-r--r-- | src/ir/utils.h | 8 |
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(); } |