@@ -2598,6 +2598,12 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
25982598 if (typeStructFields.find (type) != typeStructFields.end ()) {
25992599 options.add (FeatureSet::ReferenceTypes | FeatureSet::GC,
26002600 &Self::makeStructGet);
2601+ options.add (FeatureSet::ReferenceTypes | FeatureSet::GC |
2602+ FeatureSet::Atomics | FeatureSet::SharedEverything,
2603+ &Self::makeStructRMW);
2604+ options.add (FeatureSet::ReferenceTypes | FeatureSet::GC |
2605+ FeatureSet::Atomics | FeatureSet::SharedEverything,
2606+ &Self::makeStructCmpxchg);
26012607 }
26022608 if (typeArrays.find (type) != typeArrays.end ()) {
26032609 options.add (FeatureSet::ReferenceTypes | FeatureSet::GC,
@@ -5583,8 +5589,66 @@ Expression* TranslateToFuzzReader::makeStructGet(Type type) {
55835589 auto [structType, fieldIndex] = pick (structFields);
55845590 auto * ref = makeTrappingRefUse (structType);
55855591 auto signed_ = maybeSignedGet (structType.getStruct ().fields [fieldIndex]);
5586- return builder.makeStructGet (
5587- fieldIndex, ref, MemoryOrder::Unordered, type, signed_);
5592+ auto order = MemoryOrder::Unordered;
5593+ if (wasm.features .hasAtomics () && wasm.features .hasSharedEverything () &&
5594+ oneIn (2 )) {
5595+ order = oneIn (2 ) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
5596+ }
5597+ return builder.makeStructGet (fieldIndex, ref, order, type, signed_);
5598+ }
5599+
5600+ Expression* TranslateToFuzzReader::makeStructRMW (Type type) {
5601+ bool isAny =
5602+ type.isRef () &&
5603+ Type::isSubType (
5604+ type,
5605+ Type (HeapTypes::any.getBasic (type.getHeapType ().getShared ()), Nullable));
5606+ if (type != Type::i32 && type != Type::i64 && !isAny) {
5607+ // Not a valid field type for an RMW operation.
5608+ return makeStructGet (type);
5609+ }
5610+ auto & structFields = typeStructFields[type];
5611+ assert (!structFields.empty ());
5612+ auto [structType, fieldIndex] = pick (structFields);
5613+ const auto & field = structType.getStruct ().fields [fieldIndex];
5614+ if (field.isPacked () || field.mutable_ == Immutable) {
5615+ // Cannot RMW a packed or immutable field.
5616+ return makeStructGet (type);
5617+ }
5618+ AtomicRMWOp op = RMWXchg;
5619+ if (type == Type::i32 || type == Type::i64 ) {
5620+ op = pick (RMWAdd, RMWSub, RMWAnd, RMWOr, RMWXor, RMWXchg);
5621+ }
5622+ auto * ref = makeTrappingRefUse (structType);
5623+ auto * value = make (type);
5624+ auto order = oneIn (2 ) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
5625+ return builder.makeStructRMW (op, fieldIndex, ref, value, order);
5626+ }
5627+
5628+ Expression* TranslateToFuzzReader::makeStructCmpxchg (Type type) {
5629+ bool isEq =
5630+ type.isRef () &&
5631+ Type::isSubType (
5632+ type,
5633+ Type (HeapTypes::eq.getBasic (type.getHeapType ().getShared ()), Nullable));
5634+ if (type != Type::i32 && type != Type::i64 && !isEq) {
5635+ // Not a valid field type for a cmpxchg operation.
5636+ return makeStructGet (type);
5637+ }
5638+ auto & structFields = typeStructFields[type];
5639+ assert (!structFields.empty ());
5640+ auto [structType, fieldIndex] = pick (structFields);
5641+ const auto & field = structType.getStruct ().fields [fieldIndex];
5642+ if (field.isPacked () || field.mutable_ == Immutable) {
5643+ // Cannot RMW a packed or immutable field.
5644+ return makeStructGet (type);
5645+ }
5646+ auto * ref = makeTrappingRefUse (structType);
5647+ auto * expected = make (type);
5648+ auto * replacement = make (type);
5649+ auto order = oneIn (2 ) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
5650+ return builder.makeStructCmpxchg (
5651+ fieldIndex, ref, expected, replacement, order);
55885652}
55895653
55905654Expression* TranslateToFuzzReader::makeStructSet (Type type) {
@@ -5596,7 +5660,12 @@ Expression* TranslateToFuzzReader::makeStructSet(Type type) {
55965660 auto fieldType = structType.getStruct ().fields [fieldIndex].type ;
55975661 auto * ref = makeTrappingRefUse (structType);
55985662 auto * value = make (fieldType);
5599- return builder.makeStructSet (fieldIndex, ref, value, MemoryOrder::Unordered);
5663+ auto order = MemoryOrder::Unordered;
5664+ if (wasm.features .hasAtomics () && wasm.features .hasSharedEverything () &&
5665+ oneIn (2 )) {
5666+ order = oneIn (2 ) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
5667+ }
5668+ return builder.makeStructSet (fieldIndex, ref, value, order);
56005669}
56015670
56025671// Make a bounds check for an array operation, given a ref + index. An optional
0 commit comments