summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/gc-type-utils.h13
-rw-r--r--src/ir/subtypes.h21
-rw-r--r--src/passes/TypeMerging.cpp51
-rw-r--r--src/passes/TypeSSA.cpp17
-rw-r--r--src/passes/Unsubtyping.cpp38
-rw-r--r--src/tools/fuzzing/fuzzing.cpp119
-rw-r--r--src/tools/fuzzing/heap-types.cpp132
-rw-r--r--src/tools/wasm-fuzz-types.cpp23
-rw-r--r--src/wasm/wasm-binary.cpp51
-rw-r--r--src/wasm/wasm-type.cpp161
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 << ')';