summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-10-30 20:51:52 -0700
committerAlon Zakai <alonzakai@gmail.com>2015-10-30 20:52:14 -0700
commit6ebb87ce79d6aed56addfc0d275ee4e93d143469 (patch)
treeae580458359453dab0b20e0759ab03db2c7e8af7 /src
parenta6701a55871bdccd60445da4a47bcc63840c0115 (diff)
downloadbinaryen-6ebb87ce79d6aed56addfc0d275ee4e93d143469.tar.gz
binaryen-6ebb87ce79d6aed56addfc0d275ee4e93d143469.tar.bz2
binaryen-6ebb87ce79d6aed56addfc0d275ee4e93d143469.zip
refactorings and begin interpreter
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.cpp147
-rw-r--r--src/istring.h4
-rw-r--r--src/wasm-interpreter.cpp95
-rw-r--r--src/wasm.h151
4 files changed, 250 insertions, 147 deletions
diff --git a/src/asm2wasm.cpp b/src/asm2wasm.cpp
index d6a521ca1..bdbef2d78 100644
--- a/src/asm2wasm.cpp
+++ b/src/asm2wasm.cpp
@@ -47,153 +47,6 @@ static void abort_on(std::string why, IString element) {
abort();
}
-//
-// Simple WebAssembly optimizer, improves common patterns we get in asm2wasm.
-// Operates in-place.
-//
-
-struct WasmWalker {
- wasm::Arena* allocator; // use an existing allocator, or null if no allocations
-
- WasmWalker() : allocator(nullptr) {}
- WasmWalker(wasm::Arena* allocator) : allocator(allocator) {}
-
- // Each method receives an AST pointer, and it is replaced with what is returned.
- virtual Expression* walkBlock(Block *curr) { return curr; };
- virtual Expression* walkIf(If *curr) { return curr; };
- virtual Expression* walkLoop(Loop *curr) { return curr; };
- virtual Expression* walkLabel(Label *curr) { return curr; };
- virtual Expression* walkBreak(Break *curr) { return curr; };
- virtual Expression* walkSwitch(Switch *curr) { return curr; };
- virtual Expression* walkCall(Call *curr) { return curr; };
- virtual Expression* walkCallImport(CallImport *curr) { return curr; };
- virtual Expression* walkCallIndirect(CallIndirect *curr) { return curr; };
- virtual Expression* walkGetLocal(GetLocal *curr) { return curr; };
- virtual Expression* walkSetLocal(SetLocal *curr) { return curr; };
- virtual Expression* walkLoad(Load *curr) { return curr; };
- virtual Expression* walkStore(Store *curr) { return curr; };
- virtual Expression* walkConst(Const *curr) { return curr; };
- virtual Expression* walkUnary(Unary *curr) { return curr; };
- virtual Expression* walkBinary(Binary *curr) { return curr; };
- virtual Expression* walkCompare(Compare *curr) { return curr; };
- virtual Expression* walkConvert(Convert *curr) { return curr; };
- virtual Expression* walkHost(Host *curr) { return curr; };
- virtual Expression* walkNop(Nop *curr) { return curr; };
-
- // children-first
- Expression *walk(Expression *curr) {
- if (!curr) return curr;
-
- if (Block *cast = dynamic_cast<Block*>(curr)) {
- ExpressionList& list = cast->list;
- for (size_t z = 0; z < list.size(); z++) {
- list[z] = walk(list[z]);
- }
- return walkBlock(cast);
- }
- if (If *cast = dynamic_cast<If*>(curr)) {
- cast->condition = walk(cast->condition);
- cast->ifTrue = walk(cast->ifTrue);
- cast->ifFalse = walk(cast->ifFalse);
- return walkIf(cast);
- }
- if (Loop *cast = dynamic_cast<Loop*>(curr)) {
- cast->body = walk(cast->body);
- return walkLoop(cast);
- }
- if (Label *cast = dynamic_cast<Label*>(curr)) {
- return walkLabel(cast);
- }
- if (Break *cast = dynamic_cast<Break*>(curr)) {
- cast->condition = walk(cast->condition);
- cast->value = walk(cast->value);
- return walkBreak(cast);
- }
- if (Switch *cast = dynamic_cast<Switch*>(curr)) {
- cast->value = walk(cast->value);
- for (auto& curr : cast->cases) {
- curr.body = walk(curr.body);
- }
- cast->default_ = walk(cast->default_);
- return walkSwitch(cast);
- }
- if (Call *cast = dynamic_cast<Call*>(curr)) {
- ExpressionList& list = cast->operands;
- for (size_t z = 0; z < list.size(); z++) {
- list[z] = walk(list[z]);
- }
- return walkCall(cast);
- }
- if (CallImport *cast = dynamic_cast<CallImport*>(curr)) {
- ExpressionList& list = cast->operands;
- for (size_t z = 0; z < list.size(); z++) {
- list[z] = walk(list[z]);
- }
- return walkCallImport(cast);
- }
- if (CallIndirect *cast = dynamic_cast<CallIndirect*>(curr)) {
- cast->target = walk(cast->target);
- ExpressionList& list = cast->operands;
- for (size_t z = 0; z < list.size(); z++) {
- list[z] = walk(list[z]);
- }
- return walkCallIndirect(cast);
- }
- if (GetLocal *cast = dynamic_cast<GetLocal*>(curr)) {
- return walkGetLocal(cast);
- }
- if (SetLocal *cast = dynamic_cast<SetLocal*>(curr)) {
- cast->value = walk(cast->value);
- return walkSetLocal(cast);
- }
- if (Load *cast = dynamic_cast<Load*>(curr)) {
- cast->ptr = walk(cast->ptr);
- return walkLoad(cast);
- }
- if (Store *cast = dynamic_cast<Store*>(curr)) {
- cast->ptr = walk(cast->ptr);
- cast->value = walk(cast->value);
- return walkStore(cast);
- }
- if (Const *cast = dynamic_cast<Const*>(curr)) {
- return walkConst(cast);
- }
- if (Unary *cast = dynamic_cast<Unary*>(curr)) {
- cast->value = walk(cast->value);
- return walkUnary(cast);
- }
- if (Binary *cast = dynamic_cast<Binary*>(curr)) {
- cast->left = walk(cast->left);
- cast->right = walk(cast->right);
- return walkBinary(cast);
- }
- if (Compare *cast = dynamic_cast<Compare*>(curr)) {
- cast->left = walk(cast->left);
- cast->right = walk(cast->right);
- return walkCompare(cast);
- }
- if (Convert *cast = dynamic_cast<Convert*>(curr)) {
- cast->value = walk(cast->value);
- return walkConvert(cast);
- }
- if (Host *cast = dynamic_cast<Host*>(curr)) {
- ExpressionList& list = cast->operands;
- for (size_t z = 0; z < list.size(); z++) {
- list[z] = walk(list[z]);
- }
- return walkHost(cast);
- }
- if (Nop *cast = dynamic_cast<Nop*>(curr)) {
- return walkNop(cast);
- }
- abort();
- }
-
- void startWalk(Function *func) {
- func->body = walk(func->body);
- }
-};
-
// useful when we need to see our parent, in an asm.js expression stack
struct AstStackHelper {
static std::vector<Ref> astStack;
diff --git a/src/istring.h b/src/istring.h
index 3a66465d0..921e04487 100644
--- a/src/istring.h
+++ b/src/istring.h
@@ -68,6 +68,10 @@ struct IString {
str = s.str;
}
+ void clear() {
+ str = nullptr;
+ }
+
bool operator==(const IString& other) const {
//assert((str == other.str) == !strcmp(str, other.str));
return str == other.str; // fast!
diff --git a/src/wasm-interpreter.cpp b/src/wasm-interpreter.cpp
new file mode 100644
index 000000000..8e1294624
--- /dev/null
+++ b/src/wasm-interpreter.cpp
@@ -0,0 +1,95 @@
+
+// Simple WebAssembly interpreter, designed to be embeddable in JavaScript, so it
+// can function as a polyfill.
+
+#include "wasm.h"
+
+namespace wasm {
+
+// An instance of a WebAssembly module
+class ModuleInstance {
+public:
+ ModuleInstance(Module& wasm) : wasm(wasm) {
+ for (auto function : wasm.functions) {
+ functions[function->name] = function;
+ }
+ }
+
+ Literal callFunction(const char *name) {
+ return callFunction(IString(name));
+ }
+
+ Literal callFunction(IString name) {
+ // Stuff that flows around during executing expressions: a literal, or a change in control flow
+ class Flow : public Literal {
+ public:
+ IString breakTo; // if non-null, a break is going on
+ };
+
+ // Execute a statement
+ class ExpressionRunner : public WasmVisitor<Flow> {
+ virtual Flow visitBlock(Block *curr) {
+ Flow flow;
+ for (auto expression : curr->list) {
+ flow = visit(expression);
+ if (flow.breakTo) {
+ if (flow.breakTo == curr->name) {
+ flow.breakTo.clear();
+ }
+ return flow;
+ }
+ }
+ return flow;
+ }
+ virtual Flow visitIf(If *curr) {
+ }
+ virtual Flow visitLoop(Loop *curr) {
+ }
+ virtual Flow visitLabel(Label *curr) {
+ }
+ virtual Flow visitBreak(Break *curr) {
+ }
+ virtual Flow visitSwitch(Switch *curr) {
+ }
+ virtual Flow visitCall(Call *curr) {
+ }
+ virtual Flow visitCallImport(CallImport *curr) {
+ }
+ virtual Flow visitCallIndirect(CallIndirect *curr) {
+ }
+ virtual Flow visitGetLocal(GetLocal *curr) {
+ }
+ virtual Flow visitSetLocal(SetLocal *curr) {
+ }
+ virtual Flow visitLoad(Load *curr) {
+ }
+ virtual Flow visitStore(Store *curr) {
+ }
+ virtual Flow visitConst(Const *curr) {
+ }
+ virtual Flow visitUnary(Unary *curr) {
+ }
+ virtual Flow visitBinary(Binary *curr) {
+ }
+ virtual Flow visitCompare(Compare *curr) {
+ }
+ virtual Flow visitConvert(Convert *curr) {
+ }
+ virtual Flow visitHost(Host *curr) {
+ }
+ virtual Flow visitNop(Nop *curr) {
+ }
+ };
+
+ return ExpressionRunner().visit(functions[name]->body);
+ }
+
+private:
+ Module& wasm;
+
+ std::map<IString, Function*> functions;
+
+};
+
+} // namespace wasm
+
diff --git a/src/wasm.h b/src/wasm.h
index d13eb0795..290fc5d47 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -2,6 +2,9 @@
// WebAssembly representation and processing library
//
+#ifndef __wasm_h__
+#define __wasm_h__
+
#include <cassert>
#include <cstddef>
#include <cstdint>
@@ -796,5 +799,153 @@ public:
}
};
+//
+// Simple WebAssembly AST walker
+//
+
+struct WasmWalker {
+ wasm::Arena* allocator; // use an existing allocator, or null if no allocations
+
+ WasmWalker() : allocator(nullptr) {}
+ WasmWalker(wasm::Arena* allocator) : allocator(allocator) {}
+
+ // Each method receives an AST pointer, and it is replaced with what is returned.
+ virtual Expression* walkBlock(Block *curr) { return curr; };
+ virtual Expression* walkIf(If *curr) { return curr; };
+ virtual Expression* walkLoop(Loop *curr) { return curr; };
+ virtual Expression* walkLabel(Label *curr) { return curr; };
+ virtual Expression* walkBreak(Break *curr) { return curr; };
+ virtual Expression* walkSwitch(Switch *curr) { return curr; };
+ virtual Expression* walkCall(Call *curr) { return curr; };
+ virtual Expression* walkCallImport(CallImport *curr) { return curr; };
+ virtual Expression* walkCallIndirect(CallIndirect *curr) { return curr; };
+ virtual Expression* walkGetLocal(GetLocal *curr) { return curr; };
+ virtual Expression* walkSetLocal(SetLocal *curr) { return curr; };
+ virtual Expression* walkLoad(Load *curr) { return curr; };
+ virtual Expression* walkStore(Store *curr) { return curr; };
+ virtual Expression* walkConst(Const *curr) { return curr; };
+ virtual Expression* walkUnary(Unary *curr) { return curr; };
+ virtual Expression* walkBinary(Binary *curr) { return curr; };
+ virtual Expression* walkCompare(Compare *curr) { return curr; };
+ virtual Expression* walkConvert(Convert *curr) { return curr; };
+ virtual Expression* walkHost(Host *curr) { return curr; };
+ virtual Expression* walkNop(Nop *curr) { return curr; };
+
+ // children-first
+ Expression *walk(Expression *curr) {
+ if (!curr) return curr;
+
+ if (Block *cast = dynamic_cast<Block*>(curr)) {
+ ExpressionList& list = cast->list;
+ for (size_t z = 0; z < list.size(); z++) {
+ list[z] = walk(list[z]);
+ }
+ return walkBlock(cast);
+ }
+ if (If *cast = dynamic_cast<If*>(curr)) {
+ cast->condition = walk(cast->condition);
+ cast->ifTrue = walk(cast->ifTrue);
+ cast->ifFalse = walk(cast->ifFalse);
+ return walkIf(cast);
+ }
+ if (Loop *cast = dynamic_cast<Loop*>(curr)) {
+ cast->body = walk(cast->body);
+ return walkLoop(cast);
+ }
+ if (Label *cast = dynamic_cast<Label*>(curr)) {
+ return walkLabel(cast);
+ }
+ if (Break *cast = dynamic_cast<Break*>(curr)) {
+ cast->condition = walk(cast->condition);
+ cast->value = walk(cast->value);
+ return walkBreak(cast);
+ }
+ if (Switch *cast = dynamic_cast<Switch*>(curr)) {
+ cast->value = walk(cast->value);
+ for (auto& curr : cast->cases) {
+ curr.body = walk(curr.body);
+ }
+ cast->default_ = walk(cast->default_);
+ return walkSwitch(cast);
+ }
+ if (Call *cast = dynamic_cast<Call*>(curr)) {
+ ExpressionList& list = cast->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ list[z] = walk(list[z]);
+ }
+ return walkCall(cast);
+ }
+ if (CallImport *cast = dynamic_cast<CallImport*>(curr)) {
+ ExpressionList& list = cast->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ list[z] = walk(list[z]);
+ }
+ return walkCallImport(cast);
+ }
+ if (CallIndirect *cast = dynamic_cast<CallIndirect*>(curr)) {
+ cast->target = walk(cast->target);
+ ExpressionList& list = cast->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ list[z] = walk(list[z]);
+ }
+ return walkCallIndirect(cast);
+ }
+ if (GetLocal *cast = dynamic_cast<GetLocal*>(curr)) {
+ return walkGetLocal(cast);
+ }
+ if (SetLocal *cast = dynamic_cast<SetLocal*>(curr)) {
+ cast->value = walk(cast->value);
+ return walkSetLocal(cast);
+ }
+ if (Load *cast = dynamic_cast<Load*>(curr)) {
+ cast->ptr = walk(cast->ptr);
+ return walkLoad(cast);
+ }
+ if (Store *cast = dynamic_cast<Store*>(curr)) {
+ cast->ptr = walk(cast->ptr);
+ cast->value = walk(cast->value);
+ return walkStore(cast);
+ }
+ if (Const *cast = dynamic_cast<Const*>(curr)) {
+ return walkConst(cast);
+ }
+ if (Unary *cast = dynamic_cast<Unary*>(curr)) {
+ cast->value = walk(cast->value);
+ return walkUnary(cast);
+ }
+ if (Binary *cast = dynamic_cast<Binary*>(curr)) {
+ cast->left = walk(cast->left);
+ cast->right = walk(cast->right);
+ return walkBinary(cast);
+ }
+ if (Compare *cast = dynamic_cast<Compare*>(curr)) {
+ cast->left = walk(cast->left);
+ cast->right = walk(cast->right);
+ return walkCompare(cast);
+ }
+ if (Convert *cast = dynamic_cast<Convert*>(curr)) {
+ cast->value = walk(cast->value);
+ return walkConvert(cast);
+ }
+ if (Host *cast = dynamic_cast<Host*>(curr)) {
+ ExpressionList& list = cast->operands;
+ for (size_t z = 0; z < list.size(); z++) {
+ list[z] = walk(list[z]);
+ }
+ return walkHost(cast);
+ }
+ if (Nop *cast = dynamic_cast<Nop*>(curr)) {
+ return walkNop(cast);
+ }
+ abort();
+ }
+
+ void startWalk(Function *func) {
+ func->body = walk(func->body);
+ }
+};
+
} // namespace wasm
+#endif // __wasm_h__
+