summaryrefslogtreecommitdiff
path: root/src/wasm-traversal.h
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-08-03 18:03:24 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-09-07 09:54:55 -0700
commit42155057a56a979eccb6d811671cfbf290cf429e (patch)
treea645eac6260895f269b44a1132e97b48c464db09 /src/wasm-traversal.h
parentf30d9f6cde023b29409f73aba68f472c06c3b11c (diff)
downloadbinaryen-42155057a56a979eccb6d811671cfbf290cf429e.tar.gz
binaryen-42155057a56a979eccb6d811671cfbf290cf429e.tar.bz2
binaryen-42155057a56a979eccb6d811671cfbf290cf429e.zip
move drop into blocks, dropping all the breaks as well, when possible
Diffstat (limited to 'src/wasm-traversal.h')
-rw-r--r--src/wasm-traversal.h62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index f9d3d8413..f4483644c 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -446,6 +446,68 @@ struct PostWalker : public Walker<SubType, VisitorType> {
}
};
+// Traversal with a control-flow stack.
+
+template<typename SubType, typename VisitorType>
+struct ControlFlowWalker : public PostWalker<SubType, VisitorType> {
+ ControlFlowWalker() {}
+
+ std::vector<Expression*> controlFlowStack; // contains blocks, loops, and ifs
+
+ // Uses the control flow stack to find the target of a break to a name
+ Expression* findBreakTarget(Name name) {
+ assert(!controlFlowStack.empty());
+ Index i = controlFlowStack.size() - 1;
+ while (1) {
+ auto* curr = controlFlowStack[i];
+ if (Block* block = curr->dynCast<Block>()) {
+ if (name == block->name) return curr;
+ } else if (Loop* loop = curr->dynCast<Loop>()) {
+ if (name == loop->name) return curr;
+ } else {
+ WASM_UNREACHABLE();
+ }
+ if (i == 0) return nullptr;
+ i--;
+ }
+ }
+
+ static void doPreVisitControlFlow(SubType* self, Expression** currp) {
+ self->controlFlowStack.push_back(*currp);
+ }
+
+ static void doPostVisitControlFlow(SubType* self, Expression** currp) {
+ assert(self->controlFlowStack.back() == *currp);
+ self->controlFlowStack.pop_back();
+ }
+
+ static void scan(SubType* self, Expression** currp) {
+ auto* curr = *currp;
+
+ switch (curr->_id) {
+ case Expression::Id::BlockId:
+ case Expression::Id::IfId:
+ case Expression::Id::LoopId: {
+ self->pushTask(SubType::doPostVisitControlFlow, currp);
+ break;
+ }
+ default: {}
+ }
+
+ PostWalker<SubType, VisitorType>::scan(self, currp);
+
+ switch (curr->_id) {
+ case Expression::Id::BlockId:
+ case Expression::Id::IfId:
+ case Expression::Id::LoopId: {
+ self->pushTask(SubType::doPreVisitControlFlow, currp);
+ break;
+ }
+ default: {}
+ }
+ }
+};
+
// Traversal in the order of execution. This is quick and simple, but
// does not provide the same comprehensive information that a full
// conversion to basic blocks would. What it does give is a quick