diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 19 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 26 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 14 |
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; |