summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/gen-s-parser.py27
-rw-r--r--src/gen-s-parser.inc3
-rw-r--r--src/ir/ReFinalize.cpp1
-rw-r--r--src/ir/cost.h7
-rw-r--r--src/ir/effects.h1
-rw-r--r--src/ir/global-utils.h2
-rw-r--r--src/ir/properties.cpp1
-rw-r--r--src/js/binaryen.js-post.js1
-rw-r--r--src/passes/Precompute.cpp1
-rw-r--r--src/passes/Print.cpp4
-rw-r--r--src/wasm-binary.h2
-rw-r--r--src/wasm-builder.h8
-rw-r--r--src/wasm-delegations-fields.def7
-rw-r--r--src/wasm-delegations.def1
-rw-r--r--src/wasm-interpreter.h21
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm.h11
-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
-rw-r--r--src/wasm2js.h4
-rw-r--r--test/binaryen.js/kitchen-sink.js1
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt7
-rw-r--r--test/heap-types.wast17
-rw-r--r--test/heap-types.wast.from-wast23
-rw-r--r--test/heap-types.wast.fromBinary23
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo23
-rw-r--r--test/passes/Oz_fuzz-exec_all-features.txt35
-rw-r--r--test/passes/Oz_fuzz-exec_all-features.wast22
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)))