diff options
-rw-r--r-- | src/ast/branch-utils.h | 22 | ||||
-rw-r--r-- | src/ast_utils.h | 2 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 4 | ||||
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 2 | ||||
-rw-r--r-- | src/wasm-validator.h | 1 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 11 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 7 |
7 files changed, 21 insertions, 28 deletions
diff --git a/src/ast/branch-utils.h b/src/ast/branch-utils.h index 05ead8571..d574945ef 100644 --- a/src/ast/branch-utils.h +++ b/src/ast/branch-utils.h @@ -24,24 +24,23 @@ namespace wasm { namespace BranchUtils { -// branches not actually taken (e.g. (br $out (unreachable))) -// are trivially ignored in our type system +// Some branches are obviously not actually reachable (e.g. (br $out (unreachable))) -inline bool isBranchTaken(Break* br) { +inline bool isBranchReachable(Break* br) { return !(br->value && br->value->type == unreachable) && !(br->condition && br->condition->type == unreachable); } -inline bool isBranchTaken(Switch* sw) { +inline bool isBranchReachable(Switch* sw) { return !(sw->value && sw->value->type == unreachable) && sw->condition->type != unreachable; } -inline bool isBranchTaken(Expression* expr) { +inline bool isBranchReachable(Expression* expr) { if (auto* br = expr->dynCast<Break>()) { - return isBranchTaken(br); + return isBranchReachable(br); } else if (auto* sw = expr->dynCast<Switch>()) { - return isBranchTaken(sw); + return isBranchReachable(sw); } WASM_UNREACHABLE(); } @@ -103,8 +102,9 @@ inline std::set<Name> getBranchTargets(Expression* ast) { // Finds if there are branches targeting a name. Note that since names are // unique in our IR, we just need to look for the name, and do not need // to analyze scoping. -// By default we consider untaken branches (so any named use). You can unset named to -// avoid that (and only note branches that are not obviously unreachable) +// By default we consider all branches, so any place there is a branch that +// names the target. You can unset 'named' to only note branches that appear +// reachable (i.e., are not obviously unreachable). struct BranchSeeker : public PostWalker<BranchSeeker> { Name target; bool named = true; @@ -144,7 +144,7 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { if (curr->default_ == target) noteFound(curr->value); } - static bool hasTaken(Expression* tree, Name target) { + static bool hasReachable(Expression* tree, Name target) { if (!target.is()) return false; BranchSeeker seeker(target); seeker.named = false; @@ -152,7 +152,7 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { return seeker.found > 0; } - static Index countTaken(Expression* tree, Name target) { + static Index countReachable(Expression* tree, Name target) { if (!target.is()) return 0; BranchSeeker seeker(target); seeker.named = false; diff --git a/src/ast_utils.h b/src/ast_utils.h index 852cf89a3..95f725636 100644 --- a/src/ast_utils.h +++ b/src/ast_utils.h @@ -62,7 +62,7 @@ struct ExpressionAnalyzer { if (auto* br = curr->dynCast<Break>()) { if (!br->condition) return true; } else if (auto* block = curr->dynCast<Block>()) { - if (block->list.size() > 0 && obviouslyDoesNotFlowOut(block->list.back()) && !BranchUtils::BranchSeeker::hasTaken(block, block->name)) return true; + if (block->list.size() > 0 && obviouslyDoesNotFlowOut(block->list.back()) && !BranchUtils::BranchSeeker::hasReachable(block, block->name)) return true; } return false; } diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index ec7809f48..7e122b806 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -31,7 +31,7 @@ namespace wasm { // condition and possible value, and the possible value must // not have side effects (as they would run unconditionally) static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue, PassOptions& options) { - // if the if isn't even taken, this is all dead code anyhow + // if the if isn't even reached, this is all dead code anyhow if (ifCondition->type == unreachable) return false; if (!brValue) return true; EffectAnalyzer value(options, brValue); @@ -512,7 +512,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { if (curr->name.is()) { auto* br = list[0]->dynCast<Break>(); // we seek a regular br_if; if the type is unreachable that means it is not - // actually taken, so ignore + // actually reached, so ignore if (br && br->condition && br->name == curr->name && br->type != unreachable) { assert(!br->value); // can't, it would be dropped or last in the block if (BranchUtils::BranchSeeker::countNamed(curr, curr->name) == 1) { diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 919784cdf..618f8dead 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -348,7 +348,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>> auto* brp = breaks[j].brp; auto* br = (*brp)->cast<Break>(); assert(!br->value); - // if the break is conditional, then we must set the value here - if the break is not taken, we must still have the new value in the local + // if the break is conditional, then we must set the value here - if the break is not reached, we must still have the new value in the local auto* set = (*breakSetLocalPointer)->cast<SetLocal>(); if (br->condition) { br->value = set; diff --git a/src/wasm-validator.h b/src/wasm-validator.h index 35304d1c9..0851d33e8 100644 --- a/src/wasm-validator.h +++ b/src/wasm-validator.h @@ -78,7 +78,6 @@ struct WasmValidator : public PostWalker<WasmValidator> { std::map<Name, Expression*> breakTargets; std::map<Expression*, BreakInfo> breakInfos; - std::set<Name> namedBreakTargets; // even breaks not taken must not be named if they go to a place that does not exist WasmType returnType = unreachable; // type used in returns diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index f0787600e..9c0e5cd37 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -670,7 +670,7 @@ void WasmBinaryWriter::visitBreak(Break *curr) { // then either the condition or the value is unreachable, which is // extremely rare, and may require us to make the stack polymorphic // (if the block we branch to has a value, we may lack one as we - // are not a taken branch; the wasm spec on the other hand does + // are not a reachable branch; the wasm spec on the other hand does // presume the br_if emits a value of the right type, even if it // popped unreachable) o << int8_t(BinaryConsts::Unreachable); @@ -683,11 +683,10 @@ void WasmBinaryWriter::visitSwitch(Switch *curr) { recurse(curr->value); } recurse(curr->condition); - if (!BranchUtils::isBranchTaken(curr)) { - // if the branch is not taken, then it's dangerous to emit it, as - // wasm type checking rules are stricter than ours - we tolerate - // an untaken branch to a target with a different value, but not - // wasm. so just don't emit it + if (!BranchUtils::isBranchReachable(curr)) { + // if the branch is not reachable, then it's dangerous to emit it, as + // wasm type checking rules are different, especially in unreachable + // code. so just don't emit that unreachable code. o << int8_t(BinaryConsts::Unreachable); return; } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 877232521..8e93b1c38 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -58,7 +58,6 @@ void WasmValidator::visitBlock(Block *curr) { } } breakTargets.erase(curr->name); - namedBreakTargets.erase(curr->name); } if (curr->list.size() > 1) { for (Index i = 0; i < curr->list.size() - 1; i++) { @@ -88,7 +87,6 @@ void WasmValidator::visitLoop(Loop *curr) { if (curr->name.is()) { noteLabelName(curr->name); breakTargets.erase(curr->name); - namedBreakTargets.erase(curr->name); if (breakInfos.count(curr) > 0) { auto& info = breakInfos[curr]; shouldBeEqual(info.arity, Index(0), curr, "breaks to a loop cannot pass a value"); @@ -128,7 +126,6 @@ void WasmValidator::visitIf(If *curr) { } void WasmValidator::noteBreak(Name name, Expression* value, Expression* curr) { - namedBreakTargets.insert(name); WasmType valueType = none; Index arity = 0; if (value) { @@ -550,9 +547,7 @@ void WasmValidator::visitFunction(Function *curr) { if (returnType != unreachable) { shouldBeEqual(curr->result, returnType, curr->body, "function result must match, if function has returns"); } - if (!shouldBeTrue(namedBreakTargets.empty(), curr->body, "all named break targets must exist") && !quiet) { - std::cerr << "(on label " << *namedBreakTargets.begin() << ")\n"; - } + shouldBeTrue(breakTargets.empty(), curr->body, "all named break targets must exist"); returnType = unreachable; labelNames.clear(); } |