From 05b14c00a36a79444c0304539125f4e88a72a72a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Sep 2025 16:23:03 -0700 Subject: [PATCH 1/8] go --- src/tools/fuzzing.h | 8 +++++++- src/tools/fuzzing/fuzzing.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 1d42c11aeaf..4475a2a075c 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -214,6 +214,9 @@ class TranslateToFuzzReader { // All tags that are valid as exception tags (which cannot have results). std::vector exceptionTags; + // All types that have a descriptor. + std::vector describedTypes; + Index numAddedFunctions = 0; // The name of an empty tag. @@ -502,6 +505,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 +549,9 @@ class TranslateToFuzzReader { Nullability getSuperType(Nullability nullability); HeapType getSuperType(HeapType type); Type getSuperType(Type type); - HeapType getArrayTypeForString(); + + // Given a HeapType, get a Type that uses it. + Type getType(HeapType heapType); // Utilities Name getTargetName(Expression* target); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 30ea252a372..e1bdf83140e 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -525,13 +525,16 @@ void TranslateToFuzzReader::setupHeapTypes() { } } - // Compute struct and array fields. + // Compute struct and array fields and other data. for (auto type : interestingHeapTypes) { if (type.isStruct()) { auto& fields = type.getStruct().fields; for (Index i = 0; i < fields.size(); i++) { typeStructFields[fields[i].type].push_back(StructField{type, i}); } + if (type.getDescriptorType()) { + describedTypes.push_back(type); + } } else if (type.isArray()) { typeArrays[type.getArray().element.type].push_back(type); } @@ -2204,6 +2207,10 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) { options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeRefCast); } + if (!describedTypes.empty()) { + options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, + &Self::makeRefGetDesc); + } } if (wasm.features.hasGC()) { if (typeStructFields.find(type) != typeStructFields.end()) { @@ -4881,7 +4888,16 @@ 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); + Expression* descRef = nullptr; + if (auto desc = refType.getHeapType().getDescriptorType()) { + descRef = make(Type(*desc, getNullability(), refType.getExactness())); + } + return builder.makeRefCast(make(refType), descRef, type); +} + +Expression* TranslateToFuzzReader::makeRefGetDesc(Type type) { + auto refType = pick(describedTypes); + return builder.makeRefGetDesc(make(getType(refType))); } Expression* TranslateToFuzzReader::makeBrOn(Type type) { @@ -5656,6 +5672,10 @@ Type TranslateToFuzzReader::getSuperType(Type type) { return superType; } +Type TranslateToFuzzReader::getType(HeapType heapType) { + return Type(heapType, getNullability(), getExactness()); +} + Name TranslateToFuzzReader::getTargetName(Expression* target) { if (auto* block = target->dynCast()) { return block->name; From b2ecebdd28a2fe851e3bd559aca0701e9384a1dd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Sep 2025 16:32:42 -0700 Subject: [PATCH 2/8] fix --- src/tools/fuzzing.h | 3 --- src/tools/fuzzing/fuzzing.cpp | 13 ++++++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 4475a2a075c..ab7d6bd2e3d 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -214,9 +214,6 @@ class TranslateToFuzzReader { // All tags that are valid as exception tags (which cannot have results). std::vector exceptionTags; - // All types that have a descriptor. - std::vector describedTypes; - Index numAddedFunctions = 0; // The name of an empty tag. diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index e1bdf83140e..f614fb53aeb 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -525,16 +525,13 @@ void TranslateToFuzzReader::setupHeapTypes() { } } - // Compute struct and array fields and other data. + // Compute struct and array fields. for (auto type : interestingHeapTypes) { if (type.isStruct()) { auto& fields = type.getStruct().fields; for (Index i = 0; i < fields.size(); i++) { typeStructFields[fields[i].type].push_back(StructField{type, i}); } - if (type.getDescriptorType()) { - describedTypes.push_back(type); - } } else if (type.isArray()) { typeArrays[type.getArray().element.type].push_back(type); } @@ -2207,7 +2204,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) { options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeRefCast); } - if (!describedTypes.empty()) { + if (heapType.getDescribedType()) { options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeRefGetDesc); } @@ -4896,8 +4893,10 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { } Expression* TranslateToFuzzReader::makeRefGetDesc(Type type) { - auto refType = pick(describedTypes); - return builder.makeRefGetDesc(make(getType(refType))); + auto described = type.getHeapType().getDescribedType(); + assert(described); + auto refType = getType(*described); + return builder.makeRefGetDesc(make(refType)); } Expression* TranslateToFuzzReader::makeBrOn(Type type) { From 15eef4ac6247951923c4734a37ba34072365dd85 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Sep 2025 13:05:14 -0700 Subject: [PATCH 3/8] fix --- src/tools/fuzzing/fuzzing.cpp | 12 ++++++++---- src/wasm/wasm.cpp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index f614fb53aeb..17fe53a48c7 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -2112,8 +2112,8 @@ 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; @@ -4885,8 +4885,12 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { // This unreachable avoids a warning on refType being possibly undefined. WASM_UNREACHABLE("bad case"); } + // Descriptor casts emit a type that depends on the descriptor, so we can only + // create one if that type would fit |type| which is what we must emit at the + // end. Expression* descRef = nullptr; - if (auto desc = refType.getHeapType().getDescriptorType()) { + if (auto desc = refType.getHeapType().getDescriptorType(); + desc && Type::isSubType(refType, type)) { descRef = make(Type(*desc, getNullability(), refType.getExactness())); } return builder.makeRefCast(make(refType), descRef, type); @@ -4895,7 +4899,7 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { Expression* TranslateToFuzzReader::makeRefGetDesc(Type type) { auto described = type.getHeapType().getDescribedType(); assert(described); - auto refType = getType(*described); + auto refType = type.with(*described); return builder.makeRefGetDesc(make(refType)); } 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(); From da987c9a00682951e12833e851c1f2e1df7c8839 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Sep 2025 13:05:20 -0700 Subject: [PATCH 4/8] format --- src/tools/fuzzing/fuzzing.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 17fe53a48c7..ae3509b9cd2 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 " << ModuleType(wasm, type) - << ", instead we have " << ModuleType(wasm, ret->type) << " : " << ModuleExpression(wasm, 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; From bf1ca4b5374c4a78efad3e698b19d8a38d16a161 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Sep 2025 13:09:04 -0700 Subject: [PATCH 5/8] clean --- src/tools/fuzzing.h | 3 --- src/tools/fuzzing/fuzzing.cpp | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index ab7d6bd2e3d..f1ec4ba8bf8 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -547,9 +547,6 @@ class TranslateToFuzzReader { HeapType getSuperType(HeapType type); Type getSuperType(Type type); - // Given a HeapType, get a Type that uses it. - Type getType(HeapType heapType); - // Utilities Name getTargetName(Expression* target); Type getTargetType(Expression* target); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index ae3509b9cd2..0dc05098e79 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -5677,10 +5677,6 @@ Type TranslateToFuzzReader::getSuperType(Type type) { return superType; } -Type TranslateToFuzzReader::getType(HeapType heapType) { - return Type(heapType, getNullability(), getExactness()); -} - Name TranslateToFuzzReader::getTargetName(Expression* target) { if (auto* block = target->dynCast()) { return block->name; From 0d5bcf0ed96d2560b8c8b9f556cb5d8ca550017a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Sep 2025 14:06:54 -0700 Subject: [PATCH 6/8] fix --- src/tools/fuzzing/fuzzing.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 0dc05098e79..ad7e7680eac 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -4893,7 +4893,14 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { Expression* descRef = nullptr; if (auto desc = refType.getHeapType().getDescriptorType(); desc && Type::isSubType(refType, type)) { - descRef = make(Type(*desc, getNullability(), refType.getExactness())); + descRef = make(refType.with(*desc)); + // 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(descRef->type, type)) { + descRef = make(refType.with(*desc).with(Exact)); + } } return builder.makeRefCast(make(refType), descRef, type); } From de2611f88bd3166eb9479d3716a4ba5ff50bdb78 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Sep 2025 18:36:54 -0700 Subject: [PATCH 7/8] feedback --- src/tools/fuzzing/fuzzing.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index ad7e7680eac..dcab7af3f6b 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -4891,15 +4891,15 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { // create one if that type would fit |type| which is what we must emit at the // end. Expression* descRef = nullptr; - if (auto desc = refType.getHeapType().getDescriptorType(); - desc && Type::isSubType(refType, type)) { - descRef = make(refType.with(*desc)); + if (auto desc = type.getHeapType().getDescriptorType()) { + descRef = make(type.with(*desc)); // 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(descRef->type, type)) { - descRef = make(refType.with(*desc).with(Exact)); + if (!HeapType::isSubType(*descRef->type.getHeapType().getDescribedType(), + type.getHeapType())) { + descRef = make(type.with(*desc).with(Exact)); } } return builder.makeRefCast(make(refType), descRef, type); From c2e2a8bf2ec63ebf595c76ccfb5d7eb2f4fa558a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 23 Sep 2025 09:21:02 -0700 Subject: [PATCH 8/8] fix --- src/tools/fuzzing/fuzzing.cpp | 36 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index dcab7af3f6b..ff88772e906 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -4887,22 +4887,26 @@ Expression* TranslateToFuzzReader::makeRefCast(Type type) { // This unreachable avoids a warning on refType being possibly undefined. WASM_UNREACHABLE("bad case"); } - // Descriptor casts emit a type that depends on the descriptor, so we can only - // create one if that type would fit |type| which is what we must emit at the - // end. - Expression* descRef = nullptr; - if (auto desc = type.getHeapType().getDescriptorType()) { - descRef = make(type.with(*desc)); - // 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 (!HeapType::isSubType(*descRef->type.getHeapType().getDescribedType(), - type.getHeapType())) { - descRef = make(type.with(*desc).with(Exact)); - } - } - return builder.makeRefCast(make(refType), descRef, 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) {