summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Bebenita <mbebenita@gmail.com>2016-01-11 20:51:27 -0800
committerMichael Bebenita <mbebenita@gmail.com>2016-01-13 20:09:10 -0800
commit7e3bdd00f9b390c36461291fa5b884ace55e82d6 (patch)
treed282aedbd7d08efdb1383ae22c4b2db6937bc713
parentab3b76b29488ca8f85c39491c5ac96d6274fac7c (diff)
downloadbinaryen-7e3bdd00f9b390c36461291fa5b884ace55e82d6.tar.gz
binaryen-7e3bdd00f9b390c36461291fa5b884ace55e82d6.tar.bz2
binaryen-7e3bdd00f9b390c36461291fa5b884ace55e82d6.zip
A more generic compiler pass system.
-rw-r--r--src/pass.h18
-rw-r--r--src/passes/LowerIfElse.cpp2
-rw-r--r--src/passes/MergeBlocks.cpp2
-rw-r--r--src/passes/RemoveImports.cpp2
-rw-r--r--src/passes/RemoveUnusedBrs.cpp2
-rw-r--r--src/passes/RemoveUnusedNames.cpp2
-rw-r--r--src/passes/SimplifyLocals.cpp2
-rw-r--r--src/wasm.h178
8 files changed, 112 insertions, 96 deletions
diff --git a/src/pass.h b/src/pass.h
index d3f1d9edb..691583f2b 100644
--- a/src/pass.h
+++ b/src/pass.h
@@ -88,14 +88,24 @@ struct PassRunner {
//
// Core pass class
//
-class Pass : public WasmWalker {
+class Pass {
public:
// Override this to perform preparation work before the pass runs
virtual void prepare(PassRunner* runner, Module* module) {}
+ virtual void run(PassRunner* runner, Module* module) { abort(); }
+ virtual ~Pass() {}
+};
- void run(PassRunner* runner, Module* module) {
+//
+// Core pass class that uses AST walking. This class can be parameterized by
+// different types of AST walkers.
+//
+template <class WalkerType>
+class WalkerPass : public Pass, public WalkerType {
+ public:
+ void run(PassRunner* runner, Module* module) override {
prepare(runner, module);
- startWalk(module);
+ WalkerType::startWalk(module);
}
};
@@ -104,7 +114,7 @@ class Pass : public WasmWalker {
// e.g. through PassRunner::getLast
// Handles names in a module, in particular adding names without duplicates
-class NameManager : public Pass {
+class NameManager : public WalkerPass<WasmWalker> {
public:
Name getUnique(std::string prefix);
// TODO: getUniqueInFunction
diff --git a/src/passes/LowerIfElse.cpp b/src/passes/LowerIfElse.cpp
index 711f5469c..26ae321e6 100644
--- a/src/passes/LowerIfElse.cpp
+++ b/src/passes/LowerIfElse.cpp
@@ -32,7 +32,7 @@
namespace wasm {
-struct LowerIfElse : public Pass {
+struct LowerIfElse : public WalkerPass<WasmWalker> {
MixedArena* allocator;
std::unique_ptr<NameManager> namer;
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 3d7afc4cb..5543c407b 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -23,7 +23,7 @@
namespace wasm {
-struct MergeBlocks : public Pass {
+struct MergeBlocks : public WalkerPass<WasmWalker> {
void visitBlock(Block *curr) override {
bool more = true;
while (more) {
diff --git a/src/passes/RemoveImports.cpp b/src/passes/RemoveImports.cpp
index 0c4924a45..0938bbed3 100644
--- a/src/passes/RemoveImports.cpp
+++ b/src/passes/RemoveImports.cpp
@@ -27,7 +27,7 @@
namespace wasm {
-struct RemoveImports : public Pass {
+struct RemoveImports : public WalkerPass<WasmWalker> {
MixedArena* allocator;
std::map<Name, Import*> importsMap;
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 395b0f1ba..f01add24c 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -23,7 +23,7 @@
namespace wasm {
-struct RemoveUnusedBrs : public Pass {
+struct RemoveUnusedBrs : public WalkerPass<WasmWalker> {
// preparation: try to unify branches, as the fewer there are, the higher a chance we can remove them
// specifically for if-else, turn an if-else with branches to the same target at the end of each
// child, and with a value, to a branch to that target containing the if-else
diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp
index 62de48567..d3057c78a 100644
--- a/src/passes/RemoveUnusedNames.cpp
+++ b/src/passes/RemoveUnusedNames.cpp
@@ -23,7 +23,7 @@
namespace wasm {
-struct RemoveUnusedNames : public Pass {
+struct RemoveUnusedNames : public WalkerPass<WasmWalker> {
// We maintain a list of branches that we saw in children, then when we reach
// a parent block, we know if it was branched to
std::set<Name> branchesSeen;
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index b1adf5c26..bf3775445 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -23,7 +23,7 @@
namespace wasm {
-struct SimplifyLocals : public Pass {
+struct SimplifyLocals : public WalkerPass<WasmWalker> {
void visitBlock(Block *curr) override {
// look for pairs of setlocal-getlocal, which can be just a setlocal (since it returns a value)
if (curr->list.size() == 0) return;
diff --git a/src/wasm.h b/src/wasm.h
index 306804c66..c6942acfe 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1233,13 +1233,101 @@ std::ostream& Expression::print(std::ostream &o, unsigned indent) {
return o;
}
+struct WasmWalkerBase : public WasmVisitor<void> {
+ virtual void walk(Expression*& curr) { abort(); }
+ virtual void startWalk(Function *func) { abort(); }
+ virtual void startWalk(Module *module) { abort(); }
+};
+
+struct ChildWalker : public WasmWalkerBase {
+ WasmWalkerBase& parent;
+
+ ChildWalker(WasmWalkerBase& parent) : parent(parent) {}
+
+ void visitBlock(Block *curr) override {
+ ExpressionList& list = curr->list;
+ for (size_t z = 0; z < list.size(); z++) {
+ parent.walk(list[z]);
+ }
+ }
+ void visitIf(If *curr) override {
+ parent.walk(curr->condition);
+ parent.walk(curr->ifTrue);
+ parent.walk(curr->ifFalse);
+ }
+ void visitLoop(Loop *curr) override {
+ parent.walk(curr->body);
+ }
+ void visitBreak(Break *curr) override {
+ parent.walk(curr->condition);
+ parent.walk(curr->value);
+ }
+ void visitSwitch(Switch *curr) override {
+ parent.walk(curr->value);
+ for (auto& case_ : curr->cases) {
+ parent.walk(case_.body);
+ }
+ }
+ void visitCall(Call *curr) override {
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ parent.walk(list[z]);
+ }
+ }
+ void visitCallImport(CallImport *curr) override {
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ parent.walk(list[z]);
+ }
+ }
+ void visitCallIndirect(CallIndirect *curr) override {
+ parent.walk(curr->target);
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ parent.walk(list[z]);
+ }
+ }
+ void visitGetLocal(GetLocal *curr) override {}
+ void visitSetLocal(SetLocal *curr) override {
+ parent.walk(curr->value);
+ }
+ void visitLoad(Load *curr) override {
+ parent.walk(curr->ptr);
+ }
+ void visitStore(Store *curr) override {
+ parent.walk(curr->ptr);
+ parent.walk(curr->value);
+ }
+ void visitConst(Const *curr) override {}
+ void visitUnary(Unary *curr) override {
+ parent.walk(curr->value);
+ }
+ void visitBinary(Binary *curr) override {
+ parent.walk(curr->left);
+ parent.walk(curr->right);
+ }
+ void visitSelect(Select *curr) override {
+ parent.walk(curr->condition);
+ parent.walk(curr->ifTrue);
+ parent.walk(curr->ifFalse);
+ }
+ void visitHost(Host *curr) override {
+ ExpressionList& list = curr->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ parent.walk(list[z]);
+ }
+ }
+ void visitNop(Nop *curr) override {}
+ void visitUnreachable(Unreachable *curr) override {}
+};
+
//
// Simple WebAssembly children-first walking (i.e., post-order, if you look
// at the children as subtrees of the current node), with the ability to replace
// the current expression node. Useful for writing optimization passes.
//
-struct WasmWalker : public WasmVisitor<void> {
+struct WasmWalker : public WasmWalkerBase {
Expression* replace;
WasmWalker() : replace(nullptr) {}
@@ -1279,91 +1367,9 @@ struct WasmWalker : public WasmVisitor<void> {
void visitModule(Module *curr) override {}
// children-first
- void walk(Expression*& curr) {
+ void walk(Expression*& curr) override {
if (!curr) return;
- struct ChildWalker : public WasmVisitor {
- WasmWalker& parent;
-
- ChildWalker(WasmWalker& parent) : parent(parent) {}
-
- void visitBlock(Block *curr) override {
- ExpressionList& list = curr->list;
- for (size_t z = 0; z < list.size(); z++) {
- parent.walk(list[z]);
- }
- }
- void visitIf(If *curr) override {
- parent.walk(curr->condition);
- parent.walk(curr->ifTrue);
- parent.walk(curr->ifFalse);
- }
- void visitLoop(Loop *curr) override {
- parent.walk(curr->body);
- }
- void visitBreak(Break *curr) override {
- parent.walk(curr->condition);
- parent.walk(curr->value);
- }
- void visitSwitch(Switch *curr) override {
- parent.walk(curr->value);
- for (auto& case_ : curr->cases) {
- parent.walk(case_.body);
- }
- }
- void visitCall(Call *curr) override {
- ExpressionList& list = curr->operands;
- for (size_t z = 0; z < list.size(); z++) {
- parent.walk(list[z]);
- }
- }
- void visitCallImport(CallImport *curr) override {
- ExpressionList& list = curr->operands;
- for (size_t z = 0; z < list.size(); z++) {
- parent.walk(list[z]);
- }
- }
- void visitCallIndirect(CallIndirect *curr) override {
- parent.walk(curr->target);
- ExpressionList& list = curr->operands;
- for (size_t z = 0; z < list.size(); z++) {
- parent.walk(list[z]);
- }
- }
- void visitGetLocal(GetLocal *curr) override {}
- void visitSetLocal(SetLocal *curr) override {
- parent.walk(curr->value);
- }
- void visitLoad(Load *curr) override {
- parent.walk(curr->ptr);
- }
- void visitStore(Store *curr) override {
- parent.walk(curr->ptr);
- parent.walk(curr->value);
- }
- void visitConst(Const *curr) override {}
- void visitUnary(Unary *curr) override {
- parent.walk(curr->value);
- }
- void visitBinary(Binary *curr) override {
- parent.walk(curr->left);
- parent.walk(curr->right);
- }
- void visitSelect(Select *curr) override {
- parent.walk(curr->condition);
- parent.walk(curr->ifTrue);
- parent.walk(curr->ifFalse);
- }
- void visitHost(Host *curr) override {
- ExpressionList& list = curr->operands;
- for (size_t z = 0; z < list.size(); z++) {
- parent.walk(list[z]);
- }
- }
- void visitNop(Nop *curr) override {}
- void visitUnreachable(Unreachable *curr) override {}
- };
-
ChildWalker(*this).visit(curr);
visit(curr);
@@ -1374,11 +1380,11 @@ struct WasmWalker : public WasmVisitor<void> {
}
}
- void startWalk(Function *func) {
+ void startWalk(Function *func) override {
walk(func->body);
}
- void startWalk(Module *module) {
+ void startWalk(Module *module) override {
for (auto curr : module->functionTypes) {
visitFunctionType(curr);
assert(!replace);