diff options
author | Thomas Lively <tlively@google.com> | 2024-08-19 09:23:55 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-19 09:23:55 -0700 |
commit | 0b05a3ebc7feedfd28f54b6486cf3f2ec1864edb (patch) | |
tree | 530a4d6a6ccd4375f757a5b87f0ba16a4fbf6729 | |
parent | e058bfbdf31c7b59df8ab62a9ebaedac45521c12 (diff) | |
download | binaryen-0b05a3ebc7feedfd28f54b6486cf3f2ec1864edb.tar.gz binaryen-0b05a3ebc7feedfd28f54b6486cf3f2ec1864edb.tar.bz2 binaryen-0b05a3ebc7feedfd28f54b6486cf3f2ec1864edb.zip |
[NFC] Use HeapType::getKind more broadly (#6846)
Replace code that checked `isStruct()`, `isArray()`, etc. in sequence
with uses of `HeapType::getKind()` and switch statements. This will make
it easier to find the code that needs updating if/when we add new heap
type kinds in the future. It also makes it much easier to find code that
already needs updating to handle continuation types by grepping for
"TODO: cont".
-rw-r--r-- | src/ir/gc-type-utils.h | 13 | ||||
-rw-r--r-- | src/ir/subtypes.h | 21 | ||||
-rw-r--r-- | src/passes/TypeMerging.cpp | 51 | ||||
-rw-r--r-- | src/passes/TypeSSA.cpp | 17 | ||||
-rw-r--r-- | src/passes/Unsubtyping.cpp | 38 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 119 | ||||
-rw-r--r-- | src/tools/fuzzing/heap-types.cpp | 132 | ||||
-rw-r--r-- | src/tools/wasm-fuzz-types.cpp | 23 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 51 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 161 |
10 files changed, 363 insertions, 263 deletions
diff --git a/src/ir/gc-type-utils.h b/src/ir/gc-type-utils.h index 7c530e179..6ac6db3ba 100644 --- a/src/ir/gc-type-utils.h +++ b/src/ir/gc-type-utils.h @@ -149,10 +149,15 @@ inline EvaluationResult evaluateCastCheck(Type refType, Type castType) { // // TODO: use in more places inline std::optional<Field> getField(HeapType type, Index index = 0) { - if (type.isStruct()) { - return type.getStruct().fields[index]; - } else if (type.isArray()) { - return type.getArray().element; + switch (type.getKind()) { + case HeapTypeKind::Struct: + return type.getStruct().fields[index]; + case HeapTypeKind::Array: + return type.getArray().element; + case HeapTypeKind::Func: + case HeapTypeKind::Cont: + case HeapTypeKind::Basic: + break; } return {}; } diff --git a/src/ir/subtypes.h b/src/ir/subtypes.h index 767c79fd7..203772055 100644 --- a/src/ir/subtypes.h +++ b/src/ir/subtypes.h @@ -125,13 +125,20 @@ struct SubTypes { for (auto type : types) { HeapType basic; auto share = type.getShared(); - if (type.isStruct()) { - basic = HeapTypes::struct_.getBasic(share); - } else if (type.isArray()) { - basic = HeapTypes::array.getBasic(share); - } else { - assert(type.isSignature()); - basic = HeapTypes::func.getBasic(share); + switch (type.getKind()) { + case HeapTypeKind::Func: + basic = HeapTypes::func.getBasic(share); + break; + case HeapTypeKind::Struct: + basic = HeapTypes::struct_.getBasic(share); + break; + case HeapTypeKind::Array: + basic = HeapTypes::array.getBasic(share); + break; + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } auto& basicDepth = depths[basic]; basicDepth = std::max(basicDepth, depths[type] + 1); diff --git a/src/passes/TypeMerging.cpp b/src/passes/TypeMerging.cpp index e5ac7888b..1cac7732f 100644 --- a/src/passes/TypeMerging.cpp +++ b/src/passes/TypeMerging.cpp @@ -544,14 +544,22 @@ bool shapeEq(HeapType a, HeapType b) { if (a.isShared() != b.isShared()) { return false; } - if (a.isStruct() && b.isStruct()) { - return shapeEq(a.getStruct(), b.getStruct()); - } - if (a.isArray() && b.isArray()) { - return shapeEq(a.getArray(), b.getArray()); + auto aKind = a.getKind(); + auto bKind = b.getKind(); + if (aKind != bKind) { + return false; } - if (a.isSignature() && b.isSignature()) { - return shapeEq(a.getSignature(), b.getSignature()); + switch (aKind) { + case HeapTypeKind::Func: + return shapeEq(a.getSignature(), b.getSignature()); + case HeapTypeKind::Struct: + return shapeEq(a.getStruct(), b.getStruct()); + case HeapTypeKind::Array: + return shapeEq(a.getArray(), b.getArray()); + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } return false; } @@ -559,19 +567,24 @@ bool shapeEq(HeapType a, HeapType b) { size_t shapeHash(HeapType a) { size_t digest = hash(a.isOpen()); rehash(digest, a.isShared()); - if (a.isStruct()) { - rehash(digest, 0); - hash_combine(digest, shapeHash(a.getStruct())); - } else if (a.isArray()) { - rehash(digest, 1); - hash_combine(digest, shapeHash(a.getArray())); - } else if (a.isSignature()) { - rehash(digest, 2); - hash_combine(digest, shapeHash(a.getSignature())); - } else { - WASM_UNREACHABLE("unexpected kind"); + auto kind = a.getKind(); + rehash(digest, kind); + switch (kind) { + case HeapTypeKind::Func: + hash_combine(digest, shapeHash(a.getSignature())); + return digest; + case HeapTypeKind::Struct: + hash_combine(digest, shapeHash(a.getStruct())); + return digest; + case HeapTypeKind::Array: + hash_combine(digest, shapeHash(a.getArray())); + return digest; + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + break; } - return digest; + WASM_UNREACHABLE("unexpected kind"); } bool shapeEq(const Struct& a, const Struct& b) { diff --git a/src/passes/TypeSSA.cpp b/src/passes/TypeSSA.cpp index 1355b113e..8ba6c10c4 100644 --- a/src/passes/TypeSSA.cpp +++ b/src/passes/TypeSSA.cpp @@ -237,12 +237,17 @@ struct TypeSSA : public Pass { for (Index i = 0; i < num; i++) { auto* curr = newsToModify[i]; auto oldType = curr->type.getHeapType(); - if (oldType.isStruct()) { - builder[i] = oldType.getStruct(); - } else if (oldType.isArray()) { - builder[i] = oldType.getArray(); - } else { - WASM_UNREACHABLE("unexpected type kind"); + switch (oldType.getKind()) { + case HeapTypeKind::Struct: + builder[i] = oldType.getStruct(); + break; + case HeapTypeKind::Array: + builder[i] = oldType.getArray(); + break; + case HeapTypeKind::Func: + case HeapTypeKind::Cont: + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } builder[i].subTypeOf(oldType); builder[i].setShared(oldType.getShared()); diff --git a/src/passes/Unsubtyping.cpp b/src/passes/Unsubtyping.cpp index ccad4ed3d..8d76f348a 100644 --- a/src/passes/Unsubtyping.cpp +++ b/src/passes/Unsubtyping.cpp @@ -264,21 +264,31 @@ struct Unsubtyping if (super.isBasic()) { continue; } - if (type.isStruct()) { - const auto& fields = type.getStruct().fields; - const auto& superFields = super.getStruct().fields; - for (size_t i = 0, size = superFields.size(); i < size; ++i) { - noteSubtype(fields[i].type, superFields[i].type); + switch (type.getKind()) { + case HeapTypeKind::Func: { + auto sig = type.getSignature(); + auto superSig = super.getSignature(); + noteSubtype(superSig.params, sig.params); + noteSubtype(sig.results, superSig.results); + break; } - } else if (type.isArray()) { - auto elem = type.getArray().element; - noteSubtype(elem.type, super.getArray().element.type); - } else { - assert(type.isSignature()); - auto sig = type.getSignature(); - auto superSig = super.getSignature(); - noteSubtype(superSig.params, sig.params); - noteSubtype(sig.results, superSig.results); + case HeapTypeKind::Struct: { + const auto& fields = type.getStruct().fields; + const auto& superFields = super.getStruct().fields; + for (size_t i = 0, size = superFields.size(); i < size; ++i) { + noteSubtype(fields[i].type, superFields[i].type); + } + break; + } + case HeapTypeKind::Array: { + auto elem = type.getArray().element; + noteSubtype(elem.type, super.getArray().element.type); + break; + } + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } } diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 64780696b..bebf4f989 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -291,28 +291,35 @@ void TranslateToFuzzReader::setupHeapTypes() { auto eq = HeapTypes::eq.getBasic(share); auto any = HeapTypes::any.getBasic(share); auto func = HeapTypes::func.getBasic(share); - if (type.isStruct()) { - interestingHeapSubTypes[struct_].push_back(type); - interestingHeapSubTypes[eq].push_back(type); - interestingHeapSubTypes[any].push_back(type); - - // Note the mutable fields. - auto& fields = type.getStruct().fields; - for (Index i = 0; i < fields.size(); i++) { - if (fields[i].mutable_) { - mutableStructFields.push_back(StructField{type, i}); + switch (type.getKind()) { + case HeapTypeKind::Func: + interestingHeapSubTypes[func].push_back(type); + break; + case HeapTypeKind::Struct: { + interestingHeapSubTypes[struct_].push_back(type); + interestingHeapSubTypes[eq].push_back(type); + interestingHeapSubTypes[any].push_back(type); + // Note the mutable fields. + auto& fields = type.getStruct().fields; + for (Index i = 0; i < fields.size(); i++) { + if (fields[i].mutable_) { + mutableStructFields.push_back(StructField{type, i}); + } } + break; } - } else if (type.isArray()) { - interestingHeapSubTypes[array].push_back(type); - interestingHeapSubTypes[eq].push_back(type); - interestingHeapSubTypes[any].push_back(type); - - if (type.getArray().element.mutable_) { - mutableArrays.push_back(type); - } - } else if (type.isSignature()) { - interestingHeapSubTypes[func].push_back(type); + case HeapTypeKind::Array: + interestingHeapSubTypes[array].push_back(type); + interestingHeapSubTypes[eq].push_back(type); + interestingHeapSubTypes[any].push_back(type); + if (type.getArray().element.mutable_) { + mutableArrays.push_back(type); + } + break; + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } } @@ -2757,43 +2764,49 @@ Expression* TranslateToFuzzReader::makeCompoundRef(Type type) { return funcContext ? make(type) : makeTrivial(type); }; - if (heapType.isSignature()) { - return makeRefFuncConst(type); - } else if (type.isStruct()) { - auto& fields = heapType.getStruct().fields; - std::vector<Expression*> values; - // If there is a nondefaultable field, we must provide the value and not - // depend on defaults. Also do that randomly half the time. - if (std::any_of( - fields.begin(), - fields.end(), - [&](const Field& field) { return !field.type.isDefaultable(); }) || - oneIn(2)) { - for (auto& field : fields) { - values.push_back(makeChild(field.type)); - } - // Add more nesting manually, as we can easily get exponential blowup - // here. This nesting makes it much less likely for a recursive data - // structure to end up as a massive tree of struct.news, since the nesting - // limitation code at the top of this function will kick in. - if (!values.empty()) { - // Subtract 1 since if there is a single value there cannot be - // exponential blowup. - nester.add(values.size() - 1); + switch (heapType.getKind()) { + case HeapTypeKind::Func: + return makeRefFuncConst(type); + case HeapTypeKind::Struct: { + auto& fields = heapType.getStruct().fields; + std::vector<Expression*> values; + // If there is a nondefaultable field, we must provide the value and not + // depend on defaults. Also do that randomly half the time. + if (std::any_of( + fields.begin(), + fields.end(), + [&](const Field& field) { return !field.type.isDefaultable(); }) || + oneIn(2)) { + for (auto& field : fields) { + values.push_back(makeChild(field.type)); + } + // Add more nesting manually, as we can easily get exponential blowup + // here. This nesting makes it much less likely for a recursive data + // structure to end up as a massive tree of struct.news, since the + // nesting limitation code at the top of this function will kick in. + if (!values.empty()) { + // Subtract 1 since if there is a single value there cannot be + // exponential blowup. + nester.add(values.size() - 1); + } } + return builder.makeStructNew(heapType, values); } - return builder.makeStructNew(heapType, values); - } else if (type.isArray()) { - auto element = heapType.getArray().element; - Expression* init = nullptr; - if (!element.type.isDefaultable() || oneIn(2)) { - init = makeChild(element.type); + case HeapTypeKind::Array: { + auto element = heapType.getArray().element; + Expression* init = nullptr; + if (!element.type.isDefaultable() || oneIn(2)) { + init = makeChild(element.type); + } + auto* count = builder.makeConst(int32_t(upTo(MAX_ARRAY_SIZE))); + return builder.makeArrayNew(type.getHeapType(), count, init); } - auto* count = builder.makeConst(int32_t(upTo(MAX_ARRAY_SIZE))); - return builder.makeArrayNew(type.getHeapType(), count, init); - } else { - WASM_UNREACHABLE("bad user-defined ref type"); + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + break; } + WASM_UNREACHABLE("unexpected kind"); } Expression* TranslateToFuzzReader::makeStringNewArray() { diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index e4d54ae07..b4833475a 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -131,14 +131,20 @@ struct HeapTypeGeneratorImpl { } else { // We have a supertype, so create a subtype. HeapType supertype = builder[*supertypeIndices[index]]; - if (supertype.isSignature()) { - builder[index] = generateSubSignature(supertype.getSignature()); - } else if (supertype.isStruct()) { - builder[index] = generateSubStruct(supertype.getStruct(), share); - } else if (supertype.isArray()) { - builder[index] = generateSubArray(supertype.getArray()); - } else { - WASM_UNREACHABLE("unexpected kind"); + switch (supertype.getKind()) { + case wasm::HeapTypeKind::Func: + builder[index] = generateSubSignature(supertype.getSignature()); + break; + case wasm::HeapTypeKind::Struct: + builder[index] = generateSubStruct(supertype.getStruct(), share); + break; + case wasm::HeapTypeKind::Array: + builder[index] = generateSubArray(supertype.getArray()); + break; + case wasm::HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case wasm::HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } } } @@ -879,38 +885,44 @@ std::vector<HeapType> Inhabitator::build() { for (size_t i = 0; i < types.size(); ++i) { auto type = types[i]; - if (type.isStruct()) { - Struct copy = type.getStruct(); - for (size_t j = 0; j < copy.fields.size(); ++j) { - updateType({type, j}, copy.fields[j].type); + switch (type.getKind()) { + case HeapTypeKind::Func: { + auto sig = type.getSignature(); + size_t j = 0; + std::vector<Type> params; + for (auto param : sig.params) { + params.push_back(param); + updateType({type, j++}, params.back()); + } + std::vector<Type> results; + for (auto result : sig.results) { + results.push_back(result); + updateType({type, j++}, results.back()); + } + builder[i] = Signature(builder.getTempTupleType(params), + builder.getTempTupleType(results)); + continue; } - builder[i] = copy; - continue; - } - if (type.isArray()) { - Array copy = type.getArray(); - updateType({type, 0}, copy.element.type); - builder[i] = copy; - continue; - } - if (type.isSignature()) { - auto sig = type.getSignature(); - size_t j = 0; - std::vector<Type> params; - for (auto param : sig.params) { - params.push_back(param); - updateType({type, j++}, params.back()); + case HeapTypeKind::Struct: { + Struct copy = type.getStruct(); + for (size_t j = 0; j < copy.fields.size(); ++j) { + updateType({type, j}, copy.fields[j].type); + } + builder[i] = copy; + continue; } - std::vector<Type> results; - for (auto result : sig.results) { - results.push_back(result); - updateType({type, j++}, results.back()); + case HeapTypeKind::Array: { + Array copy = type.getArray(); + updateType({type, 0}, copy.element.type); + builder[i] = copy; + continue; } - builder[i] = Signature(builder.getTempTupleType(params), - builder.getTempTupleType(results)); - continue; + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + break; } - WASM_UNREACHABLE("unexpected type kind"); + WASM_UNREACHABLE("unexpected kind"); } // Establish rec groups. @@ -994,35 +1006,43 @@ bool isUninhabitable(Type type, bool isUninhabitable(HeapType type, std::unordered_set<HeapType>& visited, std::unordered_set<HeapType>& visiting) { - if (type.isBasic()) { - return false; - } - if (type.isSignature()) { - // Function types are always inhabitable. - return false; + switch (type.getKind()) { + case HeapTypeKind::Basic: + return false; + case HeapTypeKind::Func: + case HeapTypeKind::Cont: + // Function types are always inhabitable. + return false; + case HeapTypeKind::Struct: + case HeapTypeKind::Array: + break; } if (visited.count(type)) { return false; } - - if (!visiting.insert(type).second) { + auto [it, inserted] = visiting.insert(type); + if (!inserted) { return true; } - - if (type.isStruct()) { - for (auto& field : type.getStruct().fields) { - if (isUninhabitable(field.type, visited, visiting)) { + switch (type.getKind()) { + case HeapTypeKind::Struct: + for (auto& field : type.getStruct().fields) { + if (isUninhabitable(field.type, visited, visiting)) { + return true; + } + } + break; + case HeapTypeKind::Array: + if (isUninhabitable(type.getArray().element.type, visited, visiting)) { return true; } - } - } else if (type.isArray()) { - if (isUninhabitable(type.getArray().element.type, visited, visiting)) { - return true; - } - } else { - WASM_UNREACHABLE("unexpected type kind"); + break; + case HeapTypeKind::Basic: + case HeapTypeKind::Func: + case HeapTypeKind::Cont: + WASM_UNREACHABLE("unexpected kind"); } - visiting.erase(type); + visiting.erase(it); visited.insert(type); return false; } diff --git a/src/tools/wasm-fuzz-types.cpp b/src/tools/wasm-fuzz-types.cpp index 074d235c9..7ba341e09 100644 --- a/src/tools/wasm-fuzz-types.cpp +++ b/src/tools/wasm-fuzz-types.cpp @@ -297,15 +297,22 @@ void Fuzzer::checkCanonicalization() { // Copy the original types for (; index < types.size(); ++index) { auto type = types[index]; - if (type.isSignature()) { - builder[index] = getSignature(type.getSignature()); - } else if (type.isStruct()) { - builder[index] = getStruct(type.getStruct()); - } else if (type.isArray()) { - builder[index] = getArray(type.getArray()); - } else { - WASM_UNREACHABLE("unexpected type kind"); + switch (type.getKind()) { + case HeapTypeKind::Func: + builder[index] = getSignature(type.getSignature()); + continue; + case HeapTypeKind::Struct: + builder[index] = getStruct(type.getStruct()); + continue; + case HeapTypeKind::Array: + builder[index] = getArray(type.getArray()); + continue; + case HeapTypeKind::Cont: + WASM_UNREACHABLE("TODO: cont"); + case HeapTypeKind::Basic: + break; } + WASM_UNREACHABLE("unexpected type kind"); } } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 2abb32837..8565ddaad 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -291,30 +291,37 @@ void WasmBinaryWriter::writeTypes() { if (type.isShared()) { o << S32LEB(BinaryConsts::EncodedType::Shared); } - if (type.isSignature()) { - o << S32LEB(BinaryConsts::EncodedType::Func); - auto sig = type.getSignature(); - for (auto& sigType : {sig.params, sig.results}) { - o << U32LEB(sigType.size()); - for (const auto& type : sigType) { - writeType(type); + switch (type.getKind()) { + case HeapTypeKind::Func: { + o << S32LEB(BinaryConsts::EncodedType::Func); + auto sig = type.getSignature(); + for (auto& sigType : {sig.params, sig.results}) { + o << U32LEB(sigType.size()); + for (const auto& type : sigType) { + writeType(type); + } } + break; } - } else if (type.isContinuation()) { - o << S32LEB(BinaryConsts::EncodedType::Cont); - writeHeapType(type.getContinuation().type); - } else if (type.isStruct()) { - o << S32LEB(BinaryConsts::EncodedType::Struct); - auto fields = type.getStruct().fields; - o << U32LEB(fields.size()); - for (const auto& field : fields) { - writeField(field); - } - } else if (type.isArray()) { - o << S32LEB(BinaryConsts::EncodedType::Array); - writeField(type.getArray().element); - } else { - WASM_UNREACHABLE("TODO GC type writing"); + case HeapTypeKind::Struct: { + o << S32LEB(BinaryConsts::EncodedType::Struct); + auto fields = type.getStruct().fields; + o << U32LEB(fields.size()); + for (const auto& field : fields) { + writeField(field); + } + break; + } + case HeapTypeKind::Array: + o << S32LEB(BinaryConsts::EncodedType::Array); + writeField(type.getArray().element); + break; + case HeapTypeKind::Cont: + o << S32LEB(BinaryConsts::EncodedType::Cont); + writeHeapType(type.getContinuation().type); + break; + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } } finishSection(start); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 34299a9a1..84ae51521 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -1233,42 +1233,46 @@ size_t HeapType::getDepth() const { // In addition to the explicit supertypes we just traversed over, there is // implicit supertyping wrt basic types. A signature type always has one more // super, HeapType::func, etc. - if (!isBasic()) { - if (isFunction() || isContinuation()) { - depth++; - } else if (isStruct()) { + switch (getKind()) { + case HeapTypeKind::Basic: + // Some basic types have supers. + switch (getBasic(Unshared)) { + case HeapType::ext: + case HeapType::func: + case HeapType::cont: + case HeapType::any: + case HeapType::exn: + break; + case HeapType::eq: + depth++; + break; + case HeapType::i31: + case HeapType::struct_: + case HeapType::array: + case HeapType::string: + depth += 2; + break; + case HeapType::none: + case HeapType::nofunc: + case HeapType::nocont: + case HeapType::noext: + case HeapType::noexn: + // Bottom types are infinitely deep. + depth = size_t(-1l); + } + break; + case HeapTypeKind::Func: + case HeapTypeKind::Cont: + ++depth; + break; + case HeapTypeKind::Struct: // specific struct types <: struct <: eq <: any depth += 3; - } else if (isArray()) { + break; + case HeapTypeKind::Array: // specific array types <: array <: eq <: any depth += 3; - } - } else { - // Some basic types have supers. - switch (getBasic(Unshared)) { - case HeapType::ext: - case HeapType::func: - case HeapType::cont: - case HeapType::any: - case HeapType::exn: - break; - case HeapType::eq: - depth++; - break; - case HeapType::i31: - case HeapType::struct_: - case HeapType::array: - case HeapType::string: - depth += 2; - break; - case HeapType::none: - case HeapType::nofunc: - case HeapType::nocont: - case HeapType::noext: - case HeapType::noexn: - // Bottom types are infinitely deep. - depth = size_t(-1l); - } + break; } return depth; } @@ -1353,31 +1357,30 @@ bool HeapType::isSubType(HeapType left, HeapType right) { } std::vector<Type> HeapType::getTypeChildren() const { - if (isBasic()) { - return {}; - } - if (isStruct()) { - std::vector<Type> children; - for (auto& field : getStruct().fields) { - children.push_back(field.type); + switch (getKind()) { + case HeapTypeKind::Basic: + return {}; + case HeapTypeKind::Func: { + std::vector<Type> children; + auto sig = getSignature(); + for (auto tuple : {sig.params, sig.results}) { + for (auto t : tuple) { + children.push_back(t); + } + } + return children; } - return children; - } - if (isArray()) { - return {getArray().element.type}; - } - if (isSignature()) { - std::vector<Type> children; - auto sig = getSignature(); - for (auto tuple : {sig.params, sig.results}) { - for (auto t : tuple) { - children.push_back(t); + case HeapTypeKind::Struct: { + std::vector<Type> children; + for (auto& field : getStruct().fields) { + children.push_back(field.type); } + return children; } - return children; - } - if (isContinuation()) { - return {}; + case HeapTypeKind::Array: + return {getArray().element.type}; + case HeapTypeKind::Cont: + return {}; } WASM_UNREACHABLE("unexpected kind"); } @@ -1586,16 +1589,21 @@ TypeNames DefaultTypeNameGenerator::getNames(HeapType type) { if (inserted) { // Generate a new name for this type we have not previously seen. std::stringstream stream; - if (type.isSignature()) { - stream << "func." << funcCount++; - } else if (type.isContinuation()) { - stream << "cont." << contCount++; - } else if (type.isStruct()) { - stream << "struct." << structCount++; - } else if (type.isArray()) { - stream << "array." << arrayCount++; - } else { - WASM_UNREACHABLE("unexpected kind"); + switch (type.getKind()) { + case HeapTypeKind::Func: + stream << "func." << funcCount++; + break; + case HeapTypeKind::Struct: + stream << "struct." << structCount++; + break; + case HeapTypeKind::Array: + stream << "array." << arrayCount++; + break; + case HeapTypeKind::Cont: + stream << "cont." << contCount++; + break; + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } it->second = {stream.str(), {}}; } @@ -1972,16 +1980,21 @@ std::ostream& TypePrinter::print(HeapType type) { if (type.isShared()) { os << "(shared "; } - if (type.isSignature()) { - print(type.getSignature()); - } else if (type.isContinuation()) { - print(type.getContinuation()); - } else if (type.isStruct()) { - print(type.getStruct(), names.fieldNames); - } else if (type.isArray()) { - print(type.getArray()); - } else { - WASM_UNREACHABLE("unexpected type"); + switch (type.getKind()) { + case HeapTypeKind::Func: + print(type.getSignature()); + break; + case HeapTypeKind::Struct: + print(type.getStruct(), names.fieldNames); + break; + case HeapTypeKind::Array: + print(type.getArray()); + break; + case HeapTypeKind::Cont: + print(type.getContinuation()); + break; + case HeapTypeKind::Basic: + WASM_UNREACHABLE("unexpected kind"); } if (type.isShared()) { os << ')'; |