diff options
-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 << ')'; |