@@ -1073,16 +1073,19 @@ struct InfoCollector
10731073 if (curr->ref ->type == Type::unreachable) {
10741074 return ;
10751075 }
1076- // TODO: Model the modification part of the RMW in addition to the read and
1077- // the write.
1076+ addChildParentLink (curr->ref , curr);
1077+ addChildParentLink (curr->value , curr);
1078+ // TODO: Model the output
10781079 addRoot (curr);
10791080 }
10801081 void visitStructCmpxchg (StructCmpxchg* curr) {
10811082 if (curr->ref ->type == Type::unreachable) {
10821083 return ;
10831084 }
1084- // TODO: Model the modification part of the RMW in addition to the read and
1085- // the write.
1085+ addChildParentLink (curr->ref , curr);
1086+ addChildParentLink (curr->expected , curr);
1087+ addChildParentLink (curr->replacement , curr);
1088+ // TODO: Model the output
10861089 addRoot (curr);
10871090 }
10881091 void visitStructWait (StructWait* curr) { addRoot (curr); }
@@ -1171,16 +1174,19 @@ struct InfoCollector
11711174 if (curr->ref ->type == Type::unreachable) {
11721175 return ;
11731176 }
1174- // TODO: Model the modification part of the RMW in addition to the read and
1175- // the write.
1177+ addChildParentLink (curr->ref , curr);
1178+ addChildParentLink (curr->value , curr);
1179+ // TODO: Model the output
11761180 addRoot (curr);
11771181 }
11781182 void visitArrayCmpxchg (ArrayCmpxchg* curr) {
11791183 if (curr->ref ->type == Type::unreachable) {
11801184 return ;
11811185 }
1182- // TODO: Model the modification part of the RMW in addition to the read and
1183- // the write.
1186+ addChildParentLink (curr->ref , curr);
1187+ addChildParentLink (curr->expected , curr);
1188+ addChildParentLink (curr->replacement , curr);
1189+ // TODO: Model the output
11841190 addRoot (curr);
11851191 }
11861192 void visitStringNew (StringNew* curr) {
@@ -2247,10 +2253,12 @@ struct Flower {
22472253 Expression* read);
22482254
22492255 // Similar to readFromData, but does a write for a struct.set or array.set.
2256+ void writeToData (Expression* ref, Expression* value, Index fieldIndex);
2257+
2258+ // A write with given contents.
22502259 void writeToData (Expression* ref,
2251- Expression* value,
2252- Index fieldIndex,
2253- bool multibyte = false );
2260+ const PossibleContents& valueContents,
2261+ Index fieldIndex);
22542262
22552263 // We will need subtypes during the flow, so compute them once ahead of time.
22562264 std::unique_ptr<SubTypes> subTypes;
@@ -2839,6 +2847,18 @@ void Flower::flowAfterUpdate(LocationIndex locationIndex) {
28392847 // |child| is either the reference or the value child of a struct.set.
28402848 assert (set->ref == child || set->value == child);
28412849 writeToData (set->ref , set->value , set->index );
2850+ } else if (auto * set = parent->dynCast <StructRMW>()) {
2851+ assert (set->ref == child || set->value == child);
2852+ // TODO: model the stored value, depending on the actual operation.
2853+ writeToData (
2854+ set->ref , PossibleContents::fromType (set->value ->type ), set->index );
2855+ } else if (auto * set = parent->dynCast <StructCmpxchg>()) {
2856+ assert (set->ref == child || set->expected == child ||
2857+ set->replacement == child);
2858+ // TODO: model the stored value, depending on the actual operation.
2859+ writeToData (set->ref ,
2860+ PossibleContents::fromType (set->replacement ->type ),
2861+ set->index );
28422862 } else if (auto * get = parent->dynCast <ArrayGet>()) {
28432863 assert (get->ref == child);
28442864 readFromData (get->ref ->type , 0 , contents, get);
@@ -2847,9 +2867,21 @@ void Flower::flowAfterUpdate(LocationIndex locationIndex) {
28472867 writeToData (set->ref , set->value , 0 );
28482868 } else if (auto * store = parent->dynCast <ArrayStore>()) {
28492869 assert (store->ref == child || store->value == child);
2850- writeToData (store->ref , store->value , 0 , /* multibyte*/ true );
2870+ // TODO: model the stored value, and handle different but equal values in
2871+ // type, e.g. writing i16 0x1212 is the same as i8 0x12.
2872+ writeToData (
2873+ store->ref , PossibleContents::fromType (store->value ->type ), 0 );
2874+ } else if (auto * set = parent->dynCast <ArrayRMW>()) {
2875+ assert (set->ref == child || set->value == child);
2876+ // TODO: model the stored value, depending on the actual operation.
2877+ writeToData (set->ref , PossibleContents::fromType (set->value ->type ), 0 );
2878+ } else if (auto * set = parent->dynCast <ArrayCmpxchg>()) {
2879+ assert (set->ref == child || set->expected == child ||
2880+ set->replacement == child);
2881+ // TODO: model the stored value, depending on the actual operation.
2882+ writeToData (
2883+ set->ref , PossibleContents::fromType (set->replacement ->type ), 0 );
28512884 } else if (auto * get = parent->dynCast <RefGetDesc>()) {
2852- // Similar to struct.get.
28532885 assert (get->ref == child);
28542886 readFromData (
28552887 get->ref ->type , DataLocation::DescriptorIndex, contents, get);
@@ -3214,23 +3246,7 @@ void Flower::readFromData(Type declaredType,
32143246 connectDuringFlow (coneReadLocation, ExpressionLocation{read, 0 });
32153247}
32163248
3217- void Flower::writeToData (Expression* ref,
3218- Expression* value,
3219- Index fieldIndex,
3220- bool multibyte) {
3221- #if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
3222- std::cout << " add special writes\n " ;
3223- #endif
3224-
3225- auto refContents = getContents (getIndex (ExpressionLocation{ref, 0 }));
3226-
3227- #ifndef NDEBUG
3228- // We must not have anything in the reference that is invalid for the wasm
3229- // type there.
3230- auto maximalContents = PossibleContents::coneType (ref->type );
3231- assert (PossibleContents::isSubContents (refContents, maximalContents));
3232- #endif
3233-
3249+ void Flower::writeToData (Expression* ref, Expression* value, Index fieldIndex) {
32343250 // We could set up links here as we do for reads, but as we get to this code
32353251 // in any case, we can just flow the values forward directly. This avoids
32363252 // adding any links (edges) to the graph (and edges are what we want to avoid
@@ -3253,6 +3269,24 @@ void Flower::writeToData(Expression* ref,
32533269 // reference and value.)
32543270
32553271 auto valueContents = getContents (getIndex (ExpressionLocation{value, 0 }));
3272+ writeToData (ref, valueContents, fieldIndex);
3273+ }
3274+
3275+ void Flower::writeToData (Expression* ref,
3276+ const PossibleContents& valueContents,
3277+ Index fieldIndex) {
3278+ #if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
3279+ std::cout << " add special writes\n " ;
3280+ #endif
3281+
3282+ auto refContents = getContents (getIndex (ExpressionLocation{ref, 0 }));
3283+
3284+ #ifndef NDEBUG
3285+ // We must not have anything in the reference that is invalid for the wasm
3286+ // type there.
3287+ auto maximalContents = PossibleContents::coneType (ref->type );
3288+ assert (PossibleContents::isSubContents (refContents, maximalContents));
3289+ #endif
32563290
32573291 // See the related comment in readFromData() as to why these are the only
32583292 // things we need to check, and why the assertion afterwards contains the only
@@ -3265,9 +3299,6 @@ void Flower::writeToData(Expression* ref,
32653299 // As in readFromData, normalize to the proper cone.
32663300 auto cone = refContents.getCone ();
32673301 auto normalizedDepth = getNormalizedConeDepth (cone.type , cone.depth );
3268- if (multibyte) {
3269- valueContents = PossibleContents::fromType (value->type );
3270- }
32713302
32723303 subTypes->iterSubTypes (
32733304 cone.type .getHeapType (), normalizedDepth, [&](HeapType type, Index depth) {
0 commit comments