@@ -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
@@ -1742,6 +1749,7 @@ void TNHOracle::scan(Function* func,
17421749 }
17431750 void visitArrayGet (ArrayGet* curr) { notePossibleTrap (curr->ref ); }
17441751 void visitArraySet (ArraySet* curr) { notePossibleTrap (curr->ref ); }
1752+ void visitArrayStore (ArrayStore* curr) { notePossibleTrap (curr->ref ); }
17451753 void visitArrayLen (ArrayLen* curr) { notePossibleTrap (curr->ref ); }
17461754 void visitArrayCopy (ArrayCopy* curr) {
17471755 notePossibleTrap (curr->srcRef );
@@ -2239,7 +2247,10 @@ struct Flower {
22392247 Expression* read);
22402248
22412249 // Similar to readFromData, but does a write for a struct.set or array.set.
2242- void writeToData (Expression* ref, Expression* value, Index fieldIndex);
2250+ void writeToData (Expression* ref,
2251+ Expression* value,
2252+ Index fieldIndex,
2253+ bool multibyte = false );
22432254
22442255 // We will need subtypes during the flow, so compute them once ahead of time.
22452256 std::unique_ptr<SubTypes> subTypes;
@@ -2576,7 +2587,7 @@ Flower::Flower(Module& wasm, const PassOptions& options)
25762587 for (const auto & [location, value] : roots) {
25772588#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
25782589 std::cout << " init root\n " ;
2579- dump (location);
2590+ dump (getLocation ( location) );
25802591 value.dump (std::cout, &wasm);
25812592 std::cout << ' \n ' ;
25822593#endif
@@ -2743,6 +2754,11 @@ bool Flower::updateContents(LocationIndex locationIndex,
27432754 } else if (auto * globalLoc = std::get_if<GlobalLocation>(&location)) {
27442755 filterGlobalContents (contents, *globalLoc);
27452756 filtered = true ;
2757+ } else if (auto * dataLoc = std::get_if<DataLocation>(&location)) {
2758+ // Multibyte array stores with differing widths can merge to Many, so
2759+ // filter again afterwards to fall back to the declared type limit.
2760+ filterDataContents (contents, *dataLoc);
2761+ filtered = true ;
27462762 }
27472763
27482764 // Check if anything changed after filtering, if we did so.
@@ -2829,6 +2845,9 @@ void Flower::flowAfterUpdate(LocationIndex locationIndex) {
28292845 } else if (auto * set = parent->dynCast <ArraySet>()) {
28302846 assert (set->ref == child || set->value == child);
28312847 writeToData (set->ref , set->value , 0 );
2848+ } else if (auto * store = parent->dynCast <ArrayStore>()) {
2849+ assert (store->ref == child || store->value == child);
2850+ writeToData (store->ref , store->value , 0 , /* multibyte*/ true );
28322851 } else if (auto * get = parent->dynCast <RefGetDesc>()) {
28332852 // Similar to struct.get.
28342853 assert (get->ref == child);
@@ -3006,6 +3025,13 @@ void Flower::filterDataContents(PossibleContents& contents,
30063025 contents = PossibleContents::none ();
30073026 return ;
30083027 }
3028+ if (contents.isMany ()) {
3029+ // An unknown state (e.g. from combining writes of different types like in
3030+ // multibyte array stores) translates into the most generic bounded type.
3031+ // TODO: We could optimize these, as e.g. a write of i16 0x1212 does not
3032+ // actually conflict with a write of i8 0x12.
3033+ contents = PossibleContents::fromType (field->type );
3034+ }
30093035
30103036 if (field->isPacked ()) {
30113037 // We must handle packed fields carefully.
@@ -3188,7 +3214,10 @@ void Flower::readFromData(Type declaredType,
31883214 connectDuringFlow (coneReadLocation, ExpressionLocation{read, 0 });
31893215}
31903216
3191- void Flower::writeToData (Expression* ref, Expression* value, Index fieldIndex) {
3217+ void Flower::writeToData (Expression* ref,
3218+ Expression* value,
3219+ Index fieldIndex,
3220+ bool multibyte) {
31923221#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
31933222 std::cout << " add special writes\n " ;
31943223#endif
@@ -3236,6 +3265,9 @@ void Flower::writeToData(Expression* ref, Expression* value, Index fieldIndex) {
32363265 // As in readFromData, normalize to the proper cone.
32373266 auto cone = refContents.getCone ();
32383267 auto normalizedDepth = getNormalizedConeDepth (cone.type , cone.depth );
3268+ if (multibyte) {
3269+ valueContents = PossibleContents::fromType (value->type );
3270+ }
32393271
32403272 subTypes->iterSubTypes (
32413273 cone.type .getHeapType (), normalizedDepth, [&](HeapType type, Index depth) {
0 commit comments