summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/DeadCodeElimination.cpp16
-rw-r--r--src/passes/Precompute.cpp4
-rw-r--r--src/passes/Print.cpp120
-rw-r--r--src/passes/RemoveUnusedNames.cpp6
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();
}