diff --git a/src/wasm-type.h b/src/wasm-type.h index cee8dae0355..8a9e58ec975 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -31,13 +31,6 @@ namespace wasm { -struct Tuple; -struct Signature; -struct Struct; -struct Array; - -typedef std::vector TypeList; - 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 `BasicID` @@ -73,16 +66,14 @@ class Type { Type(std::initializer_list); // Construct from tuple description - explicit Type(const Tuple&); - - // Construct from signature description - explicit Type(const Signature, bool nullable); + explicit Type(const struct Tuple&); - // Construct from struct description - explicit Type(const Struct&, bool nullable); + // Construct from a heap type description. Also covers construction from + // Signature, Struct or Array via implicit conversion to HeapType. + explicit Type(const struct HeapType&, bool nullable); - // Construct from array description - explicit Type(const Array&, bool nullable); + // Construct from rtt description + explicit Type(const struct Rtt&); // Predicates // Compound Concrete @@ -96,16 +87,18 @@ class Type { // │ f32 ║ x │ │ x │ x │ F │ │ F_loat // │ f64 ║ x │ │ x │ x │ F │ │ V_ector // │ v128 ║ x │ │ x │ x │ V │ ┘ - // ├─────────────╫───┼───┼───┼───┤───────┤ - // │ funcref ║ x │ │ x │ x │ f │ ┐ Ref - // │ externref ║ x │ │ x │ x │ │ │ f_unc - // │ nullref ║ x │ │ x │ x │ │ │ - // │ exnref ║ x │ │ x │ x │ │ │ - // ├─────────────╫───┼───┼───┼───┤───────┤ │ - // │ Signature ║ │ x │ x │ x │ f │ │ - // │ Struct ║ │ x │ x │ x │ │ │ - // │ Array ║ │ x │ x │ x │ │ ┘ + // ├─ Aliases ───╫───┼───┼───┼───┤───────┤ + // │ funcref ║ x │ │ x │ x │ f n │ ┐ Ref + // │ externref ║ x │ │ x │ x │ f? n │ │ f_unc, n_ullable + // │ anyref ║ x │ │ x │ x │ f? n │ │ ┐ + // │ eqref ║ x │ │ x │ x │ n │ │ │ TODO (GC) + // │ i31ref ║ x │ │ x │ x │ │ │ ┘ + // │ nullref ║ x │ │ x │ x │ f? n │ │ ◄ TODO (removed) + // │ exnref ║ x │ │ x │ x │ n │ │ + // ├─ Compound ──╫───┼───┼───┼───┤───────┤ │ + // │ Ref ║ │ x │ x │ x │ f? n? │◄┘ // │ Tuple ║ │ x │ │ x │ │ + // │ Rtt ║ │ x │ x │ x │ │ // └─────────────╨───┴───┴───┴───┴───────┘ constexpr bool isBasic() const { return id <= _last_basic_id; } constexpr bool isCompound() const { return id > _last_basic_id; } @@ -118,6 +111,7 @@ class Type { bool isSingle() const { return isConcrete() && !isTuple(); } bool isRef() const; bool isNullable() const; + bool isRtt() const; private: template bool hasPredicate() { @@ -227,6 +221,8 @@ struct ResultType { std::string toString() const; }; +typedef std::vector TypeList; + struct Tuple { TypeList types; Tuple() : types() {} @@ -303,6 +299,72 @@ struct Array { std::string toString() const; }; +struct HeapType { + enum Kind { + FuncKind, + ExternKind, + AnyKind, + EqKind, + I31Kind, + ExnKind, + _last_basic_kind = ExnKind, + SignatureKind, + StructKind, + ArrayKind, + } kind; + union { + Signature signature; + Struct struct_; + Array array; + }; + HeapType(Kind kind) : kind(kind) { assert(kind <= _last_basic_kind); } + HeapType(const Signature& signature) + : kind(SignatureKind), signature(signature) {} + HeapType(Signature&& signature) + : kind(SignatureKind), signature(std::move(signature)) {} + HeapType(const Struct& struct_) : kind(StructKind), struct_(struct_) {} + HeapType(Struct&& struct_) : kind(StructKind), struct_(std::move(struct_)) {} + HeapType(const Array& array) : kind(ArrayKind), array(array) {} + HeapType(Array&& array) : kind(ArrayKind), array(std::move(array)) {} + HeapType(const HeapType& other); + ~HeapType(); + + bool isSignature() const { return kind == SignatureKind; } + Signature getSignature() const { + assert(isSignature() && "Not a signature"); + return signature; + } + bool isStruct() const { return kind == StructKind; } + Struct getStruct() const { + assert(isStruct() && "Not a struct"); + return struct_; + } + bool isArray() const { return kind == ArrayKind; } + Array getArray() const { + assert(isArray() && "Not an array"); + return array; + } + + bool operator==(const HeapType& other) const; + bool operator!=(const HeapType& other) const { return !(*this == other); } + HeapType& operator=(const HeapType& other); + std::string toString() const; +}; + +struct Rtt { + uint32_t depth; + HeapType heapType; + Rtt(uint32_t depth, const HeapType& heapType) + : depth(depth), heapType(heapType) {} + Rtt(uint32_t depth, HeapType&& heapType) + : depth(depth), heapType(std::move(heapType)) {} + bool operator==(const Rtt& other) const { + return depth == other.depth && heapType == other.heapType; + } + bool operator!=(const Rtt& other) const { return !(*this == other); } + std::string toString() const; +}; + std::ostream& operator<<(std::ostream&, Type); std::ostream& operator<<(std::ostream&, ParamType); std::ostream& operator<<(std::ostream&, ResultType); @@ -311,6 +373,8 @@ std::ostream& operator<<(std::ostream&, Signature); std::ostream& operator<<(std::ostream&, Field); std::ostream& operator<<(std::ostream&, Struct); std::ostream& operator<<(std::ostream&, Array); +std::ostream& operator<<(std::ostream&, HeapType); +std::ostream& operator<<(std::ostream&, Rtt); } // namespace wasm @@ -340,6 +404,14 @@ template<> class hash { public: size_t operator()(const wasm::Array&) const; }; +template<> class hash { +public: + size_t operator()(const wasm::HeapType&) const; +}; +template<> class hash { +public: + size_t operator()(const wasm::Rtt&) const; +}; } // namespace std diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 5247ebb6f36..e46cb58866c 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -28,48 +28,40 @@ namespace wasm { struct TypeInfo { - enum Kind { TupleKind, SignatureRefKind, StructRefKind, ArrayRefKind } kind; - struct SignatureRef { - Signature signature; - bool nullable; - }; - struct StructRef { - Struct struct_; - bool nullable; - }; - struct ArrayRef { - Array array; + enum Kind { + TupleKind, + RefKind, + RttKind, + } kind; + struct Ref { + HeapType heapType; bool nullable; }; union { Tuple tuple; - SignatureRef signatureRef; - StructRef structRef; - ArrayRef arrayRef; + Ref ref; + Rtt rtt; }; TypeInfo(const Tuple& tuple) : kind(TupleKind), tuple(tuple) {} TypeInfo(Tuple&& tuple) : kind(TupleKind), tuple(std::move(tuple)) {} - TypeInfo(const Signature& signature, bool nullable) - : kind(SignatureRefKind), signatureRef{signature, nullable} {} - TypeInfo(const Struct& struct_, bool nullable) - : kind(StructRefKind), structRef{struct_, nullable} {} - TypeInfo(const Array& array, bool nullable) - : kind(ArrayRefKind), arrayRef{array, nullable} {} + TypeInfo(const HeapType& heapType, bool nullable) + : kind(RefKind), ref{heapType, nullable} {} + TypeInfo(HeapType&& heapType, bool nullable) + : kind(RefKind), ref{std::move(heapType), nullable} {} + TypeInfo(const Rtt& rtt) : kind(RttKind), rtt(rtt) {} + TypeInfo(Rtt&& rtt) : kind(RttKind), rtt(std::move(rtt)) {} TypeInfo(const TypeInfo& other) { kind = other.kind; switch (kind) { case TupleKind: new (&tuple) auto(other.tuple); return; - case SignatureRefKind: - new (&signatureRef) auto(other.signatureRef); + case RefKind: + new (&ref) auto(other.ref); return; - case StructRefKind: - new (&structRef) auto(other.structRef); - return; - case ArrayRefKind: - new (&arrayRef) auto(other.arrayRef); + case RttKind: + new (&rtt) auto(other.rtt); return; } WASM_UNREACHABLE("unexpected kind"); @@ -80,16 +72,12 @@ struct TypeInfo { tuple.~Tuple(); return; } - case SignatureRefKind: { - signatureRef.~SignatureRef(); - return; - } - case StructRefKind: { - structRef.~StructRef(); + case RefKind: { + ref.~Ref(); return; } - case ArrayRefKind: { - arrayRef.~ArrayRef(); + case RttKind: { + rtt.~Rtt(); return; } } @@ -97,23 +85,10 @@ struct TypeInfo { } constexpr bool isTuple() const { return kind == TupleKind; } - constexpr bool isSignatureRef() const { return kind == SignatureRefKind; } - constexpr bool isStructRef() const { return kind == StructRefKind; } - constexpr bool isArrayRef() const { return kind == ArrayRefKind; } + constexpr bool isRef() const { return kind == RefKind; } + constexpr bool isRtt() const { return kind == RttKind; } - bool isNullable() const { - switch (kind) { - case TupleKind: - return false; - case SignatureRefKind: - return signatureRef.nullable; - case StructRefKind: - return structRef.nullable; - case ArrayRefKind: - return arrayRef.nullable; - } - WASM_UNREACHABLE("unexpected kind"); - } + bool isNullable() const { return kind == RefKind && ref.nullable; } bool operator==(const TypeInfo& other) const { if (kind != other.kind) { @@ -122,15 +97,11 @@ struct TypeInfo { switch (kind) { case TupleKind: return tuple == other.tuple; - case SignatureRefKind: - return signatureRef.nullable == other.signatureRef.nullable && - signatureRef.signature == other.signatureRef.signature; - case StructRefKind: - return structRef.nullable == other.structRef.nullable && - structRef.struct_ == other.structRef.struct_; - case ArrayRefKind: - return arrayRef.nullable == other.arrayRef.nullable && - arrayRef.array == other.arrayRef.array; + case RefKind: + return ref.heapType == other.ref.heapType && + ref.nullable == other.ref.nullable; + case RttKind: + return rtt == other.rtt; } WASM_UNREACHABLE("unexpected kind"); } @@ -180,22 +151,16 @@ template<> class hash { auto digest = wasm::hash(info.kind); switch (info.kind) { case wasm::TypeInfo::TupleKind: { - wasm::rehash(digest, info.tuple.types); - return digest; - } - case wasm::TypeInfo::SignatureRefKind: { - wasm::rehash(digest, info.signatureRef.signature); - wasm::rehash(digest, info.signatureRef.nullable); + wasm::rehash(digest, info.tuple); return digest; } - case wasm::TypeInfo::StructRefKind: { - wasm::rehash(digest, info.structRef.struct_); - wasm::rehash(digest, info.structRef.nullable); + case wasm::TypeInfo::RefKind: { + wasm::rehash(digest, info.ref.heapType); + wasm::rehash(digest, info.ref.nullable); return digest; } - case wasm::TypeInfo::ArrayRefKind: { - wasm::rehash(digest, info.arrayRef.array); - wasm::rehash(digest, info.arrayRef.nullable); + case wasm::TypeInfo::RttKind: { + wasm::rehash(digest, info.rtt); return digest; } } @@ -225,15 +190,42 @@ size_t hash::operator()(const wasm::Field& field) const { } size_t hash::operator()(const wasm::Struct& struct_) const { - auto digest = wasm::hash(0); - wasm::rehash(digest, struct_.fields); - return digest; + return wasm::hash(struct_.fields); } size_t hash::operator()(const wasm::Array& array) const { return wasm::hash(array.element); } +size_t hash::operator()(const wasm::HeapType& heapType) const { + auto digest = wasm::hash(heapType.kind); + switch (heapType.kind) { + case wasm::HeapType::FuncKind: + case wasm::HeapType::ExternKind: + case wasm::HeapType::AnyKind: + case wasm::HeapType::EqKind: + case wasm::HeapType::I31Kind: + case wasm::HeapType::ExnKind: + return digest; + case wasm::HeapType::SignatureKind: + wasm::rehash(digest, heapType.signature); + return digest; + case wasm::HeapType::StructKind: + wasm::rehash(digest, heapType.struct_); + return digest; + case wasm::HeapType::ArrayKind: + wasm::rehash(digest, heapType.array); + return digest; + } + WASM_UNREACHABLE("unexpected kind"); +} + +size_t hash::operator()(const wasm::Rtt& rtt) const { + auto digest = wasm::hash(rtt.depth); + wasm::rehash(digest, rtt.heapType); + return digest; +} + } // namespace std namespace wasm { @@ -261,9 +253,16 @@ std::unordered_map indices = { {TypeInfo({Type::f64}), Type::f64}, {TypeInfo({Type::v128}), Type::v128}, {TypeInfo({Type::funcref}), Type::funcref}, + {TypeInfo(HeapType(HeapType::FuncKind), true), Type::funcref}, {TypeInfo({Type::externref}), Type::externref}, - {TypeInfo({Type::nullref}), Type::nullref}, + {TypeInfo(HeapType(HeapType::ExternKind), true), Type::externref}, + // TODO (GC): Add canonical ids + // * `(ref null any) == anyref` + // * `(ref null eq) == eqref` + // * `(ref i31) == i31ref` + {TypeInfo({Type::nullref}), Type::nullref}, // TODO (removed) {TypeInfo({Type::exnref}), Type::exnref}, + {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref}, }; } // anonymous namespace @@ -306,23 +305,31 @@ Type::Type(const Tuple& tuple) { id = canonicalize(TypeInfo(tuple)); } -Type::Type(const Signature signature, bool nullable) { - id = canonicalize(TypeInfo(signature, nullable)); -} - -Type::Type(const Struct& struct_, bool nullable) { +Type::Type(const HeapType& heapType, bool nullable) { #ifndef NDEBUG - for (Field f : struct_.fields) { - assert(f.type.isSingle()); + switch (heapType.kind) { + case HeapType::FuncKind: + case HeapType::ExternKind: + case HeapType::AnyKind: + case HeapType::EqKind: + case HeapType::I31Kind: + case HeapType::ExnKind: + case HeapType::SignatureKind: + break; + case HeapType::StructKind: + for (Field f : heapType.struct_.fields) { + assert(f.type.isSingle()); + } + break; + case HeapType::ArrayKind: + assert(heapType.array.element.type.isSingle()); + break; } #endif - id = canonicalize(TypeInfo(struct_, nullable)); + id = canonicalize(TypeInfo(heapType, nullable)); } -Type::Type(const Array& array, bool nullable) { - assert(array.element.type.isSingle()); - id = canonicalize(TypeInfo(array, nullable)); -} +Type::Type(const Rtt& rtt) { id = canonicalize(TypeInfo(rtt)); } bool Type::isTuple() const { if (isBasic()) { @@ -336,15 +343,7 @@ bool Type::isRef() const { if (isBasic()) { return id >= funcref && id <= exnref; } else { - switch (getTypeInfo(*this)->kind) { - case TypeInfo::TupleKind: - return false; - case TypeInfo::SignatureRefKind: - case TypeInfo::StructRefKind: - case TypeInfo::ArrayRefKind: - return true; - } - WASM_UNREACHABLE("unexpected kind"); + return getTypeInfo(*this)->isRef(); } } @@ -356,6 +355,14 @@ bool Type::isNullable() const { } } +bool Type::isRtt() const { + if (isBasic()) { + return false; + } else { + return getTypeInfo(*this)->isRtt(); + } +} + bool Type::operator<(const Type& other) const { return std::lexicographical_compare(begin(), end(), @@ -547,6 +554,80 @@ const Type& Type::operator[](size_t index) const { } } +HeapType::HeapType(const HeapType& other) { + kind = other.kind; + switch (kind) { + case FuncKind: + case ExternKind: + case AnyKind: + case EqKind: + case I31Kind: + case ExnKind: + return; + case SignatureKind: + new (&signature) auto(other.signature); + return; + case StructKind: + new (&struct_) auto(other.struct_); + return; + case ArrayKind: + new (&array) auto(other.array); + return; + } + WASM_UNREACHABLE("unexpected kind"); +} + +HeapType::~HeapType() { + switch (kind) { + case FuncKind: + case ExternKind: + case AnyKind: + case EqKind: + case I31Kind: + case ExnKind: + return; + case SignatureKind: + signature.~Signature(); + return; + case StructKind: + struct_.~Struct(); + return; + case ArrayKind: + array.~Array(); + return; + } +} + +bool HeapType::operator==(const HeapType& other) const { + if (kind != other.kind) { + return false; + } + switch (kind) { + case FuncKind: + case ExternKind: + case AnyKind: + case EqKind: + case I31Kind: + case ExnKind: + return true; + case SignatureKind: + return signature == other.signature; + case StructKind: + return struct_ == other.struct_; + case ArrayKind: + return array == other.array; + } + WASM_UNREACHABLE("unexpected kind"); +} + +HeapType& HeapType::operator=(const HeapType& other) { + if (&other != this) { + this->~HeapType(); + new (this) auto(other); + } + return *this; +} + namespace { std::ostream& @@ -581,6 +662,10 @@ std::string Struct::toString() const { return genericToString(*this); } std::string Array::toString() const { return genericToString(*this); } +std::string HeapType::toString() const { return genericToString(*this); } + +std::string Rtt::toString() const { return genericToString(*this); } + std::string TypeInfo::toString() const { return genericToString(*this); } bool Signature::operator<(const Signature& other) const { @@ -708,31 +793,48 @@ std::ostream& operator<<(std::ostream& os, Array array) { return os << "(array " << array.element << ")"; } +std::ostream& operator<<(std::ostream& os, HeapType heapType) { + switch (heapType.kind) { + case wasm::HeapType::FuncKind: + return os << "func"; + case wasm::HeapType::ExternKind: + return os << "extern"; + case wasm::HeapType::AnyKind: + return os << "any"; + case wasm::HeapType::EqKind: + return os << "eq"; + case wasm::HeapType::I31Kind: + return os << "i31"; + case wasm::HeapType::ExnKind: + return os << "exn"; + case wasm::HeapType::SignatureKind: + return os << heapType.signature; + case wasm::HeapType::StructKind: + return os << heapType.struct_; + case wasm::HeapType::ArrayKind: + return os << heapType.array; + } + WASM_UNREACHABLE("unexpected kind"); +} + +std::ostream& operator<<(std::ostream& os, Rtt rtt) { + return os << "(rtt " << rtt.depth << " " << rtt.heapType << ")"; +} + std::ostream& operator<<(std::ostream& os, TypeInfo info) { switch (info.kind) { case TypeInfo::TupleKind: { return os << info.tuple; } - case TypeInfo::SignatureRefKind: { - os << "(ref "; - if (info.signatureRef.nullable) { - os << "null "; - } - return os << info.signatureRef.signature << ")"; - } - case TypeInfo::StructRefKind: { + case TypeInfo::RefKind: { os << "(ref "; - if (info.structRef.nullable) { + if (info.ref.nullable) { os << "null "; } - return os << info.structRef.struct_ << ")"; + return os << info.ref.heapType << ")"; } - case TypeInfo::ArrayRefKind: { - os << "(ref "; - if (info.arrayRef.nullable) { - os << "null "; - } - return os << info.arrayRef.array << ")"; + case TypeInfo::RttKind: { + return os << info.rtt; } } WASM_UNREACHABLE("unexpected kind"); diff --git a/test/example/typeinfo.cpp b/test/example/typeinfo.cpp index dc98667060f..ac01c6a1b8c 100644 --- a/test/example/typeinfo.cpp +++ b/test/example/typeinfo.cpp @@ -6,6 +6,49 @@ using namespace wasm; void test_compound() { + { + HeapType func(HeapType::FuncKind); + assert(Type(func, true).getID() == Type::funcref); + assert(Type(func, false).getID() == Type(func, false).getID()); + assert(Type(func, false).getID() != Type(func, true).getID()); + HeapType sameFunc(HeapType::FuncKind); + assert(Type(func, false).getID() == Type(sameFunc, false).getID()); + + HeapType extern_(HeapType::ExternKind); + assert(Type(extern_, true).getID() == Type::externref); + assert(Type(extern_, false).getID() == Type(extern_, false).getID()); + assert(Type(extern_, false).getID() != Type(extern_, true).getID()); + HeapType sameExtern(HeapType::ExternKind); + assert(Type(extern_, false).getID() == Type(sameExtern, false).getID()); + + HeapType any(HeapType::AnyKind); + // assert(Type(any, true).getID() == Type::anyref); + assert(Type(any, false).getID() == Type(any, false).getID()); + assert(Type(any, false).getID() != Type(any, true).getID()); + HeapType sameAny(HeapType::AnyKind); + assert(Type(any, false).getID() == Type(sameAny, false).getID()); + + HeapType eq(HeapType::EqKind); + // assert(Type(eq, true).getID() == Type::eqref); + assert(Type(eq, false).getID() == Type(eq, false).getID()); + assert(Type(eq, false).getID() != Type(eq, true).getID()); + HeapType sameEq(HeapType::EqKind); + assert(Type(eq, false).getID() == Type(sameEq, false).getID()); + + HeapType i31(HeapType::I31Kind); + // assert(Type(i31, false).getID() == Type::i31ref); + assert(Type(i31, false).getID() == Type(i31, false).getID()); + assert(Type(i31, false).getID() != Type(i31, true).getID()); + HeapType sameI31(HeapType::I31Kind); + assert(Type(i31, false).getID() == Type(sameI31, false).getID()); + + HeapType exn(HeapType::ExnKind); + assert(Type(exn, true).getID() == Type::exnref); + assert(Type(exn, false).getID() == Type(exn, false).getID()); + assert(Type(exn, false).getID() != Type(exn, true).getID()); + HeapType sameExn(HeapType::ExnKind); + assert(Type(exn, false).getID() == Type(sameExn, false).getID()); + } { Signature signature(Type::i32, Type::none); assert(Type(signature, false).getID() == Type(signature, false).getID()); @@ -54,11 +97,62 @@ void test_compound() { Tuple otherTuple({Type::f64, Type::externref}); assert(Type(tuple).getID() != Type(otherTuple).getID()); } + { + Rtt rtt(0, HeapType::FuncKind); + assert(Type(rtt).getID() == Type(rtt).getID()); + + Rtt sameRtt(0, HeapType::FuncKind); + assert(rtt == sameRtt); + assert(Type(rtt).getID() == Type(sameRtt).getID()); + + Rtt otherDepthRtt(1, HeapType::FuncKind); + assert(rtt != otherDepthRtt); + assert(Type(rtt).getID() != Type(otherDepthRtt).getID()); + + Rtt otherHeapTypeRtt(0, HeapType::AnyKind); + assert(rtt != otherHeapTypeRtt); + assert(Type(rtt).getID() != Type(otherHeapTypeRtt).getID()); + + Rtt structRtt(0, Struct({})); + assert(Type(structRtt).getID() == Type(structRtt).getID()); + + Rtt sameStructRtt(0, Struct({})); + assert(structRtt == sameStructRtt); + assert(Type(structRtt).getID() == Type(sameStructRtt).getID()); + + Rtt otherStructRtt(0, Struct({{Type::i32, false}})); + assert(structRtt != otherStructRtt); + assert(Type(structRtt).getID() != Type(otherStructRtt).getID()); + } } void test_printing() { { - std::cout << ";; Signature\n"; + std::cout << ";; Heap types\n"; + std::cout << HeapType(HeapType::FuncKind) << "\n"; + std::cout << Type(HeapType::FuncKind, true) << "\n"; + std::cout << Type(HeapType::FuncKind, false) << "\n"; + std::cout << HeapType(HeapType::ExternKind) << "\n"; + std::cout << Type(HeapType::ExternKind, true) << "\n"; + std::cout << Type(HeapType::ExternKind, false) << "\n"; + std::cout << HeapType(HeapType::AnyKind) << "\n"; + std::cout << Type(HeapType::AnyKind, true) << "\n"; + std::cout << Type(HeapType::AnyKind, false) << "\n"; + std::cout << HeapType(HeapType::EqKind) << "\n"; + std::cout << Type(HeapType::EqKind, true) << "\n"; + std::cout << Type(HeapType::EqKind, false) << "\n"; + std::cout << HeapType(HeapType::I31Kind) << "\n"; + std::cout << Type(HeapType::I31Kind, true) << "\n"; + std::cout << Type(HeapType::I31Kind, false) << "\n"; + std::cout << HeapType(HeapType::ExnKind) << "\n"; + std::cout << Type(HeapType::ExnKind, true) << "\n"; + std::cout << Type(HeapType::ExnKind, false) << "\n"; + std::cout << HeapType(Signature(Type::none, Type::none)) << "\n"; + std::cout << HeapType(Struct({})) << "\n"; + std::cout << HeapType(Array({Type::i32, false})) << "\n"; + } + { + std::cout << "\n;; Signature\n"; Signature emptySignature(Type::none, Type::none); std::cout << emptySignature << "\n"; std::cout << Type(emptySignature, false) << "\n"; @@ -109,6 +203,30 @@ void test_printing() { std::cout << tuple << "\n"; std::cout << Type(tuple) << "\n"; } + { + std::cout << "\n;; Rtt\n"; + std::cout << Rtt(0, HeapType::FuncKind) << "\n"; + std::cout << Type(Rtt(0, HeapType::FuncKind)) << "\n"; + std::cout << Rtt(1, HeapType::ExternKind) << "\n"; + std::cout << Type(Rtt(1, HeapType::ExternKind)) << "\n"; + std::cout << Rtt(2, HeapType::AnyKind) << "\n"; + std::cout << Type(Rtt(2, HeapType::AnyKind)) << "\n"; + std::cout << Rtt(3, HeapType::EqKind) << "\n"; + std::cout << Type(Rtt(3, HeapType::EqKind)) << "\n"; + std::cout << Rtt(4, HeapType::I31Kind) << "\n"; + std::cout << Type(Rtt(4, HeapType::I31Kind)) << "\n"; + std::cout << Rtt(5, HeapType::ExnKind) << "\n"; + std::cout << Type(Rtt(5, HeapType::ExnKind)) << "\n"; + Rtt signatureRtt(6, Signature(Type::none, Type::none)); + std::cout << signatureRtt << "\n"; + std::cout << Type(signatureRtt) << "\n"; + Rtt structRtt(7, Struct({})); + std::cout << structRtt << "\n"; + std::cout << Type(structRtt) << "\n"; + Rtt arrayRtt(8, Array({Type::i32, false})); + std::cout << arrayRtt << "\n"; + std::cout << Type(arrayRtt) << "\n"; + } { std::cout << "\n;; Signature of references (param/result)\n"; Signature signature(Type(Struct({}), true), @@ -197,7 +315,7 @@ void test_printing() { } // TODO: Think about recursive types. Currently impossible to construct. { - std::cout << "\n;; Recursive\n"; + std::cout << "\n;; Recursive (not really)\n"; Signature signatureSignature(Type::none, Type::none); signatureSignature.params = Type(signatureSignature, false); // ^ copies diff --git a/test/example/typeinfo.txt b/test/example/typeinfo.txt index 71e9a3e9c78..95706d5e28b 100644 --- a/test/example/typeinfo.txt +++ b/test/example/typeinfo.txt @@ -1,3 +1,26 @@ +;; Heap types +func +funcref +(ref func) +extern +externref +(ref extern) +any +(ref null any) +(ref any) +eq +(ref null eq) +(ref eq) +i31 +(ref null i31) +(ref i31) +exn +exnref +(ref exn) +(func) +(struct) +(array i32) + ;; Signature (func) (ref (func)) @@ -28,6 +51,26 @@ none (i32 f64 externref) (i32 f64 externref) +;; Rtt +(rtt 0 func) +(rtt 0 func) +(rtt 1 extern) +(rtt 1 extern) +(rtt 2 any) +(rtt 2 any) +(rtt 3 eq) +(rtt 3 eq) +(rtt 4 i31) +(rtt 4 i31) +(rtt 5 exn) +(rtt 5 exn) +(rtt 6 (func)) +(rtt 6 (func)) +(rtt 7 (struct)) +(rtt 7 (struct)) +(rtt 8 (array i32)) +(rtt 8 (array i32)) + ;; Signature of references (param/result) (func (param (ref null (struct))) (result (ref (array (mut i32))))) @@ -63,7 +106,7 @@ none ((ref (func)) (ref null (func)) (ref (struct)) (ref null (struct)) (ref (array i32)) (ref null (array i32))) ((ref (func)) (ref null (func)) (ref (struct)) (ref null (struct)) (ref (array i32)) (ref null (array i32))) -;; Recursive +;; Recursive (not really) (func (param (ref (func)))) (ref (func (param (ref (func))))) (func (param (ref (array (ref (func))))))