diff options
Diffstat (limited to 'src/passes')
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 16 | ||||
-rw-r--r-- | src/passes/Precompute.cpp | 4 | ||||
-rw-r--r-- | src/passes/Print.cpp | 120 | ||||
-rw-r--r-- | src/passes/RemoveUnusedNames.cpp | 6 |
4 files changed, 119 insertions, 27 deletions
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index 61d16afc0..f913c5a93 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -144,6 +144,14 @@ struct DeadCodeElimination reachable = false; } + void visitBrOnExn(BrOnExn* curr) { + if (isDead(curr->exnref)) { + replaceCurrent(curr->exnref); + return; + } + addBreak(curr->name); + } + void visitReturn(Return* curr) { if (isDead(curr->value)) { replaceCurrent(curr->value); @@ -312,6 +320,14 @@ struct DeadCodeElimination DELEGATE(Push); case Expression::Id::PopId: DELEGATE(Pop); + case Expression::Id::TryId: + DELEGATE(Try); + case Expression::Id::ThrowId: + DELEGATE(Throw); + case Expression::Id::RethrowId: + DELEGATE(Rethrow); + case Expression::Id::BrOnExnId: + DELEGATE(BrOnExn); case Expression::Id::InvalidId: WASM_UNREACHABLE(); case Expression::Id::NumExpressionIds: diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 55ff9e264..c4d90de04 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -130,6 +130,10 @@ public: Flow visitMemoryCopy(MemoryCopy* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } Flow visitMemoryFill(MemoryFill* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } Flow visitHost(Host* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } + Flow visitTry(Try* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } + Flow visitThrow(Throw* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } + Flow visitRethrow(Rethrow* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } + Flow visitBrOnExn(BrOnExn* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } Flow visitPush(Push* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } Flow visitPop(Pop* curr) { return Flow(NOTPRECOMPUTABLE_FLOW); } diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 812a69692..0bf61e784 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1162,6 +1162,23 @@ struct PrintExpressionContents break; } } + void visitTry(Try* curr) { + printMedium(o, "try"); + if (isConcreteType(curr->type)) { + o << " (result " << printType(curr->type) << ')'; + } + } + void visitThrow(Throw* curr) { + printMedium(o, "throw "); + printName(curr->event, o); + } + void visitRethrow(Rethrow* curr) { printMedium(o, "rethrow"); } + void visitBrOnExn(BrOnExn* curr) { + printMedium(o, "br_on_exn "); + printName(curr->name, o); + o << " "; + printName(curr->event, o); + } void visitNop(Nop* curr) { printMinor(o, "nop"); } void visitUnreachable(Unreachable* curr) { printMinor(o, "unreachable"); } void visitPush(Push* curr) { prepareColor(o) << "push"; } @@ -1260,6 +1277,20 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { o << maybeNewLine; } + // loop, if, and try can contain implicit blocks. But they are not needed to + // be printed in some cases. + void maybePrintImplicitBlock(Expression* curr, bool allowMultipleInsts) { + auto block = curr->dynCast<Block>(); + if (!full && block && block->name.isNull() && + (allowMultipleInsts || block->list.size() == 1)) { + for (auto expression : block->list) { + printFullLine(expression); + } + } else { + printFullLine(curr); + } + } + void visitBlock(Block* curr) { // special-case Block, because Block nesting (in their first element) can be // incredibly deep @@ -1319,22 +1350,9 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { PrintExpressionContents(currFunction, o).visit(curr); incIndent(); printFullLine(curr->condition); - // ifTrue and False have implict blocks, avoid printing them if possible - if (!full && curr->ifTrue->is<Block>() && - curr->ifTrue->dynCast<Block>()->name.isNull() && - curr->ifTrue->dynCast<Block>()->list.size() == 1) { - printFullLine(curr->ifTrue->dynCast<Block>()->list.back()); - } else { - printFullLine(curr->ifTrue); - } + maybePrintImplicitBlock(curr->ifTrue, false); if (curr->ifFalse) { - if (!full && curr->ifFalse->is<Block>() && - curr->ifFalse->dynCast<Block>()->name.isNull() && - curr->ifFalse->dynCast<Block>()->list.size() == 1) { - printFullLine(curr->ifFalse->dynCast<Block>()->list.back()); - } else { - printFullLine(curr->ifFalse); - } + maybePrintImplicitBlock(curr->ifFalse, false); } decIndent(); if (full) { @@ -1345,16 +1363,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { o << '('; PrintExpressionContents(currFunction, o).visit(curr); incIndent(); - auto block = curr->body->dynCast<Block>(); - if (!full && block && block->name.isNull()) { - // wasm spec has loops containing children directly, while our ast - // has a single child for simplicity. print out the optimal form. - for (auto expression : block->list) { - printFullLine(expression); - } - } else { - printFullLine(curr->body); - } + maybePrintImplicitBlock(curr->body, true); decIndent(); if (full) { o << " ;; end loop"; @@ -1631,6 +1640,54 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { } } } + // try-catch-end is written in the folded wast format as + // (try + // ... + // (catch + // ... + // ) + // ) + // The parenthesis wrapping 'catch' is just a syntax and does not affect + // nested depths of instructions within. + void visitTry(Try* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + maybePrintImplicitBlock(curr->body, true); + doIndent(o, indent); + o << "(catch"; + incIndent(); + maybePrintImplicitBlock(curr->catchBody, true); + decIndent(); + o << "\n"; + decIndent(); + if (full) { + o << " ;; end try"; + } + } + void visitThrow(Throw* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); + } + decIndent(); + } + void visitRethrow(Rethrow* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->exnref); + decIndent(); + } + void visitBrOnExn(BrOnExn* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->exnref); + decIndent(); + } void visitNop(Nop* curr) { o << '('; PrintExpressionContents(currFunction, o).visit(curr); @@ -2198,7 +2255,8 @@ WasmPrinter::printStackIR(StackIR* ir, std::ostream& o, Function* func) { } case StackInst::BlockBegin: case StackInst::IfBegin: - case StackInst::LoopBegin: { + case StackInst::LoopBegin: + case StackInst::TryBegin: { doIndent(); PrintExpressionContents(func, o).visit(inst->origin); indent++; @@ -2206,7 +2264,8 @@ WasmPrinter::printStackIR(StackIR* ir, std::ostream& o, Function* func) { } case StackInst::BlockEnd: case StackInst::IfEnd: - case StackInst::LoopEnd: { + case StackInst::LoopEnd: + case StackInst::TryEnd: { indent--; doIndent(); o << "end"; @@ -2219,6 +2278,13 @@ WasmPrinter::printStackIR(StackIR* ir, std::ostream& o, Function* func) { indent++; break; } + case StackInst::Catch: { + indent--; + doIndent(); + o << "catch"; + indent++; + break; + } default: WASM_UNREACHABLE(); } diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp index 3db5a2173..3b04522ad 100644 --- a/src/passes/RemoveUnusedNames.cpp +++ b/src/passes/RemoveUnusedNames.cpp @@ -42,6 +42,8 @@ struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames>> { branchesSeen[curr->default_].insert(curr); } + void visitBrOnExn(BrOnExn* curr) { branchesSeen[curr->name].insert(curr); } + void handleBreakTarget(Name& name) { if (name.is()) { if (branchesSeen.find(name) == branchesSeen.end()) { @@ -73,6 +75,10 @@ struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames>> { if (sw->default_ == curr->name) { sw->default_ = child->name; } + } else if (BrOnExn* br = branch->dynCast<BrOnExn>()) { + if (br->name == curr->name) { + br->name = child->name; + } } else { WASM_UNREACHABLE(); } |