summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-06 15:36:12 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-06 16:06:06 -0700
commit3c6203ab0c936570c0e9cf25d810c911fc93fc05 (patch)
tree274972983971659d0c3f09dfb8380be25219c7e8
parent41b7c45e6ad662161a8cdc5fd5c88e3bae3363fc (diff)
downloadbinaryen-3c6203ab0c936570c0e9cf25d810c911fc93fc05.tar.gz
binaryen-3c6203ab0c936570c0e9cf25d810c911fc93fc05.tar.bz2
binaryen-3c6203ab0c936570c0e9cf25d810c911fc93fc05.zip
add FastExecutionWalker
-rw-r--r--src/wasm-traversal.h102
1 files changed, 101 insertions, 1 deletions
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index 7d73baf6e..a0ef357da 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -315,6 +315,106 @@ struct WasmWalker : public WasmWalkerBase<SubType, ReturnType> {
}
};
-}
+// 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
+// way to view straightline execution traces, i.e., that have no
+// branching. This can let optimizations get most of what they
+// want without the cost of creating another AST.
+//
+// When execution is no longer linear, this notifies via a call
+// to noteNonLinear().
+
+struct FastExecutionWalker : public WasmWalkerBase<FastExecutionWalker> {
+ FastExecutionWalker() {}
+
+ void noteNonLinear() { abort(); } // must be overridden
+
+ void visitBlock(Block *curr) {
+ ExpressionList& list = curr->list;
+ for (size_t z = 0; z < list.size(); z++) {
+ visit(list[z]);
+ }
+ }
+ void visitIf(If *curr) {
+ visit(curr->condition);
+ noteNonLinear();
+ visit(curr->ifTrue);
+ noteNonLinear();
+ visit(curr->ifFalse);
+ noteNonLinear();
+ }
+ void visitLoop(Loop *curr) {
+ noteNonLinear();
+ visit(curr->body);
+ }
+ void visitBreak(Break *curr) {
+ if (curr->value) visit(curr->value);
+ if (curr->condition) visit(curr->condition);
+ noteNonLinear();
+ }
+ void visitSwitch(Switch *curr) {
+ visit(curr->condition);
+ if (curr->value) visit(curr->value);
+ noteNonLinear();
+ }
+ void visitCall(Call *curr) {
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ visit(list[z]);
+ }
+ }
+ void visitCallImport(CallImport *curr) {
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ visit(list[z]);
+ }
+ }
+ void visitCallIndirect(CallIndirect *curr) {
+ visit(curr->target);
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ visit(list[z]);
+ }
+ }
+ void visitGetLocal(GetLocal *curr) {}
+ void visitSetLocal(SetLocal *curr) {
+ visit(curr->value);
+ }
+ void visitLoad(Load *curr) {
+ visit(curr->ptr);
+ }
+ void visitStore(Store *curr) {
+ visit(curr->ptr);
+ visit(curr->value);
+ }
+ void visitConst(Const *curr) {}
+ void visitUnary(Unary *curr) {
+ visit(curr->value);
+ }
+ void visitBinary(Binary *curr) {
+ visit(curr->left);
+ visit(curr->right);
+ }
+ void visitSelect(Select *curr) {
+ visit(curr->ifTrue);
+ visit(curr->ifFalse);
+ visit(curr->condition);
+ }
+ void visitReturn(Return *curr) {
+ visit(curr->value);
+ noteNonLinear();
+ }
+ void visitHost(Host *curr) {
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ visit(list[z]);
+ }
+ }
+ void visitNop(Nop *curr) {}
+ void visitUnreachable(Unreachable *curr) {}
+};
+
+} // namespace wasm
#endif // wasm_traversal_h