summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-09-16 15:37:43 -0700
committerGitHub <noreply@github.com>2024-09-16 15:37:43 -0700
commited19e3f699ddb72d59f227a9f20846c9ce79e2c6 (patch)
treec88e7be8f2672e6569f74c118dff12b201345c8e
parent106f84b4f2dc373b540ace29139f850576f22b8a (diff)
downloadbinaryen-ed19e3f699ddb72d59f227a9f20846c9ce79e2c6.tar.gz
binaryen-ed19e3f699ddb72d59f227a9f20846c9ce79e2c6.tar.bz2
binaryen-ed19e3f699ddb72d59f227a9f20846c9ce79e2c6.zip
[NFC] Move enough of wasm-type.cpp into wasm-type.h to inline core is*() methods (#6936)
This just moves code around. As a result, isRef() vanishes entirely from the profiling traces in #6931, since now the core isRef/Tuple/etc. methods are all inlineable. This also required some reordering of wasm-type.h, namely to move HeapType up front. No changes to that class otherwise. TypeInfo is now in the header. getTypeInfo is now a static method on Type. This has the downside of moving internal details into the header, and it may increase compile time a little. The upside is making the --precompute benchmark from #6931 significantly faster, 33%, and it will also help the many Type::isNonNullable() etc. calls we have scattered around the codebase in other passes too.
-rw-r--r--src/wasm-type.h479
-rw-r--r--src/wasm/wasm-type.cpp124
2 files changed, 300 insertions, 303 deletions
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 03c4f8e77..5b2074e1c 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -78,6 +78,227 @@ using HeapTypeNameGenerator = std::function<TypeNames(HeapType)>;
// HeapType.
using TypeID = uint64_t;
+enum Shareability { Shared, Unshared };
+
+enum class HeapTypeKind {
+ Basic,
+ Func,
+ Struct,
+ Array,
+ Cont,
+};
+
+class HeapType {
+ // Unlike `Type`, which represents the types of values on the WebAssembly
+ // stack, `HeapType` is used to describe the structures that reference types
+ // refer to. HeapTypes are canonicalized and interned exactly like Types and
+ // should also be passed by value.
+ uintptr_t id;
+
+public:
+ // Bit zero indicates whether the type is `shared`, so we need to leave it
+ // free.
+ enum BasicHeapType : uint32_t {
+ ext = 0 << 1,
+ func = 1 << 1,
+ cont = 2 << 1,
+ any = 3 << 1,
+ eq = 4 << 1,
+ i31 = 5 << 1,
+ struct_ = 6 << 1,
+ array = 7 << 1,
+ exn = 8 << 1,
+ string = 9 << 1,
+ none = 10 << 1,
+ noext = 11 << 1,
+ nofunc = 12 << 1,
+ nocont = 13 << 1,
+ noexn = 14 << 1,
+ };
+ static constexpr BasicHeapType _last_basic_type = BasicHeapType(noexn + 1);
+
+ // BasicHeapType can be implicitly upgraded to HeapType
+ constexpr HeapType(BasicHeapType id) : id(id) {}
+
+ // But converting raw TypeID is more dangerous, so make it explicit
+ explicit HeapType(TypeID id) : id(id) {}
+
+ // Choose an arbitrary heap type as the default.
+ constexpr HeapType() : HeapType(func) {}
+
+ // Construct a HeapType referring to the single canonical HeapType for the
+ // given signature. In nominal mode, this is the first HeapType created with
+ // this signature.
+ HeapType(Signature signature);
+
+ HeapType(Continuation cont);
+
+ // Create a HeapType with the given structure. In equirecursive mode, this may
+ // be the same as a previous HeapType created with the same contents. In
+ // nominal mode, this will be a fresh type distinct from all previously
+ // created HeapTypes.
+ // TODO: make these explicit to differentiate them.
+ HeapType(const Struct& struct_);
+ HeapType(Struct&& struct_);
+ HeapType(Array array);
+
+ HeapTypeKind getKind() const;
+
+ constexpr bool isBasic() const { return id <= _last_basic_type; }
+ bool isFunction() const {
+ return isMaybeShared(func) || getKind() == HeapTypeKind::Func;
+ }
+ bool isData() const {
+ auto kind = getKind();
+ return isMaybeShared(string) || kind == HeapTypeKind::Struct ||
+ kind == HeapTypeKind::Array;
+ }
+ bool isSignature() const { return getKind() == HeapTypeKind::Func; }
+ bool isContinuation() const { return getKind() == HeapTypeKind::Cont; }
+ bool isStruct() const { return getKind() == HeapTypeKind::Struct; }
+ bool isArray() const { return getKind() == HeapTypeKind::Array; }
+ bool isExn() const { return isMaybeShared(HeapType::exn); }
+ bool isString() const { return isMaybeShared(HeapType::string); }
+ bool isBottom() const;
+ bool isOpen() const;
+ bool isShared() const { return getShared() == Shared; }
+
+ Shareability getShared() const;
+
+ // Check if the type is a given basic heap type, while ignoring whether it is
+ // shared or not.
+ bool isMaybeShared(BasicHeapType type) const {
+ return isBasic() && getBasic(Unshared) == type;
+ }
+
+ Signature getSignature() const;
+ Continuation getContinuation() const;
+
+ const Struct& getStruct() const;
+ Array getArray() const;
+
+ // If there is a nontrivial (i.e. non-basic, one that was declared by the
+ // module) nominal supertype, return it, else an empty optional.
+ std::optional<HeapType> getDeclaredSuperType() const;
+
+ // As |getDeclaredSuperType|, but also handles basic types, that is, if the
+ // super is a basic type, then we return it here. Declared types are returned
+ // as well, just like |getDeclaredSuperType|.
+ std::optional<HeapType> getSuperType() const;
+
+ // Return the depth of this heap type in the nominal type hierarchy, i.e. the
+ // number of supertypes in its supertype chain.
+ size_t getDepth() const;
+
+ // Get the bottom heap type for this heap type's hierarchy.
+ BasicHeapType getUnsharedBottom() const;
+ BasicHeapType getBottom() const {
+ return HeapType(getUnsharedBottom()).getBasic(getShared());
+ }
+
+ // Get the top heap type for this heap type's hierarchy.
+ BasicHeapType getUnsharedTop() const;
+ BasicHeapType getTop() const {
+ return HeapType(getUnsharedTop()).getBasic(getShared());
+ }
+
+ // Get the recursion group for this non-basic type.
+ RecGroup getRecGroup() const;
+
+ // Get the index of this non-basic type within its recursion group.
+ size_t getRecGroupIndex() const;
+
+ constexpr TypeID getID() const { return id; }
+
+ // Get the shared or unshared version of this basic heap type.
+ constexpr BasicHeapType getBasic(Shareability share) const {
+ assert(isBasic());
+ return BasicHeapType(share == Shared ? (id | 1) : (id & ~1));
+ }
+
+ // (In)equality must be defined for both HeapType and BasicHeapType because it
+ // is otherwise ambiguous whether to convert both this and other to int or
+ // convert other to HeapType.
+ bool operator==(const HeapType& other) const { return id == other.id; }
+ bool operator==(const BasicHeapType& other) const { return id == other; }
+ bool operator!=(const HeapType& other) const { return id != other.id; }
+ bool operator!=(const BasicHeapType& other) const { return id != other; }
+
+ // Returns true if left is a subtype of right. Subtype includes itself.
+ static bool isSubType(HeapType left, HeapType right);
+
+ std::vector<Type> getTypeChildren() const;
+
+ // Return the ordered HeapType children, looking through child Types.
+ std::vector<HeapType> getHeapTypeChildren() const;
+
+ // Similar to `getHeapTypeChildren`, but also includes the supertype if it
+ // exists.
+ std::vector<HeapType> getReferencedHeapTypes() const;
+
+ // Return the LUB of two HeapTypes, which may or may not exist.
+ static std::optional<HeapType> getLeastUpperBound(HeapType a, HeapType b);
+
+ // Returns the feature set required to use this type.
+ FeatureSet getFeatures() const;
+
+ // Helper allowing the value of `print(...)` to be sent to an ostream. Stores
+ // a `TypeID` because `Type` is incomplete at this point and using a reference
+ // makes it less convenient to use.
+ struct Printed {
+ TypeID typeID;
+ HeapTypeNameGenerator generateName;
+ };
+
+ // Given a function for generating HeapType names, print the definition of
+ // this HeapType to `os`. `generateName` should return the same
+ // name each time it is called with the same HeapType and it should return
+ // different names for different types.
+ Printed print(HeapTypeNameGenerator generateName) {
+ return Printed{getID(), generateName};
+ }
+
+ std::string toString() const;
+};
+
+// Internal only.
+struct TypeInfo {
+ using type_t = Type;
+ // Used in assertions to ensure that temporary types don't leak into the
+ // global store.
+ bool isTemp = false;
+ enum Kind {
+ TupleKind,
+ RefKind,
+ } kind;
+ struct Ref {
+ HeapType heapType;
+ Nullability nullability;
+ };
+ union {
+ Tuple tuple;
+ Ref ref;
+ };
+
+ TypeInfo(const Tuple& tuple) : kind(TupleKind), tuple(tuple) {}
+ TypeInfo(Tuple&& tuple) : kind(TupleKind), tuple(std::move(tuple)) {}
+ TypeInfo(HeapType heapType, Nullability nullable)
+ : kind(RefKind), ref{heapType, nullable} {}
+ TypeInfo(const TypeInfo& other);
+ ~TypeInfo();
+
+ constexpr bool isTuple() const { return kind == TupleKind; }
+ constexpr bool isRef() const { return kind == RefKind; }
+
+ // If this TypeInfo represents a Type that can be represented more simply,
+ // return that simpler Type. For example, this handles eliminating singleton
+ // tuple types.
+ std::optional<Type> getCanonical() const;
+
+ bool operator==(const TypeInfo& other) const;
+ bool operator!=(const TypeInfo& other) const { return !(*this == other); }
+};
+
class Type {
// The `id` uniquely represents each type, so type equality is just a
// comparison of the ids. For basic types the `id` is just the `BasicType`
@@ -150,24 +371,72 @@ public:
constexpr bool isFloat() const { return id == f32 || id == f64; }
constexpr bool isVector() const { return id == v128; };
constexpr bool isNumber() const { return id >= i32 && id <= v128; }
- bool isTuple() const;
bool isSingle() const { return isConcrete() && !isTuple(); }
- bool isRef() const;
- bool isFunction() const;
- // See literal.h.
- bool isData() const;
+
+ // Tuples, refs, etc. are quickly handled using isBasic(), leaving the non-
+ // basic case for the underlying implementation.
+
+ bool isTuple() const {
+ if (isBasic()) {
+ return false;
+ } else {
+ return getTypeInfo(*this)->isTuple();
+ }
+ }
+
+ bool isRef() const {
+ if (isBasic()) {
+ return false;
+ } else {
+ return getTypeInfo(*this)->isRef();
+ }
+ }
+
+ bool isFunction() const {
+ if (isBasic()) {
+ return false;
+ } else {
+ auto* info = getTypeInfo(*this);
+ return info->isRef() && info->ref.heapType.isFunction();
+ }
+ }
+
+ bool isData() const {
+ if (isBasic()) {
+ return false;
+ } else {
+ auto* info = getTypeInfo(*this);
+ return info->isRef() && info->ref.heapType.isData();
+ }
+ }
+
// Checks whether a type is a reference and is nullable. This returns false
// for a value that is not a reference, that is, for which nullability is
// irrelevant.
- bool isNullable() const;
+ bool isNullable() const {
+ if (isRef()) {
+ return getTypeInfo(*this)->ref.nullability == Nullable;
+ } else {
+ return false;
+ }
+ }
+
// Checks whether a type is a reference and is non-nullable. This returns
// false for a value that is not a reference, that is, for which nullability
// is irrelevant. (For that reason, this is only the negation of isNullable()
// on references, but both return false on non-references.)
- bool isNonNullable() const;
+ bool isNonNullable() const {
+ if (isRef()) {
+ return getTypeInfo(*this)->ref.nullability == NonNullable;
+ } else {
+ return false;
+ }
+ }
+
+ bool isSignature() const { return isRef() && getHeapType().isSignature(); }
+
// Whether this type is only inhabited by null values.
bool isNull() const;
- bool isSignature() const;
bool isStruct() const;
bool isArray() const;
bool isExn() const;
@@ -222,11 +491,17 @@ public:
// Returns the tuple, assuming that this is a tuple type. Note that it is
// normally simpler to use operator[] and size() on the Type directly.
- const Tuple& getTuple() const;
+ HeapType getHeapType() const {
+ assert(isRef());
+ return getTypeInfo(*this)->ref.heapType;
+ }
// Gets the heap type corresponding to this type, assuming that it is a
// reference type.
- HeapType getHeapType() const;
+ const Tuple& getTuple() const {
+ assert(isTuple());
+ return getTypeInfo(*this)->tuple;
+ }
// Returns a number type based on its size in bytes and whether it is a float
// type.
@@ -308,189 +583,11 @@ public:
return std::make_reverse_iterator(begin());
}
const Type& operator[](size_t i) const { return *Iterator{{this, i}}; }
-};
-
-enum Shareability { Shared, Unshared };
-
-enum class HeapTypeKind {
- Basic,
- Func,
- Struct,
- Array,
- Cont,
-};
-
-class HeapType {
- // Unlike `Type`, which represents the types of values on the WebAssembly
- // stack, `HeapType` is used to describe the structures that reference types
- // refer to. HeapTypes are canonicalized and interned exactly like Types and
- // should also be passed by value.
- uintptr_t id;
-
-public:
- // Bit zero indicates whether the type is `shared`, so we need to leave it
- // free.
- enum BasicHeapType : uint32_t {
- ext = 0 << 1,
- func = 1 << 1,
- cont = 2 << 1,
- any = 3 << 1,
- eq = 4 << 1,
- i31 = 5 << 1,
- struct_ = 6 << 1,
- array = 7 << 1,
- exn = 8 << 1,
- string = 9 << 1,
- none = 10 << 1,
- noext = 11 << 1,
- nofunc = 12 << 1,
- nocont = 13 << 1,
- noexn = 14 << 1,
- };
- static constexpr BasicHeapType _last_basic_type = BasicHeapType(noexn + 1);
-
- // BasicHeapType can be implicitly upgraded to HeapType
- constexpr HeapType(BasicHeapType id) : id(id) {}
-
- // But converting raw TypeID is more dangerous, so make it explicit
- explicit HeapType(TypeID id) : id(id) {}
-
- // Choose an arbitrary heap type as the default.
- constexpr HeapType() : HeapType(func) {}
-
- // Construct a HeapType referring to the single canonical HeapType for the
- // given signature. In nominal mode, this is the first HeapType created with
- // this signature.
- HeapType(Signature signature);
-
- HeapType(Continuation cont);
-
- // Create a HeapType with the given structure. In equirecursive mode, this may
- // be the same as a previous HeapType created with the same contents. In
- // nominal mode, this will be a fresh type distinct from all previously
- // created HeapTypes.
- // TODO: make these explicit to differentiate them.
- HeapType(const Struct& struct_);
- HeapType(Struct&& struct_);
- HeapType(Array array);
-
- HeapTypeKind getKind() const;
-
- constexpr bool isBasic() const { return id <= _last_basic_type; }
- bool isFunction() const {
- return isMaybeShared(func) || getKind() == HeapTypeKind::Func;
- }
- bool isData() const {
- auto kind = getKind();
- return isMaybeShared(string) || kind == HeapTypeKind::Struct ||
- kind == HeapTypeKind::Array;
- }
- bool isSignature() const { return getKind() == HeapTypeKind::Func; }
- bool isContinuation() const { return getKind() == HeapTypeKind::Cont; }
- bool isStruct() const { return getKind() == HeapTypeKind::Struct; }
- bool isArray() const { return getKind() == HeapTypeKind::Array; }
- bool isExn() const { return isMaybeShared(HeapType::exn); }
- bool isString() const { return isMaybeShared(HeapType::string); }
- bool isBottom() const;
- bool isOpen() const;
- bool isShared() const { return getShared() == Shared; }
-
- Shareability getShared() const;
-
- // Check if the type is a given basic heap type, while ignoring whether it is
- // shared or not.
- bool isMaybeShared(BasicHeapType type) const {
- return isBasic() && getBasic(Unshared) == type;
- }
- Signature getSignature() const;
- Continuation getContinuation() const;
-
- const Struct& getStruct() const;
- Array getArray() const;
-
- // If there is a nontrivial (i.e. non-basic, one that was declared by the
- // module) nominal supertype, return it, else an empty optional.
- std::optional<HeapType> getDeclaredSuperType() const;
-
- // As |getDeclaredSuperType|, but also handles basic types, that is, if the
- // super is a basic type, then we return it here. Declared types are returned
- // as well, just like |getDeclaredSuperType|.
- std::optional<HeapType> getSuperType() const;
-
- // Return the depth of this heap type in the nominal type hierarchy, i.e. the
- // number of supertypes in its supertype chain.
- size_t getDepth() const;
-
- // Get the bottom heap type for this heap type's hierarchy.
- BasicHeapType getUnsharedBottom() const;
- BasicHeapType getBottom() const {
- return HeapType(getUnsharedBottom()).getBasic(getShared());
- }
-
- // Get the top heap type for this heap type's hierarchy.
- BasicHeapType getUnsharedTop() const;
- BasicHeapType getTop() const {
- return HeapType(getUnsharedTop()).getBasic(getShared());
- }
-
- // Get the recursion group for this non-basic type.
- RecGroup getRecGroup() const;
-
- // Get the index of this non-basic type within its recursion group.
- size_t getRecGroupIndex() const;
-
- constexpr TypeID getID() const { return id; }
-
- // Get the shared or unshared version of this basic heap type.
- constexpr BasicHeapType getBasic(Shareability share) const {
- assert(isBasic());
- return BasicHeapType(share == Shared ? (id | 1) : (id & ~1));
- }
-
- // (In)equality must be defined for both HeapType and BasicHeapType because it
- // is otherwise ambiguous whether to convert both this and other to int or
- // convert other to HeapType.
- bool operator==(const HeapType& other) const { return id == other.id; }
- bool operator==(const BasicHeapType& other) const { return id == other; }
- bool operator!=(const HeapType& other) const { return id != other.id; }
- bool operator!=(const BasicHeapType& other) const { return id != other; }
-
- // Returns true if left is a subtype of right. Subtype includes itself.
- static bool isSubType(HeapType left, HeapType right);
-
- std::vector<Type> getTypeChildren() const;
-
- // Return the ordered HeapType children, looking through child Types.
- std::vector<HeapType> getHeapTypeChildren() const;
-
- // Similar to `getHeapTypeChildren`, but also includes the supertype if it
- // exists.
- std::vector<HeapType> getReferencedHeapTypes() const;
-
- // Return the LUB of two HeapTypes, which may or may not exist.
- static std::optional<HeapType> getLeastUpperBound(HeapType a, HeapType b);
-
- // Returns the feature set required to use this type.
- FeatureSet getFeatures() const;
-
- // Helper allowing the value of `print(...)` to be sent to an ostream. Stores
- // a `TypeID` because `Type` is incomplete at this point and using a reference
- // makes it less convenient to use.
- struct Printed {
- TypeID typeID;
- HeapTypeNameGenerator generateName;
- };
-
- // Given a function for generating HeapType names, print the definition of
- // this HeapType to `os`. `generateName` should return the same
- // name each time it is called with the same HeapType and it should return
- // different names for different types.
- Printed print(HeapTypeNameGenerator generateName) {
- return Printed{getID(), generateName};
+ static TypeInfo* getTypeInfo(Type type) {
+ assert(!type.isBasic());
+ return (TypeInfo*)type.getID();
}
-
- std::string toString() const;
};
inline bool Type::isNull() const { return isRef() && getHeapType().isBottom(); }
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 151d45a1d..dad8bb669 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -41,43 +41,6 @@ namespace wasm {
namespace {
-struct TypeInfo {
- using type_t = Type;
- // Used in assertions to ensure that temporary types don't leak into the
- // global store.
- bool isTemp = false;
- enum Kind {
- TupleKind,
- RefKind,
- } kind;
- struct Ref {
- HeapType heapType;
- Nullability nullability;
- };
- union {
- Tuple tuple;
- Ref ref;
- };
-
- TypeInfo(const Tuple& tuple) : kind(TupleKind), tuple(tuple) {}
- TypeInfo(Tuple&& tuple) : kind(TupleKind), tuple(std::move(tuple)) {}
- TypeInfo(HeapType heapType, Nullability nullable)
- : kind(RefKind), ref{heapType, nullable} {}
- TypeInfo(const TypeInfo& other);
- ~TypeInfo();
-
- constexpr bool isTuple() const { return kind == TupleKind; }
- constexpr bool isRef() const { return kind == RefKind; }
-
- // If this TypeInfo represents a Type that can be represented more simply,
- // return that simpler Type. For example, this handles eliminating singleton
- // tuple types.
- std::optional<Type> getCanonical() const;
-
- bool operator==(const TypeInfo& other) const;
- bool operator!=(const TypeInfo& other) const { return !(*this == other); }
-};
-
using RecGroupInfo = std::vector<HeapType>;
struct HeapTypeInfo {
@@ -403,11 +366,6 @@ public:
namespace wasm {
namespace {
-TypeInfo* getTypeInfo(Type type) {
- assert(!type.isBasic());
- return (TypeInfo*)type.getID();
-}
-
HeapTypeInfo* getHeapTypeInfo(HeapType ht) {
assert(!ht.isBasic());
return (HeapTypeInfo*)ht.getID();
@@ -419,12 +377,14 @@ HeapType asHeapType(std::unique_ptr<HeapTypeInfo>& info) {
Type markTemp(Type type) {
if (!type.isBasic()) {
- getTypeInfo(type)->isTemp = true;
+ Type::getTypeInfo(type)->isTemp = true;
}
return type;
}
-bool isTemp(Type type) { return !type.isBasic() && getTypeInfo(type)->isTemp; }
+bool isTemp(Type type) {
+ return !type.isBasic() && Type::getTypeInfo(type)->isTemp;
+}
bool isTemp(HeapType type) {
return !type.isBasic() && getHeapTypeInfo(type)->isTemp;
@@ -517,6 +477,8 @@ std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a,
return {lubUnshared.getBasic(share)};
}
+} // anonymous namespace
+
TypeInfo::TypeInfo(const TypeInfo& other) {
kind = other.kind;
switch (kind) {
@@ -588,6 +550,8 @@ HeapTypeInfo::~HeapTypeInfo() {
WASM_UNREACHABLE("unexpected kind");
}
+namespace {
+
struct TypeStore {
std::recursive_mutex mutex;
@@ -756,60 +720,6 @@ Type::Type(HeapType heapType, Nullability nullable) {
new (this) Type(globalTypeStore.insert(TypeInfo(heapType, nullable)));
}
-bool Type::isTuple() const {
- if (isBasic()) {
- return false;
- } else {
- return getTypeInfo(*this)->isTuple();
- }
-}
-
-bool Type::isRef() const {
- if (isBasic()) {
- return false;
- } else {
- return getTypeInfo(*this)->isRef();
- }
-}
-
-bool Type::isFunction() const {
- if (isBasic()) {
- return false;
- } else {
- auto* info = getTypeInfo(*this);
- return info->isRef() && info->ref.heapType.isFunction();
- }
-}
-
-bool Type::isData() const {
- if (isBasic()) {
- return false;
- } else {
- auto* info = getTypeInfo(*this);
- return info->isRef() && info->ref.heapType.isData();
- }
-}
-
-bool Type::isNullable() const {
- if (isRef()) {
- return getTypeInfo(*this)->ref.nullability == Nullable;
- } else {
- return false;
- }
-}
-
-bool Type::isNonNullable() const {
- if (isRef()) {
- return getTypeInfo(*this)->ref.nullability == NonNullable;
- } else {
- return false;
- }
-}
-
-bool Type::isSignature() const {
- return isRef() && getHeapType().isSignature();
-}
-
bool Type::isStruct() const { return isRef() && getHeapType().isStruct(); }
bool Type::isArray() const { return isRef() && getHeapType().isArray(); }
@@ -919,16 +829,6 @@ FeatureSet Type::getFeatures() const {
return getSingleFeatures(*this);
}
-const Tuple& Type::getTuple() const {
- assert(isTuple());
- return getTypeInfo(*this)->tuple;
-}
-
-HeapType Type::getHeapType() const {
- assert(isRef());
- return getTypeInfo(*this)->ref.heapType;
-}
-
Type Type::get(unsigned byteSize, bool float_) {
if (byteSize < 4) {
return Type::i32;
@@ -2111,7 +2011,7 @@ size_t RecGroupHasher::hash(Type type) const {
if (type.isBasic()) {
wasm::rehash(digest, type.getID());
} else {
- hash_combine(digest, hash(*getTypeInfo(type)));
+ hash_combine(digest, hash(*Type::getTypeInfo(type)));
}
return digest;
}
@@ -2243,7 +2143,7 @@ bool RecGroupEquator::eq(Type a, Type b) const {
if (a.isBasic() || b.isBasic()) {
return a == b;
}
- return eq(*getTypeInfo(a), *getTypeInfo(b));
+ return eq(*Type::getTypeInfo(a), *Type::getTypeInfo(b));
}
bool RecGroupEquator::eq(HeapType a, HeapType b) const {
@@ -2393,7 +2293,7 @@ template<typename Self> void TypeGraphWalkerBase<Self>::scanType(Type* type) {
if (type->isBasic()) {
return;
}
- auto* info = getTypeInfo(*type);
+ auto* info = Type::getTypeInfo(*type);
switch (info->kind) {
case TypeInfo::TupleKind: {
auto& types = info->tuple;
@@ -2799,7 +2699,7 @@ buildRecGroup(std::unique_ptr<RecGroupInfo>&& groupInfo,
auto canonicalizeTypes = [&](bool tuples) {
for (auto& [original, uses] : locations.types) {
if (original.isTuple() == tuples) {
- Type canonical = globalTypeStore.insert(*getTypeInfo(original));
+ Type canonical = globalTypeStore.insert(*Type::getTypeInfo(original));
for (Type* use : uses) {
*use = canonical;
}