diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 1d42c11aeaf..f1ec4ba8bf8 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -502,6 +502,7 @@ class TranslateToFuzzReader { Expression* makeRefEq(Type type); Expression* makeRefTest(Type type); Expression* makeRefCast(Type type); + Expression* makeRefGetDesc(Type type); Expression* makeBrOn(Type type); // Decide to emit a signed Struct/ArrayGet sometimes, when the field is @@ -545,7 +546,6 @@ class TranslateToFuzzReader { Nullability getSuperType(Nullability nullability); HeapType getSuperType(HeapType type); Type getSuperType(Type type); - HeapType getArrayTypeForString(); // Utilities Name getTargetName(Expression* target); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 30ea252a372..ff88772e906 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -2112,8 +2112,10 @@ Expression* TranslateToFuzzReader::make(Type type) { ret = _makeunreachable(); } if (!Type::isSubType(ret->type, type)) { - Fatal() << "Did not generate the right subtype of " << type - << ", instead we have " << ret->type << " : " << *ret << '\n'; + Fatal() << "Did not generate the right subtype of " + << ModuleType(wasm, type) << ", instead we have " + << ModuleType(wasm, ret->type) << " : " + << ModuleExpression(wasm, ret) << '\n'; } nesting--; return ret; @@ -2204,6 +2206,10 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) { options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeRefCast); } + if (heapType.getDescribedType()) { + options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, + &Self::makeRefGetDesc); + } } if (wasm.features.hasGC()) { if (typeStructFields.find(type) != typeStructFields.end()) { @@ -4881,7 +4887,33 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { // This unreachable avoids a warning on refType being possibly undefined. WASM_UNREACHABLE("bad case"); } - return builder.makeRefCast(make(refType), type); + auto* ref = make(refType); + + // Emit a non-descriptor cast if we have to, or otherwise half the time. + auto desc = type.getHeapType().getDescriptorType(); + if (!desc || oneIn(2)) { + return builder.makeRefCast(ref, type); + } + + // Emit a descriptor for a descriptor cast. + auto* descRef = make(type.with(*desc)); + auto* ret = builder.makeRefCast(ref, descRef, type); + // descRef may be a subtype of the type we asked make() for, and if so then + // it might have a different described type - perhaps even an unrelated one, + // if the descriptors subtype but not the describees. Use an exact type to + // fix that up. + if (!Type::isSubType(ret->type, type)) { + descRef = make(type.with(*desc).with(Exact)); + ret = builder.makeRefCast(ref, descRef, type); + } + return ret; +} + +Expression* TranslateToFuzzReader::makeRefGetDesc(Type type) { + auto described = type.getHeapType().getDescribedType(); + assert(described); + auto refType = type.with(*described); + return builder.makeRefGetDesc(make(refType)); } Expression* TranslateToFuzzReader::makeBrOn(Type type) { diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index cd68e0b3c06..8364f537c19 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1075,7 +1075,7 @@ void RefCast::finalize() { return; } // The cast heap type and exactness is determined by the descriptor's type. - // Its nullability can be improved if the input valus is non-nullable. + // Its nullability can be improved if the input value is non-nullable. auto heapType = desc->type.getHeapType().getDescribedType(); assert(heapType); auto exactness = desc->type.getExactness();