diff options
31 files changed, 308 insertions, 23 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 36d9ff316..50ffdb301 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -559,19 +559,20 @@ instructions = [ ("struct.set", "makeStructSet(s)"), ("array.new_with_rtt", "makeArrayNew(s, false)"), ("array.new_default_with_rtt", "makeArrayNew(s, true)"), - ("array.get", "makeArrayGet(s)"), - ("array.get_s", "makeArrayGet(s, true)"), - ("array.get_u", "makeArrayGet(s, false)"), - ("array.set", "makeArraySet(s)"), - ("array.len", "makeArrayLen(s)"), - ("array.copy", "makeArrayCopy(s)"), - ("ref.is_func", "makeRefIs(s, RefIsFunc)"), - ("ref.is_data", "makeRefIs(s, RefIsData)"), - ("ref.is_i31", "makeRefIs(s, RefIsI31)"), - ("ref.as_non_null", "makeRefAs(s, RefAsNonNull)"), - ("ref.as_func", "makeRefAs(s, RefAsFunc)"), - ("ref.as_data", "makeRefAs(s, RefAsData)"), - ("ref.as_i31", "makeRefAs(s, RefAsI31)"), + ("array.init", "makeArrayInit(s)"), + ("array.get", "makeArrayGet(s)"), + ("array.get_s", "makeArrayGet(s, true)"), + ("array.get_u", "makeArrayGet(s, false)"), + ("array.set", "makeArraySet(s)"), + ("array.len", "makeArrayLen(s)"), + ("array.copy", "makeArrayCopy(s)"), + ("ref.is_func", "makeRefIs(s, RefIsFunc)"), + ("ref.is_data", "makeRefIs(s, RefIsData)"), + ("ref.is_i31", "makeRefIs(s, RefIsI31)"), + ("ref.as_non_null", "makeRefAs(s, RefAsNonNull)"), + ("ref.as_func", "makeRefAs(s, RefAsFunc)"), + ("ref.as_data", "makeRefAs(s, RefAsData)"), + ("ref.as_i31", "makeRefAs(s, RefAsI31)"), ] diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 9cb1962e8..7374e630a 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -33,6 +33,9 @@ switch (op[0]) { default: goto parse_error; } } + case 'i': + if (strcmp(op, "array.init") == 0) { return makeArrayInit(s); } + goto parse_error; case 'l': if (strcmp(op, "array.len") == 0) { return makeArrayLen(s); } goto parse_error; diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 419b83cc2..0d089a7ce 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -162,6 +162,7 @@ void ReFinalize::visitStructNew(StructNew* curr) { curr->finalize(); } void ReFinalize::visitStructGet(StructGet* curr) { curr->finalize(); } void ReFinalize::visitStructSet(StructSet* curr) { curr->finalize(); } void ReFinalize::visitArrayNew(ArrayNew* curr) { curr->finalize(); } +void ReFinalize::visitArrayInit(ArrayInit* curr) { curr->finalize(); } void ReFinalize::visitArrayGet(ArrayGet* curr) { curr->finalize(); } void ReFinalize::visitArraySet(ArraySet* curr) { curr->finalize(); } void ReFinalize::visitArrayLen(ArrayLen* curr) { curr->finalize(); } diff --git a/src/ir/cost.h b/src/ir/cost.h index 63424c8b3..e3e6aebf3 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -606,6 +606,13 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { CostType visitArrayNew(ArrayNew* curr) { return 4 + visit(curr->rtt) + visit(curr->size) + maybeVisit(curr->init); } + CostType visitArrayInit(ArrayInit* curr) { + CostType ret = 4 + visit(curr->rtt); + for (auto* child : curr->values) { + ret += visit(child); + } + return ret; + } CostType visitArrayGet(ArrayGet* curr) { return 1 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->index); } diff --git a/src/ir/effects.h b/src/ir/effects.h index 475e6f2b1..ad8f68efa 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -642,6 +642,7 @@ private: } } void visitArrayNew(ArrayNew* curr) {} + void visitArrayInit(ArrayInit* curr) {} void visitArrayGet(ArrayGet* curr) { parent.readsArray = true; // traps when the arg is null or the index out of bounds diff --git a/src/ir/global-utils.h b/src/ir/global-utils.h index cf0c8e1a9..34c0e56cf 100644 --- a/src/ir/global-utils.h +++ b/src/ir/global-utils.h @@ -65,7 +65,7 @@ inline bool canInitializeGlobal(Expression* curr) { } if (Properties::isSingleConstantExpression(curr) || curr->is<GlobalGet>() || curr->is<RttCanon>() || curr->is<RttSub>() || curr->is<StructNew>() || - curr->is<ArrayNew>() || curr->is<I31New>()) { + curr->is<ArrayNew>() || curr->is<ArrayInit>() || curr->is<I31New>()) { for (auto* child : ChildIterator(curr)) { if (!canInitializeGlobal(child)) { return false; diff --git a/src/ir/properties.cpp b/src/ir/properties.cpp index fa4f299b3..4739fcaaf 100644 --- a/src/ir/properties.cpp +++ b/src/ir/properties.cpp @@ -32,6 +32,7 @@ bool isGenerative(Expression* curr, FeatureSet features) { bool generative = false; void visitStructNew(StructNew* curr) { generative = true; } void visitArrayNew(ArrayNew* curr) { generative = true; } + void visitArrayInit(ArrayInit* curr) { generative = true; } } scanner; scanner.walk(curr); return scanner.generative; diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index a91d5af31..94f2d446c 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -109,6 +109,7 @@ function initializeConstants() { 'StructGet', 'StructSet', 'ArrayNew', + 'ArrayInit', 'ArrayGet', 'ArraySet', 'ArrayLen' diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 1ba298605..76ed547c1 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -94,6 +94,7 @@ public: Flow visitStructNew(StructNew* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitStructGet(StructGet* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitArrayNew(ArrayNew* curr) { return Flow(NONCONSTANT_FLOW); } + Flow visitArrayInit(ArrayInit* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitArrayGet(ArrayGet* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitArrayLen(ArrayLen* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitArrayCopy(ArrayCopy* curr) { return Flow(NONCONSTANT_FLOW); } diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 616ce9759..00b09dea4 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2006,6 +2006,10 @@ struct PrintExpressionContents o << "with_rtt "; TypeNamePrinter(o, wasm).print(curr->rtt->type.getHeapType()); } + void visitArrayInit(ArrayInit* curr) { + printMedium(o, "array.init "); + TypeNamePrinter(o, wasm).print(curr->rtt->type.getHeapType()); + } void visitArrayGet(ArrayGet* curr) { if (printUnreachableReplacement(curr->ref)) { return; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 13925f5e1..0c95f2b44 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1056,6 +1056,7 @@ enum ASTNodes { ArraySet = 0x16, ArrayLen = 0x17, ArrayCopy = 0x18, + ArrayInit = 0x19, I31New = 0x20, I31GetS = 0x21, I31GetU = 0x22, @@ -1626,6 +1627,7 @@ public: bool maybeVisitStructGet(Expression*& out, uint32_t code); bool maybeVisitStructSet(Expression*& out, uint32_t code); bool maybeVisitArrayNew(Expression*& out, uint32_t code); + bool maybeVisitArrayInit(Expression*& out, uint32_t code); bool maybeVisitArrayGet(Expression*& out, uint32_t code); bool maybeVisitArraySet(Expression*& out, uint32_t code); bool maybeVisitArrayLen(Expression*& out, uint32_t code); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 3eb263580..018b0bf8b 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -840,6 +840,14 @@ public: ret->finalize(); return ret; } + ArrayInit* makeArrayInit(Expression* rtt, + const std::vector<Expression*>& values) { + auto* ret = wasm.allocator.alloc<ArrayInit>(); + ret->rtt = rtt; + ret->values.set(values); + ret->finalize(); + return ret; + } ArrayGet* makeArrayGet(Expression* ref, Expression* index, bool signed_ = false) { auto* ret = wasm.allocator.alloc<ArrayGet>(); diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index ab68b5206..b94aa5599 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -634,6 +634,13 @@ switch (DELEGATE_ID) { DELEGATE_END(ArrayNew); break; } + case Expression::Id::ArrayInitId: { + DELEGATE_START(ArrayInit); + DELEGATE_FIELD_CHILD(ArrayInit, rtt); + DELEGATE_FIELD_CHILD_VECTOR(ArrayInit, values); + DELEGATE_END(ArrayInit); + break; + } case Expression::Id::ArrayGetId: { DELEGATE_START(ArrayGet); DELEGATE_FIELD_CHILD(ArrayGet, index); diff --git a/src/wasm-delegations.def b/src/wasm-delegations.def index 358a04dcd..2579ac621 100644 --- a/src/wasm-delegations.def +++ b/src/wasm-delegations.def @@ -75,6 +75,7 @@ DELEGATE(StructNew); DELEGATE(StructGet); DELEGATE(StructSet); DELEGATE(ArrayNew); +DELEGATE(ArrayInit); DELEGATE(ArrayGet); DELEGATE(ArraySet); DELEGATE(ArrayLen); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 77e432436..9fc11de76 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1702,6 +1702,27 @@ public: return Flow(Literal(std::make_shared<GCData>(rtt.getSingleValue(), data), curr->type)); } + Flow visitArrayInit(ArrayInit* curr) { + NOTE_ENTER("ArrayInit"); + auto rtt = this->visit(curr->rtt); + if (rtt.breaking()) { + return rtt; + } + Index num = curr->values.size(); + if (num >= ArrayLimit) { + hostLimit("allocation failure"); + } + Literals data(num); + for (Index i = 0; i < num; i++) { + auto value = this->visit(curr->values[i]); + if (value.breaking()) { + return value; + } + data[i] = value.getSingleValue(); + } + return Flow(Literal(std::make_shared<GCData>(rtt.getSingleValue(), data), + curr->type)); + } Flow visitArrayGet(ArrayGet* curr) { NOTE_ENTER("ArrayGet"); Flow ref = this->visit(curr->ref); diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index e5ba2996e..03462a7cb 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -284,6 +284,7 @@ private: Expression* makeStructGet(Element& s, bool signed_ = false); Expression* makeStructSet(Element& s); Expression* makeArrayNew(Element& s, bool default_); + Expression* makeArrayInit(Element& s); Expression* makeArrayGet(Element& s, bool signed_ = false); Expression* makeArraySet(Element& s); Expression* makeArrayLen(Element& s); diff --git a/src/wasm.h b/src/wasm.h index c4a58f3a4..2efbbfd9c 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -641,6 +641,7 @@ public: StructGetId, StructSetId, ArrayNewId, + ArrayInitId, ArrayGetId, ArraySetId, ArrayLenId, @@ -1468,6 +1469,16 @@ public: void finalize(); }; +class ArrayInit : public SpecificExpression<Expression::ArrayInitId> { +public: + ArrayInit(MixedArena& allocator) : values(allocator) {} + + ExpressionList values; + Expression* rtt; + + void finalize(); +}; + class ArrayGet : public SpecificExpression<Expression::ArrayGetId> { public: ArrayGet(MixedArena& allocator) {} 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; diff --git a/src/wasm2js.h b/src/wasm2js.h index e2b95f114..370546134 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2239,6 +2239,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, unimplemented(curr); WASM_UNREACHABLE("unimp"); } + Ref visitArrayInit(ArrayInit* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } Ref visitArrayGet(ArrayGet* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 04aca99f7..7a3007cfe 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -180,6 +180,7 @@ function test_ids() { console.log("StructGetId: " + binaryen.StructGetId); console.log("StructSetId: " + binaryen.StructSetId); console.log("ArrayNewId: " + binaryen.ArrayNewId); + console.log("ArrayInitId: " + binaryen.ArrayInitId); console.log("ArrayGetId: " + binaryen.ArrayGetId); console.log("ArraySetId: " + binaryen.ArraySetId); console.log("ArrayLenId: " + binaryen.ArrayLenId); diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index b9462e68c..95236a4be 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -104,9 +104,10 @@ StructNewId: 58 StructGetId: 59 StructSetId: 60 ArrayNewId: 61 -ArrayGetId: 62 -ArraySetId: 63 -ArrayLenId: 64 +ArrayInitId: 62 +ArrayGetId: 63 +ArraySetId: 64 +ArrayLenId: 65 getExpressionInfo={"id":15,"type":4,"op":6} (f32.neg (f32.const -33.61199951171875) diff --git a/test/heap-types.wast b/test/heap-types.wast index f62003da5..750467946 100644 --- a/test/heap-types.wast +++ b/test/heap-types.wast @@ -379,4 +379,21 @@ (i32.const 1337) ) ) + (func $array-init (result (ref $vector)) + (array.init $vector + (f64.const 1) + (f64.const 2) + (f64.const 4) + (f64.const 8) + (rtt.canon $vector) + ) + ) + (func $array-init-packed (result (ref $bytes)) + (array.init $bytes + (i32.const 4) + (i32.const 2) + (i32.const 1) + (rtt.canon $bytes) + ) + ) ) diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast index ddc590ce7..32e29bfba 100644 --- a/test/heap-types.wast.from-wast +++ b/test/heap-types.wast.from-wast @@ -1,23 +1,25 @@ (module (type $struct.A (struct (field i32) (field f32) (field $named f64))) + (type $vector (array (mut f64))) (type $none_=>_none (func)) (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) - (type $vector (array (mut f64))) (type $grandchild (struct (field i32) (field i64))) (type $struct.C (struct (field $named-mut (mut f32)))) (type $matrix (array (mut (ref null $vector)))) (type $parent (struct )) (type $child (struct (field i32))) + (type $bytes (array (mut i8))) (type $anyref_=>_none (func (param anyref))) (type $nested-child-struct (struct (field (mut (ref $child))))) (type $ref|$struct.A|_=>_ref|$struct.B| (func (param (ref $struct.A)) (result (ref $struct.B)))) (type $ref|$vector|_=>_ref|$matrix| (func (param (ref $vector)) (result (ref $matrix)))) - (type $bytes (array (mut i8))) (type $words (array (mut i32))) (type $nested-child-array (array (mut (ref $child)))) (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) (type $rtt_$parent_=>_none (func (param (rtt $parent)))) (type $ref|$vector|_ref?|$vector|_=>_none (func (param (ref $vector) (ref null $vector)))) + (type $none_=>_ref|$vector| (func (result (ref $vector)))) + (type $none_=>_ref|$bytes| (func (result (ref $bytes)))) (global $rttparent (rtt 0 $parent) (rtt.canon $parent)) (global $rttchild (rtt 1 $child) (rtt.sub $child (global.get $rttparent) @@ -468,4 +470,21 @@ (i32.const 1337) ) ) + (func $array-init (result (ref $vector)) + (array.init $vector + (f64.const 1) + (f64.const 2) + (f64.const 4) + (f64.const 8) + (rtt.canon $vector) + ) + ) + (func $array-init-packed (result (ref $bytes)) + (array.init $bytes + (i32.const 4) + (i32.const 2) + (i32.const 1) + (rtt.canon $bytes) + ) + ) ) diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary index 74c47eddf..a9bff28f3 100644 --- a/test/heap-types.wast.fromBinary +++ b/test/heap-types.wast.fromBinary @@ -1,23 +1,25 @@ (module (type $struct.A (struct (field i32) (field f32) (field $named f64))) + (type $vector (array (mut f64))) (type $none_=>_none (func)) (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) - (type $vector (array (mut f64))) (type $grandchild (struct (field i32) (field i64))) (type $matrix (array (mut (ref null $vector)))) (type $struct.C (struct (field $named-mut (mut f32)))) (type $parent (struct )) (type $child (struct (field i32))) + (type $bytes (array (mut i8))) (type $anyref_=>_none (func (param anyref))) (type $nested-child-struct (struct (field (mut (ref $child))))) (type $ref|$struct.A|_=>_ref|$struct.B| (func (param (ref $struct.A)) (result (ref $struct.B)))) (type $ref|$vector|_=>_ref|$matrix| (func (param (ref $vector)) (result (ref $matrix)))) - (type $bytes (array (mut i8))) (type $words (array (mut i32))) (type $nested-child-array (array (mut (ref $child)))) (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) (type $rtt_$parent_=>_none (func (param (rtt $parent)))) (type $ref|$vector|_ref?|$vector|_=>_none (func (param (ref $vector) (ref null $vector)))) + (type $none_=>_ref|$vector| (func (result (ref $vector)))) + (type $none_=>_ref|$bytes| (func (result (ref $bytes)))) (global $rttparent (rtt 0 $parent) (rtt.canon $parent)) (global $rttchild (rtt 1 $child) (rtt.sub $child (global.get $rttparent) @@ -423,5 +425,22 @@ (i32.const 1337) ) ) + (func $array-init (result (ref $vector)) + (array.init $vector + (f64.const 1) + (f64.const 2) + (f64.const 4) + (f64.const 8) + (rtt.canon $vector) + ) + ) + (func $array-init-packed (result (ref $bytes)) + (array.init $bytes + (i32.const 4) + (i32.const 2) + (i32.const 1) + (rtt.canon $bytes) + ) + ) ) diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo index 66caa798a..5857e6689 100644 --- a/test/heap-types.wast.fromBinary.noDebugInfo +++ b/test/heap-types.wast.fromBinary.noDebugInfo @@ -1,23 +1,25 @@ (module (type ${i32_f32_f64} (struct (field i32) (field f32) (field f64))) + (type $[mut:f64] (array (mut f64))) (type $none_=>_none (func)) (type ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref ${i32_f32_f64})) (field (mut (ref ${i32_f32_f64}))))) - (type $[mut:f64] (array (mut f64))) (type ${i32_i64} (struct (field i32) (field i64))) (type $[mut:ref?|[mut:f64]|] (array (mut (ref null $[mut:f64])))) (type ${mut:f32} (struct (field (mut f32)))) (type ${} (struct )) (type ${i32} (struct (field i32))) + (type $[mut:i8] (array (mut i8))) (type $anyref_=>_none (func (param anyref))) (type ${mut:ref|{i32}|} (struct (field (mut (ref ${i32}))))) (type $ref|{i32_f32_f64}|_=>_ref|{i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}| (func (param (ref ${i32_f32_f64})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})))) (type $ref|[mut:f64]|_=>_ref|[mut:ref?|[mut:f64]|]| (func (param (ref $[mut:f64])) (result (ref $[mut:ref?|[mut:f64]|])))) - (type $[mut:i8] (array (mut i8))) (type $[mut:i32] (array (mut i32))) (type $[mut:ref|{i32}|] (array (mut (ref ${i32})))) (type $rtt_1_{}_=>_none (func (param (rtt 1 ${})))) (type $rtt_{}_=>_none (func (param (rtt ${})))) (type $ref|[mut:f64]|_ref?|[mut:f64]|_=>_none (func (param (ref $[mut:f64]) (ref null $[mut:f64])))) + (type $none_=>_ref|[mut:f64]| (func (result (ref $[mut:f64])))) + (type $none_=>_ref|[mut:i8]| (func (result (ref $[mut:i8])))) (global $global$0 (rtt 0 ${}) (rtt.canon ${})) (global $global$1 (rtt 1 ${i32}) (rtt.sub ${i32} (global.get $global$0) @@ -423,5 +425,22 @@ (i32.const 1337) ) ) + (func $20 (result (ref $[mut:f64])) + (array.init $[mut:f64] + (f64.const 1) + (f64.const 2) + (f64.const 4) + (f64.const 8) + (rtt.canon $[mut:f64]) + ) + ) + (func $21 (result (ref $[mut:i8])) + (array.init $[mut:i8] + (i32.const 4) + (i32.const 2) + (i32.const 1) + (rtt.canon $[mut:i8]) + ) + ) ) diff --git a/test/passes/Oz_fuzz-exec_all-features.txt b/test/passes/Oz_fuzz-exec_all-features.txt index 329853ae2..4ac373f75 100644 --- a/test/passes/Oz_fuzz-exec_all-features.txt +++ b/test/passes/Oz_fuzz-exec_all-features.txt @@ -61,6 +61,10 @@ [LoggingExternalInterface logging 1] [LoggingExternalInterface logging 0] [LoggingExternalInterface logging 1] +[fuzz-exec] calling array.init +[LoggingExternalInterface logging 2] +[LoggingExternalInterface logging 42] +[LoggingExternalInterface logging 50] (module (type $extendedstruct (struct (field (mut i32)) (field f64))) (type $struct (struct (field (mut i32)))) @@ -90,6 +94,7 @@ (export "cast-func-to-struct" (func $19)) (export "array-copy" (func $20)) (export "rtt_Fresh" (func $21)) + (export "array.init" (func $22)) (func $0 (; has Stack IR ;) (local $0 i32) (call $log @@ -456,6 +461,32 @@ ) ) ) + (func $22 (; has Stack IR ;) + (local $0 (ref null $bytes)) + (call $log + (array.len $bytes + (local.tee $0 + (array.init $bytes + (i32.const 42) + (i32.const 50) + (rtt.canon $bytes) + ) + ) + ) + ) + (call $log + (array.get_u $bytes + (local.get $0) + (i32.const 0) + ) + ) + (call $log + (array.get_u $bytes + (local.get $0) + (i32.const 1) + ) + ) + ) ) [fuzz-exec] calling structs [LoggingExternalInterface logging 0] @@ -519,6 +550,10 @@ [LoggingExternalInterface logging 1] [LoggingExternalInterface logging 0] [LoggingExternalInterface logging 1] +[fuzz-exec] calling array.init +[LoggingExternalInterface logging 2] +[LoggingExternalInterface logging 42] +[LoggingExternalInterface logging 50] ignoring comparison of ExecutionResults! [fuzz-exec] calling foo [host limit allocation failure] diff --git a/test/passes/Oz_fuzz-exec_all-features.wast b/test/passes/Oz_fuzz-exec_all-features.wast index 520747075..a41e2bf70 100644 --- a/test/passes/Oz_fuzz-exec_all-features.wast +++ b/test/passes/Oz_fuzz-exec_all-features.wast @@ -475,6 +475,28 @@ ) ) ) + (func "array.init" + (local $x (ref null $bytes)) + (local.set $x + (array.init $bytes + (i32.const 42) ;; first value + (i32.const 50) ;; second value + (rtt.canon $bytes) + ) + ) + ;; The length should be 2 + (call $log + (array.len $bytes (local.get $x)) + ) + ;; The first value should be 42 + (call $log + (array.get_u $bytes (local.get $x) (i32.const 0)) + ) + ;; The second value should be 50 + (call $log + (array.get_u $bytes (local.get $x) (i32.const 1)) + ) + ) ) (module (type $[mut:i8] (array (mut i8))) |