summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binaryen-c.cpp13
-rw-r--r--src/binaryen-c.h12
-rw-r--r--src/tools/fuzzing/heap-types.cpp81
-rw-r--r--src/tools/wasm-fuzz-types.cpp58
-rw-r--r--src/wasm-type.h15
-rw-r--r--src/wasm/wasm-type.cpp130
-rw-r--r--test/example/c-api-kitchen-sink.c37
-rw-r--r--test/example/c-api-kitchen-sink.txt3
-rw-r--r--test/example/type-builder.cpp233
-rw-r--r--test/example/type-builder.txt54
-rw-r--r--test/gtest/type-builder.cpp22
-rw-r--r--test/lit/fuzz-types.test82
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt76
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