diff options
-rw-r--r-- | src/binaryen-c.cpp | 13 | ||||
-rw-r--r-- | src/binaryen-c.h | 12 | ||||
-rw-r--r-- | src/tools/fuzzing/heap-types.cpp | 81 | ||||
-rw-r--r-- | src/tools/wasm-fuzz-types.cpp | 58 | ||||
-rw-r--r-- | src/wasm-type.h | 15 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 130 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.c | 37 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.txt | 3 | ||||
-rw-r--r-- | test/example/type-builder.cpp | 233 | ||||
-rw-r--r-- | test/example/type-builder.txt | 54 | ||||
-rw-r--r-- | test/gtest/type-builder.cpp | 22 | ||||
-rw-r--r-- | test/lit/fuzz-types.test | 82 | ||||
-rw-r--r-- | test/passes/translate-to-fuzz_all-features_metrics_noprint.txt | 76 |
13 files changed, 125 insertions, 691 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index b23d53ad6..03132b23a 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -6321,12 +6321,6 @@ void TypeBuilderGrow(TypeBuilderRef builder, BinaryenIndex count) { BinaryenIndex TypeBuilderGetSize(TypeBuilderRef builder) { return ((TypeBuilder*)builder)->size(); } -void TypeBuilderSetBasicHeapType(TypeBuilderRef builder, - BinaryenIndex index, - BinaryenBasicHeapType basicHeapType) { - ((TypeBuilder*)builder) - ->setHeapType(index, HeapType::BasicHeapType(basicHeapType)); -} void TypeBuilderSetSignatureType(TypeBuilderRef builder, BinaryenIndex index, BinaryenType paramTypes, @@ -6370,13 +6364,6 @@ void TypeBuilderSetArrayType(TypeBuilderRef builder, } B->setHeapType(index, Array(element)); } -bool TypeBuilderIsBasic(TypeBuilderRef builder, BinaryenIndex index) { - return ((TypeBuilder*)builder)->isBasic(index); -} -BinaryenBasicHeapType TypeBuilderGetBasic(TypeBuilderRef builder, - BinaryenIndex index) { - return BinaryenBasicHeapType(((TypeBuilder*)builder)->getBasic(index)); -} BinaryenHeapType TypeBuilderGetTempHeapType(TypeBuilderRef builder, BinaryenIndex index) { return ((TypeBuilder*)builder)->getTempHeapType(index).getID(); diff --git a/src/binaryen-c.h b/src/binaryen-c.h index d05bdf33b..a199561f0 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -3525,12 +3525,6 @@ BINARYEN_API TypeBuilderRef TypeBuilderCreate(BinaryenIndex size); BINARYEN_API void TypeBuilderGrow(TypeBuilderRef builder, BinaryenIndex count); // Gets the size of the backing table of the type builder. BINARYEN_API BinaryenIndex TypeBuilderGetSize(TypeBuilderRef builder); -// Sets the heap type at index `index` to a basic heap type. Must not be used in -// nominal mode. -BINARYEN_API void -TypeBuilderSetBasicHeapType(TypeBuilderRef builder, - BinaryenIndex index, - BinaryenBasicHeapType basicHeapType); // Sets the heap type at index `index` to a concrete signature type. Expects // temporary tuple types if multiple parameter and/or result types include // temporary types. @@ -3551,12 +3545,6 @@ BINARYEN_API void TypeBuilderSetArrayType(TypeBuilderRef builder, BinaryenType elementType, BinaryenPackedType elementPackedType, int elementMutable); -// Tests if the heap type at index `index` is a basic heap type. -BINARYEN_API bool TypeBuilderIsBasic(TypeBuilderRef builder, - BinaryenIndex index); -// Gets the basic heap type at index `index`. -BINARYEN_API BinaryenBasicHeapType TypeBuilderGetBasic(TypeBuilderRef builder, - BinaryenIndex index); // Gets the temporary heap type to use at index `index`. Temporary heap types // may only be used to construct temporary types using the type builder. BINARYEN_API BinaryenHeapType TypeBuilderGetTempHeapType(TypeBuilderRef builder, diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index e58c7f51d..26cc518be 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -40,12 +40,10 @@ struct HeapTypeGeneratorImpl { // Top-level kinds, chosen before the types are actually constructed. This // allows us to choose HeapTypes that we know will be subtypes of data or func // before we actually generate the types. - using BasicKind = HeapType::BasicHeapType; struct SignatureKind {}; struct StructKind {}; struct ArrayKind {}; - using HeapTypeKind = - std::variant<BasicKind, SignatureKind, StructKind, ArrayKind>; + using HeapTypeKind = std::variant<SignatureKind, StructKind, ArrayKind>; std::vector<HeapTypeKind> typeKinds; // For each type, the index one past the end of its recursion group, used to @@ -83,7 +81,7 @@ struct HeapTypeGeneratorImpl { builder[i].subTypeOf(builder[super]); supertypeIndices[i] = super; subtypeIndices[super].push_back(i); - typeKinds.push_back(getSubKind(typeKinds[super])); + typeKinds.push_back(typeKinds[super]); } } @@ -110,11 +108,7 @@ struct HeapTypeGeneratorImpl { // Create the heap types. for (; index < builder.size(); ++index) { auto kind = typeKinds[index]; - if (auto* basic = std::get_if<BasicKind>(&kind)) { - // The type is already determined. - builder[index] = *basic; - } else if (!supertypeIndices[index] || - builder.isBasic(*supertypeIndices[index])) { + if (!supertypeIndices[index]) { // No nontrivial supertype, so create a root type. if (std::get_if<SignatureKind>(&kind)) { builder[index] = generateSignature(); @@ -365,9 +359,7 @@ struct HeapTypeGeneratorImpl { // the builder. if (rand.oneIn(candidates.size() * 8)) { auto* kind = &typeKinds[it->second]; - if (auto* basic = std::get_if<BasicKind>(kind)) { - return HeapType(*basic).getBottom(); - } else if (std::get_if<SignatureKind>(kind)) { + if (std::get_if<SignatureKind>(kind)) { return HeapType::nofunc; } else { return HeapType::none; @@ -434,9 +426,7 @@ struct HeapTypeGeneratorImpl { candidates.push_back(HeapType::func); return rand.pick(candidates); } else { - // A constructed basic type. Fall through to add all of the basic - // supertypes as well. - type = *std::get_if<BasicKind>(kind); + WASM_UNREACHABLE("unexpected kind"); } } // This is not a constructed type, so it must be a basic type. @@ -576,70 +566,9 @@ struct HeapTypeGeneratorImpl { return StructKind{}; case 2: return ArrayKind{}; - case 3: - return BasicKind{generateBasicHeapType()}; } WASM_UNREACHABLE("unexpected index"); } - - HeapTypeKind getSubKind(HeapTypeKind super) { - if (rand.oneIn(16)) { - // Occasionally go directly to the bottom type. - if (auto* basic = std::get_if<BasicKind>(&super)) { - return HeapType(*basic).getBottom(); - } else if (std::get_if<SignatureKind>(&super)) { - return HeapType::nofunc; - } else if (std::get_if<StructKind>(&super)) { - return HeapType::none; - } else if (std::get_if<ArrayKind>(&super)) { - return HeapType::none; - } - WASM_UNREACHABLE("unexpected kind"); - } - if (auto* basic = std::get_if<BasicKind>(&super)) { - if (rand.oneIn(8)) { - return super; - } - switch (*basic) { - case HeapType::func: - return SignatureKind{}; - case HeapType::ext: - case HeapType::i31: - return super; - case HeapType::any: - if (rand.oneIn(5)) { - return HeapType::eq; - } - [[fallthrough]]; - case HeapType::eq: - switch (rand.upTo(3)) { - case 0: - return HeapType::i31; - case 1: - return StructKind{}; - case 2: - return ArrayKind{}; - } - WASM_UNREACHABLE("unexpected index"); - case HeapType::struct_: - return StructKind{}; - case HeapType::array: - return ArrayKind{}; - case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: - case HeapType::none: - case HeapType::noext: - case HeapType::nofunc: - return super; - } - WASM_UNREACHABLE("unexpected kind"); - } else { - // Signature and Data types can only have Signature and Data subtypes. - return super; - } - } }; } // anonymous namespace diff --git a/src/tools/wasm-fuzz-types.cpp b/src/tools/wasm-fuzz-types.cpp index 0dc9f9d17..4f480ba9d 100644 --- a/src/tools/wasm-fuzz-types.cpp +++ b/src/tools/wasm-fuzz-types.cpp @@ -104,7 +104,7 @@ void Fuzzer::printTypes(const std::vector<HeapType>& types) { auto inRecGroup = [&]() { return currRecGroup && currRecGroup->size() > 1; }; for (size_t i = 0; i < types.size(); ++i) { auto type = types[i]; - if (!type.isBasic() && type.getRecGroup() != currRecGroup) { + if (type.getRecGroup() != currRecGroup) { if (inRecGroup()) { std::cout << ")\n"; } @@ -116,10 +116,6 @@ void Fuzzer::printTypes(const std::vector<HeapType>& types) { if (inRecGroup()) { std::cout << ' '; } - if (type.isBasic()) { - std::cout << "(type $" << i << ' ' << print(type) << ")\n"; - continue; - } auto [it, inserted] = seen.insert({type, i}); if (inserted) { std::cout << print(type); @@ -280,13 +276,9 @@ void Fuzzer::checkCanonicalization() { currGroupStart = end; }; for (Index i = 0; i < types.size(); ++i) { - auto type = types[i]; - if (type.isBasic()) { - continue; - } - auto newGroup = type.getRecGroup(); + auto newGroup = types[i].getRecGroup(); if (!currGroup || newGroup != currGroup || - type == types[currGroupStart]) { + types[i] == types[currGroupStart]) { finishGroup(i); currGroup = newGroup; } @@ -296,9 +288,7 @@ void Fuzzer::checkCanonicalization() { // Copy the original types for (; index < types.size(); ++index) { auto type = types[index]; - if (type.isBasic()) { - builder[index] = type.getBasic(); - } else if (type.isSignature()) { + if (type.isSignature()) { builder[index] = getSignature(type.getSignature()); } else if (type.isStruct()) { builder[index] = getStruct(type.getStruct()); @@ -333,28 +323,27 @@ void Fuzzer::checkCanonicalization() { CopiedHeapType getChildHeapType(HeapType old) { auto it = typeIndices.find(old); if (it == typeIndices.end()) { - // This is a basic heap type that wasn't explicitly built. + // This is a basic heap type and wasn't explicitly built. assert(old.isBasic()); return {OldHeapType{old}}; } - if (!old.isBasic()) { - // Check whether this child heap type is supposed to be a self-reference - // into the recursion group we are defining. If it is, we must use the - // corresponding type in the new recursion group, since anything else - // would break isorecursive equivalence. - auto group = old.getRecGroup(); - if (group == types[index].getRecGroup()) { - // This is a self-reference, so find the correct index, which is the - // last matching index less than the end of this rec group. - std::optional<Index> i; - for (auto candidate : it->second) { - if (candidate >= recGroupEnds[index]) { - break; - } - i = candidate; + assert(!old.isBasic()); + // Check whether this child heap type is supposed to be a self-reference + // into the recursion group we are defining. If it is, we must use the + // corresponding type in the new recursion group, since anything else + // would break isorecursive equivalence. + auto group = old.getRecGroup(); + if (group == types[index].getRecGroup()) { + // This is a self-reference, so find the correct index, which is the + // last matching index less than the end of this rec group. + std::optional<Index> i; + for (auto candidate : it->second) { + if (candidate >= recGroupEnds[index]) { + break; } - return {NewHeapType{builder[*i]}}; + i = candidate; } + return {NewHeapType{builder[*i]}}; } // Choose whether to use an old type or a new type if (rand.oneIn(2)) { @@ -366,12 +355,7 @@ void Fuzzer::checkCanonicalization() { candidateIndices.push_back(i); } } - if (candidateIndices.empty()) { - // This is a basic type that was only ever created after the current - // rec group, so we can't refer to a new copy of it after all. - assert(old.isBasic()); - return {OldHeapType{old}}; - } + assert(!candidateIndices.empty()); Index i = rand.pick(candidateIndices); return {NewHeapType{builder[i]}}; } else { diff --git a/src/wasm-type.h b/src/wasm-type.h index ad0606d59..551096fb5 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -579,21 +579,12 @@ struct TypeBuilder { // The number of HeapType slots in the TypeBuilder. size_t size(); - // Sets the heap type at index `i`. May only be called before `build`. The - // BasicHeapType overload may not be used in nominal mode. - void setHeapType(size_t i, HeapType::BasicHeapType basic); + // Sets the heap type at index `i`. May only be called before `build`. void setHeapType(size_t i, Signature signature); void setHeapType(size_t i, const Struct& struct_); void setHeapType(size_t i, Struct&& struct_); void setHeapType(size_t i, Array array); - // This is an ugly hack around the fact that temp heap types initialized with - // BasicHeapTypes are not themselves considered basic, so `HeapType::isBasic` - // and `HeapType::getBasic` do not work as expected with them. Call these - // methods instead. - bool isBasic(size_t i); - HeapType::BasicHeapType getBasic(size_t i); - // Gets the temporary HeapType at index `i`. This HeapType should only be used // to construct temporary Types using the methods below. HeapType getTempHeapType(size_t i); @@ -653,10 +644,6 @@ struct TypeBuilder { TypeBuilder& builder; size_t index; operator HeapType() const { return builder.getTempHeapType(index); } - Entry& operator=(HeapType::BasicHeapType basic) { - builder.setHeapType(index, basic); - return *this; - } Entry& operator=(Signature signature) { builder.setHeapType(index, signature); return *this; diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index c9c35ac49..f697ba5a3 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -77,9 +77,8 @@ struct TypeInfo { bool isNullable() const { return kind == RefKind && ref.nullable; } // If this TypeInfo represents a Type that can be represented more simply, - // return that simpler Type. For example, this handles canonicalizing the - // TypeInfo representing (ref null any) into the BasicType anyref. It also - // handles eliminating singleton tuple types. + // return that simpler Type. For example, this handles eliminating singleton + // tuple types. std::optional<Type> getCanonical() const; bool operator==(const TypeInfo& other) const; @@ -105,7 +104,6 @@ struct HeapTypeInfo { RecGroupInfo* recGroup = nullptr; size_t recGroupIndex = 0; enum Kind { - BasicKind, SignatureKind, StructKind, ArrayKind, @@ -117,7 +115,6 @@ struct HeapTypeInfo { Array array; }; - HeapTypeInfo(HeapType::BasicHeapType basic) : kind(BasicKind), basic(basic) {} HeapTypeInfo(Signature sig) : kind(SignatureKind), signature(sig) {} HeapTypeInfo(const Struct& struct_) : kind(StructKind), struct_(struct_) {} HeapTypeInfo(Struct&& struct_) @@ -131,11 +128,6 @@ struct HeapTypeInfo { constexpr bool isArray() const { return kind == ArrayKind; } constexpr bool isData() const { return isStruct() || isArray(); } - // If this HeapTypeInfo represents a HeapType that can be represented more - // simply, return that simpler HeapType. This handles turning BasicKind - // HeapTypes into their corresponding BasicHeapTypes. - std::optional<HeapType> getCanonical() const; - HeapTypeInfo& operator=(const HeapTypeInfo& other); bool operator==(const HeapTypeInfo& other) const; bool operator!=(const HeapTypeInfo& other) const { return !(*this == other); } @@ -455,27 +447,12 @@ bool isTemp(HeapType type) { return !type.isBasic() && getHeapTypeInfo(type)->isTemp; } -// Given a Type that may or may not be backed by the simplest possible -// representation, return the equivalent type that is definitely backed by the -// simplest possible representation. -Type asCanonical(Type type) { - if (type.isBasic()) { - return type; - } else if (auto canon = getTypeInfo(type)->getCanonical()) { - return *canon; - } else { - return type; - } -} - HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { if (type.isBasic()) { return type.getBasic(); } auto* info = getHeapTypeInfo(type); switch (info->kind) { - case HeapTypeInfo::BasicKind: - break; case HeapTypeInfo::SignatureKind: return HeapType::func; case HeapTypeInfo::StructKind: @@ -597,9 +574,6 @@ HeapTypeInfo::HeapTypeInfo(const HeapTypeInfo& other) { supertype = other.supertype; recGroup = other.recGroup; switch (kind) { - case BasicKind: - new (&basic) auto(other.basic); - return; case SignatureKind: new (&signature) auto(other.signature); return; @@ -615,8 +589,6 @@ HeapTypeInfo::HeapTypeInfo(const HeapTypeInfo& other) { HeapTypeInfo::~HeapTypeInfo() { switch (kind) { - case BasicKind: - return; case SignatureKind: signature.~Signature(); return; @@ -630,13 +602,6 @@ HeapTypeInfo::~HeapTypeInfo() { WASM_UNREACHABLE("unexpected kind"); } -std::optional<HeapType> HeapTypeInfo::getCanonical() const { - if (isFinalized && kind == BasicKind) { - return basic; - } - return {}; -} - HeapTypeInfo& HeapTypeInfo::operator=(const HeapTypeInfo& other) { if (&other != this) { this->~HeapTypeInfo(); @@ -702,9 +667,11 @@ private: return typename Info::type_t(id); }; - // Turn e.g. (ref null any) into anyref. - if (auto canonical = info.getCanonical()) { - return *canonical; + // Turn e.g. singleton tuple into non-tuple. + if constexpr (std::is_same_v<Info, TypeInfo>) { + if (auto canonical = info.getCanonical()) { + return *canonical; + } } std::lock_guard<std::recursive_mutex> lock(mutex); // Check whether we already have a type for this structural Info. @@ -1376,8 +1343,6 @@ HeapType::BasicHeapType HeapType::getBottom() const { } auto* info = getHeapTypeInfo(*this); switch (info->kind) { - case HeapTypeInfo::BasicKind: - return HeapType(info->basic).getBottom(); case HeapTypeInfo::SignatureKind: return nofunc; case HeapTypeInfo::StructKind: @@ -1861,10 +1826,7 @@ std::ostream& TypePrinter::print(HeapType type) { #if TRACE_CANONICALIZATION os << "(;" << ((type.getID() >> 4) % 1000) << ";)"; #endif - if (getHeapTypeInfo(type)->kind == HeapTypeInfo::BasicKind) { - os << "(; noncanonical ;) "; - print(getHeapTypeInfo(type)->basic); - } else if (type.isSignature()) { + if (type.isSignature()) { print(type.getSignature(), type.getSuperType()); } else if (type.isStruct()) { print(type.getStruct(), type.getSuperType()); @@ -2045,8 +2007,6 @@ size_t RecGroupHasher::hash(const HeapTypeInfo& info) const { } wasm::rehash(digest, info.kind); switch (info.kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("Basic HeapTypeInfo should have been canonicalized"); case HeapTypeInfo::SignatureKind: hash_combine(digest, hash(info.signature)); return digest; @@ -2171,8 +2131,6 @@ bool RecGroupEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) const { return false; } switch (a.kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("Basic HeapTypeInfo should have been canonicalized"); case HeapTypeInfo::SignatureKind: return eq(a.signature, b.signature); case HeapTypeInfo::StructKind: @@ -2282,8 +2240,6 @@ void TypeGraphWalkerBase<Self>::scanHeapType(HeapType* ht) { } auto* info = getHeapTypeInfo(*ht); switch (info->kind) { - case HeapTypeInfo::BasicKind: - break; case HeapTypeInfo::SignatureKind: taskList.push_back(Task::scan(&info->signature.results)); taskList.push_back(Task::scan(&info->signature.params)); @@ -2355,11 +2311,6 @@ void TypeBuilder::grow(size_t n) { size_t TypeBuilder::size() { return impl->entries.size(); } -void TypeBuilder::setHeapType(size_t i, HeapType::BasicHeapType basic) { - assert(i < size() && "Index out of bounds"); - impl->entries[i].set(basic); -} - void TypeBuilder::setHeapType(size_t i, Signature signature) { assert(i < size() && "index out of bounds"); impl->entries[i].set(signature); @@ -2380,16 +2331,6 @@ void TypeBuilder::setHeapType(size_t i, Array array) { impl->entries[i].set(array); } -bool TypeBuilder::isBasic(size_t i) { - assert(i < size() && "index out of bounds"); - return impl->entries[i].info->kind == HeapTypeInfo::BasicKind; -} - -HeapType::BasicHeapType TypeBuilder::getBasic(size_t i) { - assert(isBasic(i)); - return impl->entries[i].info->basic; -} - HeapType TypeBuilder::getTempHeapType(size_t i) { assert(i < size() && "index out of bounds"); return impl->entries[i].get(); @@ -2469,8 +2410,6 @@ struct CanonicalizationState { // Updates the HeapType use sites within `info`. void updateUses(ReplacementMap& replacements, std::unique_ptr<HeapTypeInfo>& info); - // Updates lists and uses. - void update(ReplacementMap& replacements); #if TRACE_CANONICALIZATION void dump() { @@ -2488,16 +2427,6 @@ struct CanonicalizationState { #endif // TRACE_CANONICALIZATION }; -void CanonicalizationState::update(ReplacementMap& replacements) { - if (replacements.empty()) { - return; - } - updateShallow(replacements); - for (auto& info : newInfos) { - updateUses(replacements, info); - } -} - void CanonicalizationState::updateShallow(ReplacementMap& replacements) { if (replacements.empty()) { return; @@ -2670,8 +2599,6 @@ validateSubtyping(const std::vector<HeapType>& types) { } SubTyper typer; switch (sub->kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("unexpected kind"); case HeapTypeInfo::SignatureKind: if (!typer.isSubType(sub->signature, super->signature)) { return fail(); @@ -2803,43 +2730,6 @@ std::optional<TypeBuilder::Error> canonicalizeIsorecursive( return {}; } -void canonicalizeBasicTypes(CanonicalizationState& state) { - // Replace heap types backed by BasicKind HeapTypeInfos with their - // corresponding BasicHeapTypes. The heap types backed by BasicKind - // HeapTypeInfos exist only to support building basic types in a TypeBuilder - // and are never canonical. - CanonicalizationState::ReplacementMap replacements; - for (auto& info : state.newInfos) { - if (info->kind == HeapTypeInfo::BasicKind) { - replacements.insert({asHeapType(info), HeapType(info->basic)}); - } - // Basic supertypes should be implicit. - if (info->supertype && info->supertype->kind == HeapTypeInfo::BasicKind) { - info->supertype = nullptr; - } - } - state.update(replacements); - - if (replacements.size()) { - // Canonicalizing basic heap types may cause their parent types to become - // canonicalizable as well, for example after creating `(ref null any)` we - // can futher canonicalize to `anyref`. - struct TypeCanonicalizer : TypeGraphWalkerBase<TypeCanonicalizer> { - void scanType(Type* type) { - if (type->isTuple()) { - TypeGraphWalkerBase<TypeCanonicalizer>::scanType(type); - } else { - *type = asCanonical(*type); - } - } - }; - for (auto& info : state.newInfos) { - auto root = asHeapType(info); - TypeCanonicalizer{}.walkRoot(&root); - } - } -} - } // anonymous namespace TypeBuilder::BuildResult TypeBuilder::build() { @@ -2859,10 +2749,6 @@ TypeBuilder::BuildResult TypeBuilder::build() { state.newInfos.emplace_back(std::move(info)); } - // Eagerly replace references to built basic heap types so the more - // complicated canonicalization algorithms don't need to consider them. - canonicalizeBasicTypes(state); - #if TRACE_CANONICALIZATION std::cerr << "After replacing basic heap types:\n"; state.dump(); diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 760f4be1d..2c6ec2d6c 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -2134,8 +2134,8 @@ void test_typebuilder() { TypeBuilderRef builder = TypeBuilderCreate(0); assert(TypeBuilderGetSize(builder) == 0); - TypeBuilderGrow(builder, 5); - assert(TypeBuilderGetSize(builder) == 5); + TypeBuilderGrow(builder, 4); + assert(TypeBuilderGetSize(builder) == 4); // Create a recursive array of its own type const BinaryenIndex tempArrayIndex = 0; @@ -2179,19 +2179,8 @@ void test_typebuilder() { tempSignatureType); } - // Create a basic heap type - const BinaryenIndex tempBasicIndex = 3; - TypeBuilderSetBasicHeapType( - builder, 3, BinaryenTypeGetHeapType(BinaryenTypeEqref())); - assert(TypeBuilderIsBasic(builder, tempBasicIndex)); - assert(TypeBuilderGetBasic(builder, tempBasicIndex) == - BinaryenTypeGetHeapType(BinaryenTypeEqref())); - assert(!TypeBuilderIsBasic(builder, tempArrayIndex)); - assert(!TypeBuilderIsBasic(builder, tempStructIndex)); - assert(!TypeBuilderIsBasic(builder, tempSignatureIndex)); - // Create a subtype (with an additional immutable packed field) - const BinaryenIndex tempSubStructIndex = 4; + const BinaryenIndex tempSubStructIndex = 3; BinaryenHeapType tempSubStructHeapType = TypeBuilderGetTempHeapType(builder, tempSubStructIndex); BinaryenType tempSubStructType = @@ -2214,7 +2203,7 @@ void test_typebuilder() { // TODO: Rtts (post-MVP?) // Build the type hierarchy and dispose the builder - BinaryenHeapType heapTypes[5]; + BinaryenHeapType heapTypes[4]; BinaryenIndex errorIndex; TypeBuilderErrorReason errorReason; bool didBuildAndDispose = TypeBuilderBuildAndDispose( @@ -2222,7 +2211,6 @@ void test_typebuilder() { assert(didBuildAndDispose); BinaryenHeapType arrayHeapType = heapTypes[tempArrayIndex]; - assert(!BinaryenHeapTypeIsBasic(arrayHeapType)); assert(!BinaryenHeapTypeIsSignature(arrayHeapType)); assert(!BinaryenHeapTypeIsStruct(arrayHeapType)); assert(BinaryenHeapTypeIsArray(arrayHeapType)); @@ -2235,7 +2223,6 @@ void test_typebuilder() { assert(BinaryenArrayTypeIsElementMutable(arrayHeapType)); BinaryenHeapType structHeapType = heapTypes[tempStructIndex]; - assert(!BinaryenHeapTypeIsBasic(structHeapType)); assert(!BinaryenHeapTypeIsSignature(structHeapType)); assert(BinaryenHeapTypeIsStruct(structHeapType)); assert(!BinaryenHeapTypeIsArray(structHeapType)); @@ -2249,7 +2236,6 @@ void test_typebuilder() { assert(BinaryenStructTypeIsFieldMutable(structHeapType, 0)); BinaryenHeapType signatureHeapType = heapTypes[tempSignatureIndex]; - assert(!BinaryenHeapTypeIsBasic(signatureHeapType)); assert(BinaryenHeapTypeIsSignature(signatureHeapType)); assert(!BinaryenHeapTypeIsStruct(signatureHeapType)); assert(!BinaryenHeapTypeIsArray(signatureHeapType)); @@ -2269,17 +2255,7 @@ void test_typebuilder() { assert(BinaryenTypeArity(signatureResults) == 1); assert(signatureResults == signatureType); - BinaryenHeapType basicHeapType = heapTypes[tempBasicIndex]; // = eq - assert(BinaryenHeapTypeIsBasic(basicHeapType)); - assert(!BinaryenHeapTypeIsSignature(basicHeapType)); - assert(!BinaryenHeapTypeIsStruct(basicHeapType)); - assert(!BinaryenHeapTypeIsArray(basicHeapType)); - assert(!BinaryenHeapTypeIsBottom(basicHeapType)); - assert(BinaryenHeapTypeIsSubType(basicHeapType, BinaryenHeapTypeAny())); - BinaryenType basicType = BinaryenTypeFromHeapType(basicHeapType, true); - BinaryenHeapType subStructHeapType = heapTypes[tempSubStructIndex]; - assert(!BinaryenHeapTypeIsBasic(subStructHeapType)); assert(!BinaryenHeapTypeIsSignature(subStructHeapType)); assert(BinaryenHeapTypeIsStruct(subStructHeapType)); assert(!BinaryenHeapTypeIsArray(subStructHeapType)); @@ -2306,7 +2282,6 @@ void test_typebuilder() { BinaryenModuleSetTypeName(module, structHeapType, "SomeStruct"); BinaryenModuleSetFieldName(module, structHeapType, 0, "SomeField"); BinaryenModuleSetTypeName(module, signatureHeapType, "SomeSignature"); - BinaryenModuleSetTypeName(module, basicHeapType, "does-nothing"); BinaryenModuleSetTypeName(module, subStructHeapType, "SomeSubStruct"); BinaryenModuleSetFieldName(module, subStructHeapType, 0, "SomeField"); BinaryenModuleSetFieldName(module, subStructHeapType, 1, "SomePackedField"); @@ -2314,13 +2289,13 @@ void test_typebuilder() { module, BinaryenFeatureReferenceTypes() | BinaryenFeatureGC()); { BinaryenType varTypes[] = { - arrayType, structType, signatureType, basicType, subStructType}; + arrayType, structType, signatureType, subStructType}; BinaryenAddFunction(module, "test", BinaryenTypeNone(), BinaryenTypeNone(), varTypes, - 5, + 4, BinaryenNop(module)); } bool didValidate = BinaryenModuleValidate(module); diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 1c1a3b956..f9b688eaf 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -3162,8 +3162,7 @@ module with recursive GC types: (local $0 (ref null $SomeArray)) (local $1 (ref null $SomeStruct)) (local $2 (ref null $SomeSignature)) - (local $3 eqref) - (local $4 (ref null $SomeSubStruct)) + (local $3 (ref null $SomeSubStruct)) (nop) ) ) diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp deleted file mode 100644 index 2ce064b5f..000000000 --- a/test/example/type-builder.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include <cassert> -#include <iostream> - -#include "wasm-type-printing.h" -#include "wasm-type.h" - -using namespace wasm; - -// Check that the builder works when there are duplicate definitions -void test_canonicalization() { - std::cout << ";; Test canonicalization\n"; - - // (type $struct (struct (field (ref null $sig) (ref null $sig)))) - // (type $sig (func)) - HeapType sig = Signature(Type::none, Type::none); - HeapType struct_ = Struct({Field(Type(sig, Nullable), Immutable), - Field(Type(sig, Nullable), Immutable)}); - - TypeBuilder builder(4); - - Type tempSigRef1 = builder.getTempRefType(builder[0], Nullable); - Type tempSigRef2 = builder.getTempRefType(builder[1], Nullable); - - assert(tempSigRef1 != tempSigRef2); - assert(tempSigRef1 != Type(sig, Nullable)); - assert(tempSigRef2 != Type(sig, Nullable)); - - builder[0] = Signature(Type::none, Type::none); - builder[1] = Signature(Type::none, Type::none); - builder[2] = - Struct({Field(tempSigRef1, Immutable), Field(tempSigRef1, Immutable)}); - builder[3] = - Struct({Field(tempSigRef2, Immutable), Field(tempSigRef2, Immutable)}); - - std::vector<HeapType> built = *builder.build(); - - assert(built[0] == sig); - assert(built[1] == sig); - assert(built[2] == struct_); - assert(built[3] == struct_); -} - -// Check that defined basic HeapTypes are handled correctly. -void test_basic() { - std::cout << ";; Test basic\n"; - - Type canonAnyref = Type(HeapType::any, Nullable); - Type canonI31ref = Type(HeapType::i31, NonNullable); - - TypeBuilder builder(6); - - Type anyref = builder.getTempRefType(builder[4], Nullable); - Type i31ref = builder.getTempRefType(builder[5], NonNullable); - - builder[0] = Signature(canonAnyref, canonI31ref); - builder[1] = Signature(anyref, canonI31ref); - builder[2] = Signature(canonAnyref, i31ref); - builder[3] = Signature(anyref, i31ref); - builder[4] = HeapType::any; - builder[5] = HeapType::i31; - - std::vector<HeapType> built = *builder.build(); - - assert(built[0] == Signature(canonAnyref, canonI31ref)); - assert(built[1] == built[0]); - assert(built[2] == built[1]); - assert(built[3] == built[2]); - assert(built[4] == HeapType::any); - assert(built[5] == HeapType::i31); -} - -void test_recursive() { - std::cout << ";; Test recursive types\n"; - - { - // Trivial recursion - std::vector<HeapType> built; - { - TypeBuilder builder(1); - Type temp = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n\n"; - assert(built[0] == built[0].getSignature().results.getHeapType()); - assert(Type(built[0], Nullable) == built[0].getSignature().results); - } - - { - // Mutual recursion - std::vector<HeapType> built; - { - TypeBuilder builder(2); - builder.createRecGroup(0, 2); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - } - - { - // A longer chain of recursion - std::vector<HeapType> built; - { - TypeBuilder builder(5); - builder.createRecGroup(0, 5); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type temp4 = builder.getTempRefType(builder[4], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp2); - builder[2] = Signature(Type::none, temp3); - builder[3] = Signature(Type::none, temp4); - builder[4] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n"; - std::cout << print(built[2]) << "\n"; - std::cout << print(built[3]) << "\n"; - std::cout << print(built[4]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[2]); - assert(built[2].getSignature().results.getHeapType() == built[3]); - assert(built[3].getSignature().results.getHeapType() == built[4]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - assert(built[1] != built[2]); - assert(built[2] != built[3]); - assert(built[3] != built[4]); - } - - { - // Check canonicalization for non-recursive parents and children of - // recursive HeapTypes. - std::vector<HeapType> built; - { - TypeBuilder builder(6); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type tuple0_2 = builder.getTempTupleType({temp0, temp2}); - Type tuple1_3 = builder.getTempTupleType({temp1, temp3}); - builder[0] = Signature(); - builder[1] = Signature(); - builder.createRecGroup(2, 2); - builder[2] = Signature(Type::none, tuple0_2); - builder[3] = Signature(Type::none, tuple1_3); - builder[4] = Signature(Type::none, temp2); - builder[5] = Signature(Type::none, temp3); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n"; - std::cout << print(built[2]) << "\n"; - std::cout << print(built[3]) << "\n"; - std::cout << print(built[4]) << "\n"; - std::cout << print(built[5]) << "\n\n"; - assert(built[0] == built[1]); - assert(built[2] != built[3]); - assert(built[4] != built[5]); - assert(built[4].getSignature().results.getHeapType() == built[2]); - assert(built[5].getSignature().results.getHeapType() == built[3]); - assert(built[2].getSignature().results == - Type({Type(built[0], Nullable), Type(built[2], Nullable)})); - assert(built[3].getSignature().results == - Type({Type(built[1], Nullable), Type(built[3], Nullable)})); - } - - { - // Folded and unfolded - std::vector<HeapType> built; - { - TypeBuilder builder(2); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp0); - builder[1] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[0]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - } - - { - // Including a basic heap type - std::vector<HeapType> built; - { - TypeBuilder builder(3); - Type anyref = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = HeapType::any; - builder[1] = Signature(anyref, temp1); - builder[2] = Signature(anyref, temp1); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0] == HeapType::any); - assert(built[1].getSignature().results.getHeapType() == built[1]); - assert(built[2].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().params == Type(HeapType::any, Nullable)); - assert(built[2].getSignature().params == Type(HeapType::any, Nullable)); - assert(built[1] != built[2]); - } -} - -int main() { - // Run the tests twice to ensure things still work when the global stores are - // already populated. - for (size_t i = 0; i < 2; ++i) { - test_canonicalization(); - test_basic(); - test_recursive(); - } -} diff --git a/test/example/type-builder.txt b/test/example/type-builder.txt deleted file mode 100644 index b0cff3cc0..000000000 --- a/test/example/type-builder.txt +++ /dev/null @@ -1,54 +0,0 @@ -;; Test canonicalization -;; Test basic -;; Test recursive types -(type $0 (func (result (ref null $0)))) - -(type $0 (func (result (ref null $1)))) -(type $1 (func (result (ref null $0)))) - -(type $0 (func (result (ref null $1)))) -(type $1 (func (result (ref null $2)))) -(type $2 (func (result (ref null $3)))) -(type $3 (func (result (ref null $4)))) -(type $4 (func (result (ref null $0)))) - -(type $0 (func)) -(type $0 (func)) -(type $2 (func (result (ref null $0) (ref null $2)))) -(type $3 (func (result (ref null $0) (ref null $3)))) -(type $4 (func (result (ref null $2)))) -(type $5 (func (result (ref null $3)))) - -(type $0 (func (result (ref null $0)))) -(type $1 (func (result (ref null $0)))) - -any -(type $1 (func (param anyref) (result (ref null $1)))) - -;; Test canonicalization -;; Test basic -;; Test recursive types -(type $0 (func (result (ref null $0)))) - -(type $0 (func (result (ref null $1)))) -(type $1 (func (result (ref null $0)))) - -(type $0 (func (result (ref null $1)))) -(type $1 (func (result (ref null $2)))) -(type $2 (func (result (ref null $3)))) -(type $3 (func (result (ref null $4)))) -(type $4 (func (result (ref null $0)))) - -(type $0 (func)) -(type $0 (func)) -(type $2 (func (result (ref null $0) (ref null $2)))) -(type $3 (func (result (ref null $0) (ref null $3)))) -(type $4 (func (result (ref null $2)))) -(type $5 (func (result (ref null $3)))) - -(type $0 (func (result (ref null $0)))) -(type $1 (func (result (ref null $0)))) - -any -(type $1 (func (param anyref) (result (ref null $1)))) - diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp index 7d5f5aa98..84b9f33c8 100644 --- a/test/gtest/type-builder.cpp +++ b/test/gtest/type-builder.cpp @@ -489,28 +489,6 @@ TEST_F(TypeTest, CanonicalizeTypesBeforeSubtyping) { EXPECT_TRUE(result); } -TEST_F(TypeTest, CanonicalizeBasicTypes) { - TypeBuilder builder(5); - - Type anyref = builder.getTempRefType(builder[0], Nullable); - Type anyrefs = builder.getTempTupleType({anyref, anyref}); - - Type anyrefCanon = Type(HeapType::any, Nullable); - - builder[0] = HeapType::any; - builder[1] = Struct({Field(anyref, Immutable)}); - builder[2] = Struct({Field(anyrefCanon, Immutable)}); - builder[3] = Signature(anyrefs, Type::none); - builder[4] = Signature({anyrefCanon, anyrefCanon}, Type::none); - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[1], built[2]); - EXPECT_EQ(built[3], built[4]); -} - TEST_F(TypeTest, TestHeapTypeRelations) { HeapType ext = HeapType::ext; HeapType func = HeapType::func; diff --git a/test/lit/fuzz-types.test b/test/lit/fuzz-types.test index b10df152b..c1748e646 100644 --- a/test/lit/fuzz-types.test +++ b/test/lit/fuzz-types.test @@ -1,66 +1,66 @@ ;; RUN: wasm-fuzz-types -v --seed=1 | filecheck %s -;; CHECK: (type $0 (struct)) -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $1 (struct)) -;; CHECK-NEXT: (type $2 (array i16)) -;; CHECK-NEXT: (type $3 (func)) -;; CHECK-NEXT: (type $4 (func (param (ref $5) i32 i64 f64 f64 (ref eq) v128) (result i64))) -;; CHECK-NEXT: (type $5 (array (mut i32))) +;; CHECK: (rec +;; CHECK-NEXT: (type $0 (struct (field (mut (ref $1)) f64 v128 (mut (ref null $1)) (mut (ref null $0)) (ref $1)))) +;; CHECK-NEXT: (type $1 (struct (field (mut v128) (mut (ref null $1)) (mut i8) (mut i16) (mut i16)))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $6 (array (mut funcref))) -;; CHECK-NEXT: (type $7 (func (param f64) (result i64))) +;; CHECK-NEXT: (type $2 (array (mut i16))) +;; CHECK-NEXT: (type $3 (func)) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $8 (struct_subtype (field f64 (ref $2) f64 (mut (ref null $9))) $1)) -;; CHECK-NEXT: (type $9 (func_subtype (param (ref array) i32 i64 f64 f64 anyref v128) (result i64) $4)) +;; CHECK-NEXT: (type $4 (func (param f32) (result f64))) +;; CHECK-NEXT: (type $5 (array v128)) +;; CHECK-NEXT: (type $6 (array (mut (ref null $3)))) +;; CHECK-NEXT: (type $7 (func (param v128) (result f32))) +;; CHECK-NEXT: (type $8 (struct_subtype (field (mut v128) (mut (ref null $1)) (mut i8) (mut i16) (mut i16) (mut i64)) $1)) ;; CHECK-NEXT: ) +;; CHECK-NEXT: (type $9 (func_subtype (param v128) (result f32) $7)) +;; CHECK-NEXT: (type $10 (struct_subtype (field (mut (ref $1)) f64 v128 (mut (ref null $1)) (mut (ref null $0)) (ref $1)) $0)) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $10 (func_subtype (param (ref eq) i32 i64 f64 f64 anyref v128) (result i64) $9)) -;; CHECK-NEXT: (type $11 (array_subtype (mut funcref) $6)) -;; CHECK-NEXT: (type $12 (array nullref)) -;; CHECK-NEXT: (type $13 none) -;; CHECK-NEXT: (type $14 (array (ref $6))) -;; CHECK-NEXT: (type $15 (array i32)) +;; CHECK-NEXT: (type $11 (struct)) +;; CHECK-NEXT: (type $12 (struct (field (mut i32) (mut i32) v128))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $16 (array_subtype (ref none) $12)) -;; CHECK-NEXT: (type $17 (func (param (ref null $9)) (result f32 structref))) -;; CHECK-NEXT: (type $18 none) +;; CHECK-NEXT: (type $13 (func (param (ref null $4)) (result f32))) +;; CHECK-NEXT: (type $14 (array_subtype (mut i16) $2)) +;; CHECK-NEXT: (type $15 (struct (field (mut v128) (ref extern) (mut (ref $15))))) +;; CHECK-NEXT: (type $16 (struct_subtype (field (mut v128) (ref extern) (mut (ref $15))) $15)) +;; CHECK-NEXT: (type $17 (struct_subtype (field (mut (ref $1)) f64 v128 (mut (ref null $1)) (mut (ref null $0)) (ref $1)) $0)) +;; CHECK-NEXT: (type $18 (func_subtype (param f32) (result f64) $4)) ;; CHECK-NEXT: ) -;; CHECK-NEXT: (type $19 (func_subtype (param (ref any) i32 i64 f64 f64 anyref v128) (result i64) $9)) +;; CHECK-NEXT: (type $19 (func (result v128))) ;; CHECK-NEXT: ;; CHECK-NEXT: Inhabitable types: ;; CHECK-NEXT: ;; CHECK-NEXT: Built 20 types: -;; CHECK-NEXT: (type $0 (struct)) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $1 (struct)) -;; CHECK-NEXT: (type $2 (array i16)) -;; CHECK-NEXT: (type $3 (func)) -;; CHECK-NEXT: (type $4 (func (param (ref $5) i32 i64 f64 f64 (ref eq) v128) (result i64))) -;; CHECK-NEXT: (type $5 (array (mut i32))) +;; CHECK-NEXT: (type $0 (struct (field (mut (ref $1)) f64 v128 (mut (ref null $1)) (mut (ref null $0)) (ref $1)))) +;; CHECK-NEXT: (type $1 (struct (field (mut v128) (mut (ref null $1)) (mut i8) (mut i16) (mut i16)))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $6 (array (mut funcref))) -;; CHECK-NEXT: (type $7 (func (param f64) (result i64))) +;; CHECK-NEXT: (type $2 (array (mut i16))) +;; CHECK-NEXT: (type $3 (func)) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $8 (struct_subtype (field f64 (ref $2) f64 (mut (ref null $9))) $1)) -;; CHECK-NEXT: (type $9 (func_subtype (param (ref array) i32 i64 f64 f64 anyref v128) (result i64) $4)) +;; CHECK-NEXT: (type $4 (func (param f32) (result f64))) +;; CHECK-NEXT: (type $5 (array v128)) +;; CHECK-NEXT: (type $6 (array (mut (ref null $3)))) +;; CHECK-NEXT: (type $7 (func (param v128) (result f32))) +;; CHECK-NEXT: (type $8 (struct_subtype (field (mut v128) (mut (ref null $1)) (mut i8) (mut i16) (mut i16) (mut i64)) $1)) ;; CHECK-NEXT: ) +;; CHECK-NEXT: (type $9 (func_subtype (param v128) (result f32) $7)) +;; CHECK-NEXT: (type $10 (struct_subtype (field (mut (ref $1)) f64 v128 (mut (ref null $1)) (mut (ref null $0)) (ref $1)) $0)) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $10 (func_subtype (param (ref eq) i32 i64 f64 f64 anyref v128) (result i64) $9)) -;; CHECK-NEXT: (type $11 (array_subtype (mut funcref) $6)) -;; CHECK-NEXT: (type $12 (array nullref)) -;; CHECK-NEXT: (type $13 none) -;; CHECK-NEXT: (type $14 (array (ref $6))) -;; CHECK-NEXT: (type $15 (array i32)) +;; CHECK-NEXT: (type $11 (struct)) +;; CHECK-NEXT: (type $12 (struct (field (mut i32) (mut i32) v128))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $16 (array_subtype nullref $12)) -;; CHECK-NEXT: (type $17 (func (param (ref null $9)) (result f32 structref))) -;; CHECK-NEXT: (type $18 none) +;; CHECK-NEXT: (type $13 (func (param (ref null $4)) (result f32))) +;; CHECK-NEXT: (type $14 (array_subtype (mut i16) $2)) +;; CHECK-NEXT: (type $15 (struct (field (mut v128) externref (mut (ref null $15))))) +;; CHECK-NEXT: (type $16 (struct_subtype (field (mut v128) externref (mut (ref null $15))) $15)) +;; CHECK-NEXT: (type $17 (struct_subtype (field (mut (ref $1)) f64 v128 (mut (ref null $1)) (mut (ref null $0)) (ref $1)) $0)) +;; CHECK-NEXT: (type $18 (func_subtype (param f32) (result f64) $4)) ;; CHECK-NEXT: ) -;; CHECK-NEXT: (type $19 (func_subtype (param (ref any) i32 i64 f64 f64 anyref v128) (result i64) $9)) +;; CHECK-NEXT: (type $19 (func (result v128))) diff --git a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt index 16eb0cbd8..b82f34f20 100644 --- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt +++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt @@ -1,47 +1,55 @@ total - [exports] : 6 - [funcs] : 15 + [exports] : 4 + [funcs] : 7 [globals] : 16 [imports] : 5 [memories] : 1 [memory-data] : 20 - [table-data] : 3 + [table-data] : 0 [tables] : 1 - [tags] : 2 - [total] : 725 - [vars] : 22 + [tags] : 0 + [total] : 600 + [vars] : 17 ArrayFill : 1 ArrayLen : 3 - ArrayNew : 7 + ArrayNew : 12 + ArrayNewFixed : 2 ArraySet : 2 AtomicCmpxchg : 1 AtomicFence : 1 - AtomicNotify : 3 - Binary : 85 - Block : 90 - Break : 14 - Call : 14 - CallIndirect : 1 - Const : 173 - Drop : 4 - GlobalGet : 40 - GlobalSet : 40 - I31New : 1 - If : 29 - Load : 17 - LocalGet : 42 - LocalSet : 28 - Loop : 6 - Nop : 13 - RefAs : 7 + AtomicNotify : 1 + AtomicRMW : 2 + Binary : 73 + Block : 51 + Break : 5 + Call : 10 + CallRef : 3 + Const : 162 + DataDrop : 1 + Drop : 1 + GlobalGet : 21 + GlobalSet : 20 + I31Get : 1 + I31New : 4 + If : 21 + Load : 22 + LocalGet : 43 + LocalSet : 29 + Loop : 4 + MemoryFill : 1 + Nop : 8 + RefAs : 5 + RefCast : 2 + RefEq : 2 RefFunc : 9 - RefNull : 12 - Return : 4 - SIMDExtract : 1 - Store : 5 - StructGet : 2 - StructNew : 7 + RefIsNull : 4 + RefNull : 8 + RefTest : 2 + Return : 6 + Select : 2 + Store : 2 + StructNew : 18 TupleExtract : 2 - TupleMake : 10 - Unary : 28 - Unreachable : 23 + TupleMake : 4 + Unary : 19 + Unreachable : 10 |