diff options
-rw-r--r-- | src/wasm-binary.h | 14 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 16 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 21 | ||||
-rw-r--r-- | src/wasm.h | 27 |
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) {} |