summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm-binary.h14
-rw-r--r--src/wasm-interpreter.h16
-rw-r--r--src/wasm-s-parser.h21
-rw-r--r--src/wasm.h27
4 files changed, 56 insertions, 22 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 26673a966..1cc6f0673 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -916,6 +916,15 @@ public:
recurse(curr->ifFalse);
recurse(curr->condition);
}
+ void visitReturn(Return *curr) {
+ if (debug) std::cerr << "zz node: Return" << std::endl;
+ o << int8_t(BinaryConsts::Return);
+ if (curr->value) {
+ recurse(curr->value);
+ } else {
+ visitNop(nullptr);
+ }
+ }
void visitHost(Host *curr) {
if (debug) std::cerr << "zz node: Host" << std::endl;
switch (curr->op) {
@@ -1263,6 +1272,7 @@ public:
case BinaryConsts::GetLocal: visitGetLocal((curr = allocator.alloc<GetLocal>())->cast<GetLocal>()); break;
case BinaryConsts::SetLocal: visitSetLocal((curr = allocator.alloc<SetLocal>())->cast<SetLocal>()); break;
case BinaryConsts::Select: visitSelect((curr = allocator.alloc<Select>())->cast<Select>()); break;
+ case BinaryConsts::Return: visitReturn((curr = allocator.alloc<Return>())->cast<Return>()); break;
case BinaryConsts::Nop: visitNop((curr = allocator.alloc<Nop>())->cast<Nop>()); break;
case BinaryConsts::Unreachable: visitUnreachable((curr = allocator.alloc<Unreachable>())->cast<Unreachable>()); break;
default: {
@@ -1603,6 +1613,10 @@ public:
readExpression(curr->condition);
curr->finalize();
}
+ void visitReturn(Return *curr) {
+ if (debug) std::cerr << "zz node: Return" << std::endl;
+ readExpression(curr->value);
+ }
bool maybeVisitImpl(Host *curr, uint8_t code) {
switch (code) {
case BinaryConsts::MemorySize: {
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index bcd8dee28..086b9751e 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -34,7 +34,8 @@ using namespace cashew;
// Utilities
-IString WASM("wasm");
+IString WASM("wasm"),
+ RETURN_FLOW("*return:)*");
enum {
pageSize = 64*1024,
@@ -623,6 +624,17 @@ private:
if (ifFalse.breaking()) return ifFalse;
return condition.value.geti32() ? ifTrue : ifFalse; // ;-)
}
+ Flow visitReturn(Return *curr) {
+ NOTE_ENTER("Return");
+ Flow flow;
+ if (curr->value) {
+ flow = visit(curr->value);
+ if (flow.breaking()) return flow;
+ NOTE_EVAL1(flow.value);
+ }
+ flow.breakTo = RETURN_FLOW;
+ return flow;
+ }
Flow visitHost(Host *curr) {
NOTE_ENTER("Host");
switch (curr->op) {
@@ -738,7 +750,7 @@ private:
#endif
Flow flow = ExpressionRunner(*this, scope).visit(function->body);
- assert(!flow.breaking()); // cannot still be breaking, it means we missed our stop
+ assert(!flow.breaking() || flow.breakTo == RETURN_FLOW); // cannot still be breaking, it means we missed our stop
Literal ret = flow.value;
if (function->result == none) ret = Literal();
assert(function->result == ret.type);
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index c8d4015ea..d4a4b38b4 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -298,7 +298,6 @@ private:
size_t localIndex; // params and locals
size_t otherIndex;
std::vector<Name> labelStack;
- bool hasReturn;
Name getPrefixedName(std::string prefix) {
return IString((prefix + std::to_string(otherIndex++)).c_str(), false);
@@ -318,7 +317,6 @@ private:
func->body = nullptr;
localIndex = 0;
otherIndex = 0;
- hasReturn = false;
std::vector<NameType> typeParams; // we may have both params and a type. store the type info here
Block* autoBlock = nullptr; // we may need to add a block for the very top level
for (;i < s.size(); i++) {
@@ -382,20 +380,6 @@ private:
}
}
if (!func->body) func->body = allocator.alloc<Nop>();
- if (hasReturn) {
- Block* body = func->body->dyn_cast<Block>();
- if (!body) {
- body = allocator.alloc<Block>();
- body->list.push_back(func->body);
- func->body = body;
- }
- if (body->name.is()) {
- body = allocator.alloc<Block>();
- body->list.push_back(func->body);
- func->body = body;
- }
- body->name = FAKE_RETURN;
- }
wasm.addFunction(func);
currLocalTypes.clear();
labelStack.clear();
@@ -897,10 +881,7 @@ private:
}
Expression* makeReturn(Element& s) {
- // return will likely not remain in wasm, but is in the testcases, for now. fake it
- hasReturn = true;
- auto ret = allocator.alloc<Break>();
- ret->name = FAKE_RETURN;
+ auto ret = allocator.alloc<Return>();
if (s.size() >= 2) {
ret->value = parseExpression(s[1]);
}
diff --git a/src/wasm.h b/src/wasm.h
index ca396fd24..beb2d340d 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -317,6 +317,7 @@ public:
UnaryId,
BinaryId,
SelectId,
+ ReturnId,
HostId,
NopId,
UnreachableId
@@ -902,6 +903,25 @@ public:
}
};
+class Return : public Expression {
+public:
+ Expression *value;
+
+ Return() : Expression(ReturnId), value(nullptr) {}
+
+ std::ostream& doPrint(std::ostream &o, unsigned indent) {
+ printOpening(o, "return");
+ if (!value || value->is<Nop>()) {
+ // avoid a new line just for the parens
+ o << ")";
+ return o;
+ }
+ incIndent(o, indent);
+ printFullLine(o, indent, value);
+ return decIndent(o, indent);
+ }
+};
+
class Host : public Expression {
public:
Host() : Expression(HostId) {}
@@ -1233,6 +1253,7 @@ struct WasmVisitor {
ReturnType visitUnary(Unary *curr) { abort(); }
ReturnType visitBinary(Binary *curr) { abort(); }
ReturnType visitSelect(Select *curr) { abort(); }
+ ReturnType visitReturn(Return *curr) { abort(); }
ReturnType visitHost(Host *curr) { abort(); }
ReturnType visitNop(Nop *curr) { abort(); }
ReturnType visitUnreachable(Unreachable *curr) { abort(); }
@@ -1269,6 +1290,7 @@ struct WasmVisitor {
case Expression::Id::UnaryId: DELEGATE(Unary);
case Expression::Id::BinaryId: DELEGATE(Binary);
case Expression::Id::SelectId: DELEGATE(Select);
+ case Expression::Id::ReturnId: DELEGATE(Return);
case Expression::Id::HostId: DELEGATE(Host);
case Expression::Id::NopId: DELEGATE(Nop);
case Expression::Id::UnreachableId: DELEGATE(Unreachable);
@@ -1300,6 +1322,7 @@ std::ostream& Expression::print(std::ostream &o, unsigned indent) {
void visitUnary(Unary *curr) { curr->doPrint(o, indent); }
void visitBinary(Binary *curr) { curr->doPrint(o, indent); }
void visitSelect(Select *curr) { curr->doPrint(o, indent); }
+ void visitReturn(Return *curr) { curr->doPrint(o, indent); }
void visitHost(Host *curr) { curr->doPrint(o, indent); }
void visitNop(Nop *curr) { curr->doPrint(o, indent); }
void visitUnreachable(Unreachable *curr) { curr->doPrint(o, indent); }
@@ -1393,6 +1416,9 @@ struct ChildWalker : public WasmWalkerBase<ChildWalker<ParentType>> {
parent.walk(curr->ifTrue);
parent.walk(curr->ifFalse);
}
+ void visitReturn(Return *curr) {
+ parent.walk(curr->value);
+ }
void visitHost(Host *curr) {
ExpressionList& list = curr->operands;
for (size_t z = 0; z < list.size(); z++) {
@@ -1437,6 +1463,7 @@ struct WasmWalker : public WasmWalkerBase<SubType, ReturnType> {
ReturnType visitUnary(Unary *curr) {}
ReturnType visitBinary(Binary *curr) {}
ReturnType visitSelect(Select *curr) {}
+ ReturnType visitReturn(Return *curr) {}
ReturnType visitHost(Host *curr) {}
ReturnType visitNop(Nop *curr) {}
ReturnType visitUnreachable(Unreachable *curr) {}