summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-10-30 21:54:41 -0700
committerAlon Zakai <alonzakai@gmail.com>2015-10-30 21:54:41 -0700
commit51be0e93e50c3717cb8e4dff47000a494e67b29a (patch)
tree1295019dd99846b924423891faa015d137175057
parent2d6a5ed822740a6ac53d1807fe2111bee5098bc6 (diff)
downloadbinaryen-51be0e93e50c3717cb8e4dff47000a494e67b29a.tar.gz
binaryen-51be0e93e50c3717cb8e4dff47000a494e67b29a.tar.bz2
binaryen-51be0e93e50c3717cb8e4dff47000a494e67b29a.zip
progress on interpreter
-rwxr-xr-xbuild.sh1
-rw-r--r--src/wasm-interpreter.cpp96
-rw-r--r--src/wasm.h52
3 files changed, 97 insertions, 52 deletions
diff --git a/build.sh b/build.sh
index 5982b33d2..6dd1914e8 100755
--- a/build.sh
+++ b/build.sh
@@ -1,3 +1,2 @@
-#g++ -std=c++11 src/wasm-interpreter.cpp -g -o bin/wasm
g++ -std=c++11 src/asm2wasm.cpp src/parser.cpp src/simple_ast.cpp -g -o bin/asm2wasm
diff --git a/src/wasm-interpreter.cpp b/src/wasm-interpreter.cpp
index ae7b2e793..a055ee17d 100644
--- a/src/wasm-interpreter.cpp
+++ b/src/wasm-interpreter.cpp
@@ -24,67 +24,109 @@ public:
Literal callFunction(IString name) {
// Stuff that flows around during executing expressions: a literal, or a change in control flow
- class Flow : public Literal {
+ class Flow {
public:
+ Flow() {}
+ Flow(Literal value) : value(value) {}
+
+ Literal value;
IString breakTo; // if non-null, a break is going on
+
+ bool breaking() { return breakTo.is(); }
+
+ void clearIf(IString target) {
+ if (breakTo == target) {
+ breakTo.clear();
+ }
+ }
};
// Execute a statement
class ExpressionRunner : public WasmVisitor<Flow> {
- virtual Flow visitBlock(Block *curr) {
+ private:
+ std::vector<Literal> arguments; // filled in before a call, cleared by the call
+
+ public:
+ Flow visitBlock(Block *curr) override {
Flow flow;
for (auto expression : curr->list) {
flow = visit(expression);
- if (flow.breakTo) {
- if (flow.breakTo == curr->name) {
- flow.breakTo.clear();
- }
+ if (flow.breaking()) {
+ flow.clearIf(curr->name);
return flow;
}
}
return flow;
}
- virtual Flow visitIf(If *curr) {
- }
- virtual Flow visitLoop(Loop *curr) {
+ Flow visitIf(If *curr) override {
+ Flow flow = visit(curr->condition);
+ if (flow.breaking()) return flow;
+ if (flow.value.geti32()) return visit(curr->ifTrue);
+ if (curr->ifFalse) return visit(curr->ifFalse);
+ return Flow();
+ }
+ Flow visitLoop(Loop *curr) override {
+ while (1) {
+ Flow flow = visit(curr->body);
+ if (flow.breaking()) {
+ if (flow.breakTo == curr->in) continue; // lol
+ flow.clearIf(curr->out);
+ return flow;
+ }
+ }
}
- virtual Flow visitLabel(Label *curr) {
+ Flow visitLabel(Label *curr) override {
+ Flow flow = visit(curr->body);
+ flow.clearIf(curr->name);
+ return flow;
}
- virtual Flow visitBreak(Break *curr) {
+ Flow visitBreak(Break *curr) override {
+ if (curr->condition) {
+ Flow flow = visit(curr->condition);
+ if (flow.breaking()) return flow;
+ if (!flow.value.geti32()) return Flow();
+ }
+ Flow flow = visit(curr->value);
+ if (!flow.breaking()) {
+ flow.breakTo = curr->name;
+ }
+ return flow;
}
- virtual Flow visitSwitch(Switch *curr) {
+ Flow visitSwitch(Switch *curr) override {
+ abort();
}
- virtual Flow visitCall(Call *curr) {
+ Flow visitCall(Call *curr) override {
}
- virtual Flow visitCallImport(CallImport *curr) {
+ Flow visitCallImport(CallImport *curr) override {
}
- virtual Flow visitCallIndirect(CallIndirect *curr) {
+ Flow visitCallIndirect(CallIndirect *curr) override {
}
- virtual Flow visitGetLocal(GetLocal *curr) {
+ Flow visitGetLocal(GetLocal *curr) override {
}
- virtual Flow visitSetLocal(SetLocal *curr) {
+ Flow visitSetLocal(SetLocal *curr) override {
}
- virtual Flow visitLoad(Load *curr) {
+ Flow visitLoad(Load *curr) override {
}
- virtual Flow visitStore(Store *curr) {
+ Flow visitStore(Store *curr) override {
}
- virtual Flow visitConst(Const *curr) {
+ Flow visitConst(Const *curr) override {
+ return Flow(curr->value); // heh
}
- virtual Flow visitUnary(Unary *curr) {
+ Flow visitUnary(Unary *curr) override {
}
- virtual Flow visitBinary(Binary *curr) {
+ Flow visitBinary(Binary *curr) override {
}
- virtual Flow visitCompare(Compare *curr) {
+ Flow visitCompare(Compare *curr) override {
}
- virtual Flow visitConvert(Convert *curr) {
+ Flow visitConvert(Convert *curr) override {
}
- virtual Flow visitHost(Host *curr) {
+ Flow visitHost(Host *curr) override {
}
- virtual Flow visitNop(Nop *curr) {
+ Flow visitNop(Nop *curr) override {
}
};
- return ExpressionRunner().visit(functions[name]->body);
+ return ExpressionRunner().visit(functions[name]->body).value;
}
private:
diff --git a/src/wasm.h b/src/wasm.h
index 25d514368..07cddfcdd 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -114,8 +114,8 @@ bool isFloat(WasmType type) {
switch (type) {
case f32:
case f64: return true;
+ default: return false;
}
- return false;
}
WasmType getWasmType(unsigned size, bool float_) {
@@ -170,6 +170,11 @@ struct Literal {
Literal(float init) : type(WasmType::f32), f32(init) {}
Literal(double init) : type(WasmType::f64), f64(init) {}
+ int32_t geti32() { assert(type == WasmType::i32); return i32; }
+ int64_t geti64() { assert(type == WasmType::i64); return i64; }
+ float getf32() { assert(type == WasmType::f32); return f32; }
+ double getf64() { assert(type == WasmType::f64); return f64; }
+
void printDouble(std::ostream &o, double d) {
const char *text = JSPrinter::numToString(d);
// spec interpreter hates floats starting with '.'
@@ -231,8 +236,6 @@ class Expression {
public:
WasmType type; // the type of the expression: its output, not necessarily its input(s)
- Expression() : type(type) {}
-
virtual std::ostream& print(std::ostream &o, unsigned indent) = 0;
template<class T>
@@ -244,7 +247,7 @@ public:
std::ostream& printFullLine(std::ostream &o, unsigned indent, Expression *expression) {
doIndent(o, indent);
expression->print(o, indent);
- o << '\n';
+ return o << '\n';
}
std::ostream& printOpening(std::ostream &o, const char *str, bool major=false) {
@@ -325,6 +328,7 @@ public:
class Label : public Expression {
public:
Name name;
+ Expression* body;
};
class Break : public Expression {
@@ -860,26 +864,26 @@ struct WasmWalker : public WasmVisitor<Expression*> {
WasmWalker(wasm::Arena* allocator) : allocator(allocator) {}
// Each method receives an AST pointer, and it is replaced with what is returned.
- virtual Expression* visitBlock(Block *curr) { return curr; };
- virtual Expression* visitIf(If *curr) { return curr; };
- virtual Expression* visitLoop(Loop *curr) { return curr; };
- virtual Expression* visitLabel(Label *curr) { return curr; };
- virtual Expression* visitBreak(Break *curr) { return curr; };
- virtual Expression* visitSwitch(Switch *curr) { return curr; };
- virtual Expression* visitCall(Call *curr) { return curr; };
- virtual Expression* visitCallImport(CallImport *curr) { return curr; };
- virtual Expression* visitCallIndirect(CallIndirect *curr) { return curr; };
- virtual Expression* visitGetLocal(GetLocal *curr) { return curr; };
- virtual Expression* visitSetLocal(SetLocal *curr) { return curr; };
- virtual Expression* visitLoad(Load *curr) { return curr; };
- virtual Expression* visitStore(Store *curr) { return curr; };
- virtual Expression* visitConst(Const *curr) { return curr; };
- virtual Expression* visitUnary(Unary *curr) { return curr; };
- virtual Expression* visitBinary(Binary *curr) { return curr; };
- virtual Expression* visitCompare(Compare *curr) { return curr; };
- virtual Expression* visitConvert(Convert *curr) { return curr; };
- virtual Expression* visitHost(Host *curr) { return curr; };
- virtual Expression* visitNop(Nop *curr) { return curr; };
+ Expression* visitBlock(Block *curr) override { return curr; };
+ Expression* visitIf(If *curr) override { return curr; };
+ Expression* visitLoop(Loop *curr) override { return curr; };
+ Expression* visitLabel(Label *curr) override { return curr; };
+ Expression* visitBreak(Break *curr) override { return curr; };
+ Expression* visitSwitch(Switch *curr) override { return curr; };
+ Expression* visitCall(Call *curr) override { return curr; };
+ Expression* visitCallImport(CallImport *curr) override { return curr; };
+ Expression* visitCallIndirect(CallIndirect *curr) override { return curr; };
+ Expression* visitGetLocal(GetLocal *curr) override { return curr; };
+ Expression* visitSetLocal(SetLocal *curr) override { return curr; };
+ Expression* visitLoad(Load *curr) override { return curr; };
+ Expression* visitStore(Store *curr) override { return curr; };
+ Expression* visitConst(Const *curr) override { return curr; };
+ Expression* visitUnary(Unary *curr) override { return curr; };
+ Expression* visitBinary(Binary *curr) override { return curr; };
+ Expression* visitCompare(Compare *curr) override { return curr; };
+ Expression* visitConvert(Convert *curr) override { return curr; };
+ Expression* visitHost(Host *curr) override { return curr; };
+ Expression* visitNop(Nop *curr) override { return curr; };
// children-first
Expression *walk(Expression *curr) {