summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp212
-rw-r--r--src/wasm/wasm-s-parser.cpp98
-rw-r--r--src/wasm/wasm-stack.cpp56
-rw-r--r--src/wasm/wasm-validator.cpp88
-rw-r--r--src/wasm/wasm.cpp37
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(); }