diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 212 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 98 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 56 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 88 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 37 |
5 files changed, 491 insertions, 0 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 48564a897..38a85bd1b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2715,6 +2715,42 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitI31Get(curr, opcode)) { break; } + if (maybeVisitRefTest(curr, opcode)) { + break; + } + if (maybeVisitRefCast(curr, opcode)) { + break; + } + if (maybeVisitBrOnCast(curr, opcode)) { + break; + } + if (maybeVisitRttCanon(curr, opcode)) { + break; + } + if (maybeVisitRttSub(curr, opcode)) { + break; + } + if (maybeVisitStructNew(curr, opcode)) { + break; + } + if (maybeVisitStructGet(curr, opcode)) { + break; + } + if (maybeVisitStructSet(curr, opcode)) { + break; + } + if (maybeVisitArrayNew(curr, opcode)) { + break; + } + if (maybeVisitArrayGet(curr, opcode)) { + break; + } + if (maybeVisitArraySet(curr, opcode)) { + break; + } + if (maybeVisitArrayLen(curr, opcode)) { + break; + } throwError("invalid code after GC prefix: " + std::to_string(opcode)); break; } @@ -5190,6 +5226,182 @@ bool WasmBinaryBuilder::maybeVisitI31Get(Expression*& out, uint32_t code) { return true; } +bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RefTest) { + return false; + } + auto* curr = allocator.alloc<RefTest>(); + WASM_UNREACHABLE("TODO (gc): ref.test"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RefCast) { + return false; + } + auto* curr = allocator.alloc<RefCast>(); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitBrOnCast(Expression*& out, uint32_t code) { + if (code != BinaryConsts::BrOnCast) { + return false; + } + auto* curr = allocator.alloc<BrOnCast>(); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitRttCanon(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RttCanon) { + return false; + } + auto* curr = allocator.alloc<RttCanon>(); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitRttSub(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RttSub) { + return false; + } + auto* curr = allocator.alloc<RttSub>(); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitStructNew(Expression*& out, uint32_t code) { + StructNew* curr; + switch (code) { + case BinaryConsts::StructNewWithRtt: + curr = allocator.alloc<StructNew>(); + // ... + break; + case BinaryConsts::StructNewDefaultWithRtt: + curr = allocator.alloc<StructNew>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): struct.new"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitStructGet(Expression*& out, uint32_t code) { + StructGet* curr; + switch (code) { + case BinaryConsts::StructGet: + curr = allocator.alloc<StructGet>(); + // ... + break; + case BinaryConsts::StructGetS: + curr = allocator.alloc<StructGet>(); + // ... + break; + case BinaryConsts::StructGetU: + curr = allocator.alloc<StructGet>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): struct.get"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitStructSet(Expression*& out, uint32_t code) { + if (code != BinaryConsts::StructSet) { + return false; + } + auto* curr = allocator.alloc<StructSet>(); + WASM_UNREACHABLE("TODO (gc): struct.set"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) { + ArrayNew* curr; + switch (code) { + case BinaryConsts::ArrayNewWithRtt: + curr = allocator.alloc<ArrayNew>(); + // ... + break; + case BinaryConsts::ArrayNewDefaultWithRtt: + curr = allocator.alloc<ArrayNew>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): array.new"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArrayGet(Expression*& out, uint32_t code) { + ArrayGet* curr; + switch (code) { + case BinaryConsts::ArrayGet: + curr = allocator.alloc<ArrayGet>(); + // ... + break; + case BinaryConsts::ArrayGetS: + curr = allocator.alloc<ArrayGet>(); + // ... + break; + case BinaryConsts::ArrayGetU: + curr = allocator.alloc<ArrayGet>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): array.get"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArraySet(Expression*& out, uint32_t code) { + if (code != BinaryConsts::ArraySet) { + return false; + } + auto* curr = allocator.alloc<ArraySet>(); + WASM_UNREACHABLE("TODO (gc): array.set"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArrayLen(Expression*& out, uint32_t code) { + if (code != BinaryConsts::ArrayLen) { + return false; + } + auto* curr = allocator.alloc<ArrayLen>(); + WASM_UNREACHABLE("TODO (gc): array.len"); + curr->finalize(); + out = curr; + return true; +} + void WasmBinaryBuilder::throwError(std::string text) { throw ParseException(text, 0, pos); } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 166fc88bb..63157b314 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1994,6 +1994,104 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { return ret; } +Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { + auto ret = allocator.alloc<RefTest>(); + WASM_UNREACHABLE("TODO (gc): ref.test"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { + auto ret = allocator.alloc<RefCast>(); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s) { + auto ret = allocator.alloc<BrOnCast>(); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeRttCanon(Element& s) { + auto ret = allocator.alloc<RttCanon>(); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeRttSub(Element& s) { + auto ret = allocator.alloc<RttSub>(); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { + auto ret = allocator.alloc<StructNew>(); + WASM_UNREACHABLE("TODO (gc): struct.new"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructGet(Element& s) { + auto ret = allocator.alloc<StructGet>(); + WASM_UNREACHABLE("TODO (gc): struct.get"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) { + auto ret = allocator.alloc<StructGet>(); + WASM_UNREACHABLE("TODO (gc): struct.get_s/u"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructSet(Element& s) { + auto ret = allocator.alloc<StructSet>(); + WASM_UNREACHABLE("TODO (gc): struct.set"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) { + auto ret = allocator.alloc<ArrayNew>(); + WASM_UNREACHABLE("TODO (gc): array.new"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayGet(Element& s) { + auto ret = allocator.alloc<ArrayGet>(); + WASM_UNREACHABLE("TODO (gc): array.get"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayGet(Element& s, bool signed_) { + auto ret = allocator.alloc<ArrayGet>(); + WASM_UNREACHABLE("TODO (gc): array.get_s/u"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArraySet(Element& s) { + auto ret = allocator.alloc<ArraySet>(); + WASM_UNREACHABLE("TODO (gc): array.set"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayLen(Element& s) { + auto ret = allocator.alloc<ArrayLen>(); + WASM_UNREACHABLE("TODO (gc): array.len"); + ret->finalize(); + return ret; +} + // converts an s-expression string representing binary data into an output // sequence of raw bytes this appends to data, which may already contain // content. diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1c16dff16..1ca8869c7 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1784,6 +1784,62 @@ void BinaryInstWriter::visitI31Get(I31Get* curr) { << U32LEB(curr->signed_ ? BinaryConsts::I31GetS : BinaryConsts::I31GetU); } +void BinaryInstWriter::visitRefTest(RefTest* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefTest); + WASM_UNREACHABLE("TODO (gc): ref.test"); +} + +void BinaryInstWriter::visitRefCast(RefCast* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefCast); + WASM_UNREACHABLE("TODO (gc): ref.cast"); +} + +void BinaryInstWriter::visitBrOnCast(BrOnCast* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnCast); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); +} + +void BinaryInstWriter::visitRttCanon(RttCanon* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttCanon); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); +} + +void BinaryInstWriter::visitRttSub(RttSub* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttSub); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); +} + +void BinaryInstWriter::visitStructNew(StructNew* curr) { + WASM_UNREACHABLE("TODO (gc): struct.new"); +} + +void BinaryInstWriter::visitStructGet(StructGet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.get"); +} + +void BinaryInstWriter::visitStructSet(StructSet* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StructSet); + WASM_UNREACHABLE("TODO (gc): struct.set"); +} + +void BinaryInstWriter::visitArrayNew(ArrayNew* curr) { + WASM_UNREACHABLE("TODO (gc): array.new"); +} + +void BinaryInstWriter::visitArrayGet(ArrayGet* curr) { + WASM_UNREACHABLE("TODO (gc): array.get"); +} + +void BinaryInstWriter::visitArraySet(ArraySet* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArraySet); + WASM_UNREACHABLE("TODO (gc): array.set"); +} + +void BinaryInstWriter::visitArrayLen(ArrayLen* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayLen); + WASM_UNREACHABLE("TODO (gc): array.len"); +} + void BinaryInstWriter::emitScopeEnd(Expression* curr) { assert(!breakStack.empty()); breakStack.pop_back(); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index ff2ed7e39..96871ad8e 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -340,6 +340,18 @@ public: void visitTupleExtract(TupleExtract* curr); void visitI31New(I31New* curr); void visitI31Get(I31Get* curr); + void visitRefTest(RefTest* curr); + void visitRefCast(RefCast* curr); + void visitBrOnCast(BrOnCast* curr); + void visitRttCanon(RttCanon* curr); + void visitRttSub(RttSub* curr); + void visitStructNew(StructNew* curr); + void visitStructGet(StructGet* curr); + void visitStructSet(StructSet* curr); + void visitArrayNew(ArrayNew* curr); + void visitArrayGet(ArrayGet* curr); + void visitArraySet(ArraySet* curr); + void visitArrayLen(ArrayLen* curr); void visitFunction(Function* curr); // helpers @@ -2135,6 +2147,82 @@ void FunctionValidator::visitI31Get(I31Get* curr) { "i31.get_s/u's argument should be i31ref"); } +void FunctionValidator::visitRefTest(RefTest* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "ref.test requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): ref.test"); +} + +void FunctionValidator::visitRefCast(RefCast* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "ref.cast requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): ref.cast"); +} + +void FunctionValidator::visitBrOnCast(BrOnCast* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "br_on_cast requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); +} + +void FunctionValidator::visitRttCanon(RttCanon* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "rtt.canon requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); +} + +void FunctionValidator::visitRttSub(RttSub* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "rtt.sub requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); +} + +void FunctionValidator::visitStructNew(StructNew* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "struct.new requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): struct.new"); +} + +void FunctionValidator::visitStructGet(StructGet* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "struct.get requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): struct.get"); +} + +void FunctionValidator::visitStructSet(StructSet* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "struct.set requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): struct.set"); +} + +void FunctionValidator::visitArrayNew(ArrayNew* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.new requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.new"); +} + +void FunctionValidator::visitArrayGet(ArrayGet* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.get requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.get"); +} + +void FunctionValidator::visitArraySet(ArraySet* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.set requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.set"); +} + +void FunctionValidator::visitArrayLen(ArrayLen* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.len requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.len"); +} + void FunctionValidator::visitFunction(Function* curr) { if (curr->sig.results.isTuple()) { shouldBeTrue(getModule()->features.hasMultivalue(), diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index c857b202c..738823d66 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -210,6 +210,30 @@ const char* getExpressionName(Expression* curr) { return "i31.new"; case Expression::Id::I31GetId: return "i31.get"; + case Expression::Id::RefTestId: + return "ref.test"; + case Expression::Id::RefCastId: + return "ref.cast"; + case Expression::Id::BrOnCastId: + return "br_on_cast"; + case Expression::Id::RttCanonId: + return "rtt.canon"; + case Expression::Id::RttSubId: + return "rtt.sub"; + case Expression::Id::StructNewId: + return "struct.new"; + case Expression::Id::StructGetId: + return "struct.get"; + case Expression::Id::StructSetId: + return "struct.set"; + case Expression::Id::ArrayNewId: + return "array.new"; + case Expression::Id::ArrayGetId: + return "array.get"; + case Expression::Id::ArraySetId: + return "array.set"; + case Expression::Id::ArrayLenId: + return "array.len"; case Expression::Id::NumExpressionIds: WASM_UNREACHABLE("invalid expr id"); } @@ -986,6 +1010,19 @@ void I31Get::finalize() { } } +// TODO (gc): ref.test +// TODO (gc): ref.cast +// TODO (gc): br_on_cast +// TODO (gc): rtt.canon +// TODO (gc): rtt.sub +// TODO (gc): struct.new +// TODO (gc): struct.get +// TODO (gc): struct.set +// TODO (gc): array.new +// TODO (gc): array.get +// TODO (gc): array.set +// TODO (gc): array.len + size_t Function::getNumParams() { return sig.params.size(); } size_t Function::getNumVars() { return vars.size(); } |