Skip to content

Commit 2f3a132

Browse files
committed
Implement multibyte array store instructions
Add support for multibyte array store instructions as proposed in the WebAssembly multibyte proposal. These instructions allow storing values of various byte widths directly into i8 arrays, avoiding the need for manual bit manipulation and masking. Link: https://github.com/WebAssembly/multibyte
1 parent 7317be6 commit 2f3a132

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1083
-167
lines changed

scripts/clusterfuzz/run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
'--disable-strings',
9595
'--disable-stack-switching',
9696
'--disable-relaxed-atomics',
97+
'--disable-multibyte',
9798
]
9899

99100

src/binaryen-c.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ BinaryenFeatures BinaryenFeatureCallIndirectOverlong(void) {
502502
BinaryenFeatures BinaryenFeatureRelaxedAtomics(void) {
503503
return static_cast<BinaryenFeatures>(FeatureSet::RelaxedAtomics);
504504
}
505+
BinaryenFeatures BinaryenFeatureMultibyte(void) {
506+
return static_cast<BinaryenFeatures>(FeatureSet::Multibyte);
507+
}
505508
BinaryenFeatures BinaryenFeatureAll(void) {
506509
return static_cast<BinaryenFeatures>(FeatureSet::All);
507510
}

src/binaryen-c.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ BINARYEN_API BinaryenFeatures BinaryenFeatureFP16(void);
244244
BINARYEN_API BinaryenFeatures BinaryenFeatureBulkMemoryOpt(void);
245245
BINARYEN_API BinaryenFeatures BinaryenFeatureCallIndirectOverlong(void);
246246
BINARYEN_API BinaryenFeatures BinaryenFeatureRelaxedAtomics(void);
247+
BINARYEN_API BinaryenFeatures BinaryenFeatureMultibyte(void);
247248
BINARYEN_API BinaryenFeatures BinaryenFeatureAll(void);
248249

249250
// Modules

src/interpreter/interpreter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ struct ExpressionInterpreter : OverriddenVisitor<ExpressionInterpreter, Flow> {
262262
Flow visitArrayNewFixed(ArrayNewFixed* curr) { WASM_UNREACHABLE("TODO"); }
263263
Flow visitArrayGet(ArrayGet* curr) { WASM_UNREACHABLE("TODO"); }
264264
Flow visitArraySet(ArraySet* curr) { WASM_UNREACHABLE("TODO"); }
265+
Flow visitArrayStore(ArrayStore* curr) { WASM_UNREACHABLE("TODO"); }
265266
Flow visitArrayLen(ArrayLen* curr) { WASM_UNREACHABLE("TODO"); }
266267
Flow visitArrayCopy(ArrayCopy* curr) { WASM_UNREACHABLE("TODO"); }
267268
Flow visitArrayFill(ArrayFill* curr) { WASM_UNREACHABLE("TODO"); }

src/ir/ReFinalize.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ void ReFinalize::visitArrayNewElem(ArrayNewElem* curr) { curr->finalize(); }
171171
void ReFinalize::visitArrayNewFixed(ArrayNewFixed* curr) { curr->finalize(); }
172172
void ReFinalize::visitArrayGet(ArrayGet* curr) { curr->finalize(); }
173173
void ReFinalize::visitArraySet(ArraySet* curr) { curr->finalize(); }
174+
void ReFinalize::visitArrayStore(ArrayStore* curr) { curr->finalize(); }
174175
void ReFinalize::visitArrayLen(ArrayLen* curr) { curr->finalize(); }
175176
void ReFinalize::visitArrayCopy(ArrayCopy* curr) { curr->finalize(); }
176177
void ReFinalize::visitArrayFill(ArrayFill* curr) { curr->finalize(); }

src/ir/child-typer.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,20 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
10961096
note(&curr->value, type);
10971097
}
10981098

1099+
void visitArrayStore(ArrayStore* curr,
1100+
std::optional<HeapType> ht = std::nullopt) {
1101+
if (!ht) {
1102+
if (!curr->ref->type.isRef()) {
1103+
self().noteUnknown();
1104+
return;
1105+
}
1106+
ht = curr->ref->type.getHeapType();
1107+
}
1108+
note(&curr->ref, Type(*ht, Nullable));
1109+
note(&curr->index, Type::i32);
1110+
note(&curr->value, curr->valueType);
1111+
}
1112+
10991113
void visitArrayLen(ArrayLen* curr) {
11001114
note(&curr->ref, Type(HeapType::array, Nullable));
11011115
}

src/ir/cost.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,10 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
753753
return 2 + nullCheckCost(curr->ref) + visit(curr->ref) +
754754
visit(curr->index) + visit(curr->value);
755755
}
756+
CostType visitArrayStore(ArrayStore* curr) {
757+
return 2 + nullCheckCost(curr->ref) + visit(curr->ref) +
758+
visit(curr->index) + visit(curr->value);
759+
}
756760
CostType visitArrayLen(ArrayLen* curr) {
757761
return 1 + nullCheckCost(curr->ref) + visit(curr->ref);
758762
}

src/ir/effects.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,15 @@ class EffectAnalyzer {
10241024
// traps when the arg is null or the index out of bounds
10251025
parent.implicitTrap = true;
10261026
}
1027+
void visitArrayStore(ArrayStore* curr) {
1028+
if (curr->ref->type.isNull()) {
1029+
parent.trap = true;
1030+
return;
1031+
}
1032+
parent.writesArray = true;
1033+
// traps when the arg is null or the index out of bounds
1034+
parent.implicitTrap = true;
1035+
}
10271036
void visitArrayLen(ArrayLen* curr) {
10281037
if (curr->ref->type.isNull()) {
10291038
parent.trap = true;

src/ir/possible-contents.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,13 @@ struct InfoCollector
11021102
addChildParentLink(curr->ref, curr);
11031103
addChildParentLink(curr->value, curr);
11041104
}
1105+
void visitArrayStore(ArrayStore* curr) {
1106+
if (curr->ref->type == Type::unreachable) {
1107+
return;
1108+
}
1109+
addChildParentLink(curr->ref, curr);
1110+
addChildParentLink(curr->value, curr);
1111+
}
11051112

11061113
void visitArrayLen(ArrayLen* curr) {
11071114
// TODO: optimize when possible (perhaps we can infer a Literal for the
@@ -1739,6 +1746,7 @@ void TNHOracle::scan(Function* func,
17391746
}
17401747
void visitArrayGet(ArrayGet* curr) { notePossibleTrap(curr->ref); }
17411748
void visitArraySet(ArraySet* curr) { notePossibleTrap(curr->ref); }
1749+
void visitArrayStore(ArrayStore* curr) { notePossibleTrap(curr->ref); }
17421750
void visitArrayLen(ArrayLen* curr) { notePossibleTrap(curr->ref); }
17431751
void visitArrayCopy(ArrayCopy* curr) {
17441752
notePossibleTrap(curr->srcRef);

src/ir/subtype-exprs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,13 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
408408
auto array = curr->ref->type.getHeapType().getArray();
409409
self()->noteSubtype(curr->value, array.element.type);
410410
}
411+
void visitArrayStore(ArrayStore* curr) {
412+
if (!curr->ref->type.isArray()) {
413+
return;
414+
}
415+
auto array = curr->ref->type.getHeapType().getArray();
416+
self()->noteSubtype(curr->value, array.element.type);
417+
}
411418
void visitArrayLen(ArrayLen* curr) {}
412419
void visitArrayCopy(ArrayCopy* curr) {
413420
if (!curr->srcRef->type.isArray() || !curr->destRef->type.isArray()) {

0 commit comments

Comments
 (0)