summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp19
-rw-r--r--src/wasm/wasm-s-parser.cpp12
-rw-r--r--src/wasm/wasm-stack.cpp6
-rw-r--r--src/wasm/wasm-validator.cpp26
-rw-r--r--src/wasm/wasm.cpp14
5 files changed, 77 insertions, 0 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index ee3c1a6fa..b6a5daf14 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -3574,6 +3574,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitArrayNew(curr, opcode)) {
break;
}
+ if (maybeVisitArrayInit(curr, opcode)) {
+ break;
+ }
if (maybeVisitArrayGet(curr, opcode)) {
break;
}
@@ -6508,6 +6511,22 @@ bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) {
return true;
}
+bool WasmBinaryBuilder::maybeVisitArrayInit(Expression*& out, uint32_t code) {
+ if (code != BinaryConsts::ArrayInit) {
+ return false;
+ }
+ auto heapType = getIndexedHeapType();
+ auto size = getU32LEB();
+ auto* rtt = popNonVoidExpression();
+ validateHeapTypeUsingChild(rtt, heapType);
+ std::vector<Expression*> values(size);
+ for (size_t i = 0; i < size; i++) {
+ values[size - i - 1] = popNonVoidExpression();
+ }
+ out = Builder(wasm).makeArrayInit(rtt, values);
+ return true;
+}
+
bool WasmBinaryBuilder::maybeVisitArrayGet(Expression*& out, uint32_t code) {
bool signed_ = false;
switch (code) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index c9ca71a6d..28028c459 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2680,6 +2680,18 @@ Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) {
return Builder(wasm).makeArrayNew(rtt, size, init);
}
+Expression* SExpressionWasmBuilder::makeArrayInit(Element& s) {
+ auto heapType = parseHeapType(*s[1]);
+ size_t i = 2;
+ std::vector<Expression*> values;
+ while (i < s.size() - 1) {
+ values.push_back(parseExpression(*s[i++]));
+ }
+ auto* rtt = parseExpression(*s[i++]);
+ validateHeapTypeUsingChild(rtt, heapType, s);
+ return Builder(wasm).makeArrayInit(rtt, values);
+}
+
Expression* SExpressionWasmBuilder::makeArrayGet(Element& s, bool signed_) {
auto heapType = parseHeapType(*s[1]);
auto ref = parseExpression(*s[2]);
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 7b682a264..e5460cf6f 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2040,6 +2040,12 @@ void BinaryInstWriter::visitArrayNew(ArrayNew* curr) {
parent.writeIndexedHeapType(curr->rtt->type.getHeapType());
}
+void BinaryInstWriter::visitArrayInit(ArrayInit* curr) {
+ o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayInit);
+ parent.writeIndexedHeapType(curr->rtt->type.getHeapType());
+ o << U32LEB(curr->values.size());
+}
+
void BinaryInstWriter::visitArrayGet(ArrayGet* curr) {
auto heapType = curr->ref->type.getHeapType();
const auto& field = heapType.getArray().element;
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 450a7b956..eaeea7f1a 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -382,6 +382,7 @@ public:
void visitStructGet(StructGet* curr);
void visitStructSet(StructSet* curr);
void visitArrayNew(ArrayNew* curr);
+ void visitArrayInit(ArrayInit* curr);
void visitArrayGet(ArrayGet* curr);
void visitArraySet(ArraySet* curr);
void visitArrayLen(ArrayLen* curr);
@@ -2416,6 +2417,31 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) {
}
}
+void FunctionValidator::visitArrayInit(ArrayInit* curr) {
+ shouldBeTrue(getModule()->features.hasGC(),
+ curr,
+ "array.init requires gc to be enabled");
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "array.init rtt must be rtt")) {
+ return;
+ }
+ auto heapType = curr->rtt->type.getHeapType();
+ if (!shouldBeTrue(
+ heapType.isArray(), curr, "array.init heap type must be array")) {
+ return;
+ }
+ const auto& element = heapType.getArray().element;
+ for (auto* value : curr->values) {
+ shouldBeSubType(value->type,
+ element.type,
+ curr,
+ "array.init value must have proper type");
+ }
+}
+
void FunctionValidator::visitArrayGet(ArrayGet* curr) {
shouldBeTrue(
getModule()->features.hasGC(), curr, "array.get requires gc to be enabled");
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 0dfcf5c2e..761c17116 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1035,6 +1035,20 @@ void ArrayNew::finalize() {
type = Type(rtt->type.getHeapType(), NonNullable);
}
+void ArrayInit::finalize() {
+ if (rtt->type == Type::unreachable) {
+ type = Type::unreachable;
+ return;
+ }
+ for (auto* value : values) {
+ if (value->type == Type::unreachable) {
+ type = Type::unreachable;
+ return;
+ }
+ }
+ type = Type(rtt->type.getHeapType(), NonNullable);
+}
+
void ArrayGet::finalize() {
if (ref->type == Type::unreachable || index->type == Type::unreachable) {
type = Type::unreachable;