summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/Poppify.cpp8
-rw-r--r--src/passes/Print.cpp77
-rw-r--r--src/passes/RemoveUnusedNames.cpp2
-rw-r--r--src/passes/StackIR.cpp4
4 files changed, 85 insertions, 6 deletions
diff --git a/src/passes/Poppify.cpp b/src/passes/Poppify.cpp
index b0d07e60c..2ab222697 100644
--- a/src/passes/Poppify.cpp
+++ b/src/passes/Poppify.cpp
@@ -128,6 +128,7 @@ struct Poppifier : BinaryenIRWriter<Poppifier> {
void emitIfElse(If* curr);
void emitCatch(Try* curr, Index i);
void emitCatchAll(Try* curr);
+ void emitDelegate(Try* curr);
void emitScopeEnd(Expression* curr);
void emitFunctionEnd();
void emitUnreachable();
@@ -272,6 +273,13 @@ void Poppifier::emitCatchAll(Try* curr) {
scopeStack.emplace_back(Scope::Catch);
}
+void Poppifier::emitDelegate(Try* curr) {
+ auto& scope = scopeStack.back();
+ assert(scope.kind == Scope::Try);
+ patchScope(curr->body);
+ scopeStack.back().instrs.push_back(curr);
+}
+
void Poppifier::emitScopeEnd(Expression* curr) {
switch (scopeStack.back().kind) {
case Scope::Block:
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index e49735af0..9b59de444 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1764,6 +1764,10 @@ struct PrintExpressionContents
void visitRefEq(RefEq* curr) { printMedium(o, "ref.eq"); }
void visitTry(Try* curr) {
printMedium(o, "try");
+ if (curr->name.is()) {
+ o << ' ';
+ printName(curr->name, o);
+ }
if (curr->type.isConcrete()) {
o << ' ' << ResultType(curr->type);
}
@@ -1955,6 +1959,9 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
Function::DebugLocation lastPrintedLocation;
bool debugInfo;
+ // Used to print delegate's depth argument when it throws to the caller
+ int controlFlowDepth = 0;
+
PrintSExpression(std::ostream& o) : o(o) {
setMinify(false);
if (!full) {
@@ -2100,6 +2107,9 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
break; // that's all we can recurse, start to unwind
}
}
+
+ int startControlFlowDepth = controlFlowDepth;
+ controlFlowDepth += stack.size();
auto* top = stack.back();
while (stack.size() > 0) {
curr = stack.back();
@@ -2129,8 +2139,10 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
o << ' ' << curr->name;
}
}
+ controlFlowDepth = startControlFlowDepth;
}
void visitIf(If* curr) {
+ controlFlowDepth++;
o << '(';
printExpressionContents(curr);
incIndent();
@@ -2147,8 +2159,10 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
if (full) {
o << " ;; end if";
}
+ controlFlowDepth--;
}
void visitLoop(Loop* curr) {
+ controlFlowDepth++;
o << '(';
printExpressionContents(curr);
incIndent();
@@ -2160,6 +2174,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
o << ' ' << curr->name;
}
}
+ controlFlowDepth--;
}
void visitBreak(Break* curr) {
o << '(';
@@ -2490,13 +2505,28 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
// (do
// ...
// )
- // (catch
- // ...
+ // (catch $e
+ // ...
+ // )
+ // ...
+ // (catch_all
+ // ...
// )
// )
- // The parenthesis wrapping 'catch' is just a syntax and does not affect
- // nested depths of instructions within.
+ // The parenthesis wrapping do/catch/catch_all is just a syntax and does not
+ // affect nested depths of instructions within.
+ //
+ // try-delegate is written in the forded format as
+ // (try
+ // (do
+ // ...
+ // )
+ // (delegate $label)
+ // )
+ // When the 'delegate' delegates to the caller, we write the argument as an
+ // immediate.
void visitTry(Try* curr) {
+ controlFlowDepth++;
o << '(';
printExpressionContents(curr);
incIndent();
@@ -2521,12 +2551,26 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
if (curr->hasCatchAll()) {
doIndent(o, indent);
printDebugDelimiterLocation(curr, curr->catchEvents.size());
- o << "(catch_all";
+ o << '(';
+ printMedium(o, "catch_all");
incIndent();
maybePrintImplicitBlock(curr->catchBodies.back(), true);
decIndent();
o << "\n";
}
+ controlFlowDepth--;
+
+ if (curr->isDelegate()) {
+ doIndent(o, indent);
+ o << '(';
+ printMedium(o, "delegate ");
+ if (curr->delegateTarget == DELEGATE_CALLER_TARGET) {
+ o << controlFlowDepth;
+ } else {
+ printName(curr->delegateTarget, o);
+ }
+ o << ")\n";
+ }
decIndent();
if (full) {
o << " ;; end try";
@@ -2913,6 +2957,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
} else {
printFullLine(curr->body);
}
+ assert(controlFlowDepth == 0);
} else {
// Print the stack IR.
printStackIR(curr->stackIR.get(), o, curr);
@@ -3324,6 +3369,11 @@ printStackInst(StackInst* inst, std::ostream& o, Function* func) {
printMedium(o, "catch_all");
break;
}
+ case StackInst::Delegate: {
+ printMedium(o, "delegate ");
+ printName(inst->origin->cast<Try>()->delegateTarget, o);
+ break;
+ }
default:
WASM_UNREACHABLE("unexpeted op");
}
@@ -3339,6 +3389,7 @@ printStackIR(StackIR* ir, std::ostream& o, Function* func) {
}
};
+ int controlFlowDepth = 0;
// Stack to track indices of catches within a try
SmallVector<Index, 4> catchIndexStack;
for (Index i = 0; i < (*ir).size(); i++) {
@@ -3364,6 +3415,7 @@ printStackIR(StackIR* ir, std::ostream& o, Function* func) {
case StackInst::BlockBegin:
case StackInst::IfBegin:
case StackInst::LoopBegin: {
+ controlFlowDepth++;
doIndent();
PrintExpressionContents(func, o).visit(inst->origin);
indent++;
@@ -3375,6 +3427,7 @@ printStackIR(StackIR* ir, std::ostream& o, Function* func) {
case StackInst::BlockEnd:
case StackInst::IfEnd:
case StackInst::LoopEnd: {
+ controlFlowDepth--;
indent--;
doIndent();
printMedium(o, "end");
@@ -3403,11 +3456,25 @@ printStackIR(StackIR* ir, std::ostream& o, Function* func) {
indent++;
break;
}
+ case StackInst::Delegate: {
+ controlFlowDepth--;
+ indent--;
+ doIndent();
+ printMedium(o, "delegate ");
+ Try* curr = inst->origin->cast<Try>();
+ if (curr->delegateTarget == DELEGATE_CALLER_TARGET) {
+ o << controlFlowDepth;
+ } else {
+ printName(curr->delegateTarget, o);
+ }
+ break;
+ }
default:
WASM_UNREACHABLE("unexpeted op");
}
std::cout << '\n';
}
+ assert(controlFlowDepth == 0);
return o;
}
diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp
index 64640aefe..53da00733 100644
--- a/src/passes/RemoveUnusedNames.cpp
+++ b/src/passes/RemoveUnusedNames.cpp
@@ -83,6 +83,8 @@ struct RemoveUnusedNames
}
}
+ void visitTry(Try* curr) { handleBreakTarget(curr->name); }
+
void visitFunction(Function* curr) { assert(branchesSeen.empty()); }
};
diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp
index 0732a6499..6d163d897 100644
--- a/src/passes/StackIR.cpp
+++ b/src/passes/StackIR.cpp
@@ -258,6 +258,7 @@ private:
case StackInst::LoopEnd:
case StackInst::Catch:
case StackInst::CatchAll:
+ case StackInst::Delegate:
case StackInst::TryEnd: {
return true;
}
@@ -284,7 +285,8 @@ private:
case StackInst::BlockEnd:
case StackInst::IfEnd:
case StackInst::LoopEnd:
- case StackInst::TryEnd: {
+ case StackInst::TryEnd:
+ case StackInst::Delegate: {
return true;
}
default: { return false; }