diff options
-rw-r--r-- | src/wasm-type.h | 19 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 2 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 51 | ||||
-rw-r--r-- | test/example/type-builder-nominal-new.cpp | 463 | ||||
-rw-r--r-- | test/example/type-builder-nominal-new.txt | 94 |
6 files changed, 13 insertions, 620 deletions
diff --git a/src/wasm-type.h b/src/wasm-type.h index c80e7cd0b..7d6306ef7 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -385,22 +385,13 @@ public: Array getArray() const; // If there is a nontrivial (i.e. non-basic) nominal supertype, return it, - // else an empty optional. Nominal types (in the sense of isNominal, - // i.e. Milestone 4 nominal types) may always have supertypes and other types - // may have supertypes in `TypeSystem::Nominal` mode but not in - // `TypeSystem::Equirecursive` mode. + // else an empty optional. 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; - // Whether this is a nominal type in the sense of being a GC Milestone 4 - // nominal type. Although all non-basic HeapTypes are nominal in - // `TypeSystem::Nominal` mode, this will still return false unless the type is - // specifically constructed as a Milestone 4 nominal type. - bool isNominal() const; - constexpr TypeID getID() const { return id; } constexpr BasicHeapType getBasic() const { assert(isBasic() && "Basic heap type expected"); @@ -605,10 +596,6 @@ struct TypeBuilder { // `j`. Does nothing for equirecursive types. void setSubType(size_t i, size_t j); - // Make this type nominal in the sense of the Milestone 4 GC spec, independent - // of the current TypeSystem configuration. - void setNominal(size_t i); - // Returns all of the newly constructed heap types. May only be called once // all of the heap types have been initialized with `setHeapType`. In nominal // mode, all of the constructed HeapTypes will be fresh and distinct. In @@ -647,10 +634,6 @@ struct TypeBuilder { builder.setSubType(index, other.index); return *this; } - Entry& setNominal() { - builder.setNominal(index); - return *this; - } }; Entry operator[](size_t i) { return Entry{*this, i}; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 36cb0fd1a..b20269f9b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -224,7 +224,7 @@ void WasmBinaryWriter::writeTypes() { o << U32LEB(indexedTypes.types.size()); for (Index i = 0; i < indexedTypes.types.size(); ++i) { auto type = indexedTypes.types[i]; - bool nominal = type.isNominal() || getTypeSystem() == TypeSystem::Nominal; + bool nominal = getTypeSystem() == TypeSystem::Nominal; BYN_TRACE("write " << type << std::endl); if (type.isSignature()) { o << S32LEB(nominal ? BinaryConsts::EncodedType::FuncExtending @@ -1962,8 +1962,6 @@ void WasmBinaryBuilder::readTypes() { if (form == BinaryConsts::EncodedType::FuncExtending || form == BinaryConsts::EncodedType::StructExtending || form == BinaryConsts::EncodedType::ArrayExtending) { - // TODO: Let the new nominal types coexist with equirecursive types - // builder[i].setNominal(); auto superIndex = getS64LEB(); // TODO: Actually s33 if (superIndex >= 0) { if (size_t(superIndex) >= numTypes) { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 9a537586e..f76db38af 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -876,8 +876,6 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } Element* super = nullptr; if (nominal) { - // TODO: Let the new nominal types coexist with equirecursive types - // builder[index].setNominal(); super = def[def.size() - 1]; if (super->dollared()) { // OK diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 738cd6e29..fc42fe230 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -105,8 +105,8 @@ struct HeapTypeInfo { // Otherwise, the type definition tree is still being constructed via the // TypeBuilder interface, so hashing and equality use pointer identity. bool isFinalized = true; - bool isNominal = false; - // In nominal mode, the supertype of this HeapType, if it exists. + // In nominal or isorecursive mode, the supertype of this HeapType, if it + // exists. HeapTypeInfo* supertype = nullptr; enum Kind { BasicKind, @@ -581,7 +581,6 @@ bool TypeInfo::operator==(const TypeInfo& other) const { HeapTypeInfo::HeapTypeInfo(const HeapTypeInfo& other) { kind = other.kind; supertype = other.supertype; - isNominal = other.isNominal; switch (kind) { case BasicKind: new (&basic) auto(other.basic); @@ -690,7 +689,7 @@ private: std::lock_guard<std::recursive_mutex> lock(mutex); // Nominal HeapTypes are always unique, so don't bother deduplicating them. if constexpr (std::is_same_v<Info, HeapTypeInfo>) { - if (info.isNominal || typeSystem == TypeSystem::Nominal) { + if (typeSystem == TypeSystem::Nominal) { return insertNew(); } } @@ -1215,14 +1214,6 @@ size_t HeapType::getDepth() const { return depth; } -bool HeapType::isNominal() const { - if (isBasic()) { - return false; - } else { - return getHeapTypeInfo(*this)->isNominal; - } -} - bool HeapType::isSubType(HeapType left, HeapType right) { // As an optimization, in the common case do not even construct a SubTyper. if (left == right) { @@ -1342,11 +1333,7 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { // Basic HeapTypes are never subtypes of compound HeapTypes. return false; } - // Nominal and structural types are never subtypes of each other. - if (a.isNominal() != b.isNominal()) { - return false; - } - if (a.isNominal() || typeSystem == TypeSystem::Nominal) { + if (typeSystem == TypeSystem::Nominal) { // Subtyping must be declared in a nominal system, not derived from // structure, so we will not recurse. TODO: optimize this search with some // form of caching. @@ -1525,9 +1512,6 @@ HeapType TypeBounder::lub(HeapType a, HeapType b) { if (a.isBasic() || b.isBasic()) { return getBasicLUB(); } - if (a.isNominal() != b.isNominal()) { - return getBasicLUB(); - } HeapTypeInfo* infoA = getHeapTypeInfo(a); HeapTypeInfo* infoB = getHeapTypeInfo(b); @@ -1536,7 +1520,7 @@ HeapType TypeBounder::lub(HeapType a, HeapType b) { return getBasicLUB(); } - if (a.isNominal() || typeSystem == TypeSystem::Nominal) { + if (typeSystem == TypeSystem::Nominal) { // Walk up the subtype tree to find the LUB. Ascend the tree from both `a` // and `b` in lockstep. The first type we see for a second time must be the // LUB because there are no cycles and the only way to encounter a type @@ -1971,15 +1955,13 @@ size_t FiniteShapeHasher::hash(const TypeInfo& info) { } size_t FiniteShapeHasher::hash(const HeapTypeInfo& info) { - size_t digest = wasm::hash(info.isNominal); - if (info.isNominal || getTypeSystem() == TypeSystem::Nominal) { - rehash(digest, uintptr_t(&info)); - return digest; + if (getTypeSystem() == TypeSystem::Nominal) { + return wasm::hash(uintptr_t(&info)); } // If the HeapTypeInfo is not finalized, then it is mutable and its shape // might change in the future. In that case, fall back to pointer identity to // keep the hash consistent until all the TypeBuilder's types are finalized. - digest = wasm::hash(info.isFinalized); + size_t digest = wasm::hash(info.isFinalized); if (!info.isFinalized) { rehash(digest, uintptr_t(&info)); return digest; @@ -2094,9 +2076,7 @@ bool FiniteShapeEquator::eq(const TypeInfo& a, const TypeInfo& b) { } bool FiniteShapeEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) { - if (a.isNominal != b.isNominal) { - return false; - } else if (a.isNominal || getTypeSystem() == TypeSystem::Nominal) { + if (getTypeSystem() == TypeSystem::Nominal) { return &a == &b; } if (a.isFinalized != b.isFinalized) { @@ -2264,7 +2244,6 @@ struct TypeBuilder::Impl { } void set(HeapTypeInfo&& hti) { hti.supertype = info->supertype; - hti.isNominal = info->isNominal; *info = std::move(hti); info->isTemp = true; info->isFinalized = false; @@ -2359,11 +2338,6 @@ void TypeBuilder::setSubType(size_t i, size_t j) { sub->supertype = super; } -void TypeBuilder::setNominal(size_t i) { - assert(i < size() && "index out of bounds"); - impl->entries[i].info->isNominal = true; -} - namespace { // Helper for TypeBuilder::build() that keeps track of temporary types and @@ -3036,9 +3010,7 @@ void globallyCanonicalize(CanonicalizationState& state) { void canonicalizeEquirecursive(CanonicalizationState& state) { // Equirecursive types always have null supertypes. for (auto& info : state.newInfos) { - if (!info->isNominal) { - info->supertype = nullptr; - } + info->supertype = nullptr; } #if TIME_CANONICALIZATION @@ -3219,8 +3191,7 @@ std::vector<HeapType> TypeBuilder::build() { // Note built signature types. See comment in `HeapType::HeapType(Signature)`. for (auto type : state.results) { - if (type.isSignature() && - (type.isNominal() || getTypeSystem() == TypeSystem::Nominal)) { + if (type.isSignature() && (getTypeSystem() == TypeSystem::Nominal)) { nominalSignatureCache.insertType(type); } } diff --git a/test/example/type-builder-nominal-new.cpp b/test/example/type-builder-nominal-new.cpp deleted file mode 100644 index a8bef1eca..000000000 --- a/test/example/type-builder-nominal-new.cpp +++ /dev/null @@ -1,463 +0,0 @@ -#include <cassert> -#include <iostream> - -#include "wasm-type.h" - -/* This file is identical to type-builder-nominal.cpp, except that instead of - * setting the global type system to be nominal, it instead individually sets - * each type to be nominal. test_signatures has been removed because the new - * nominal types are never considered canonical, so that test was - * meaningless. */ - -using namespace wasm; - -static void makeNominal(TypeBuilder& builder) { - for (size_t i = 0; i < builder.size(); ++i) { - builder[i].setNominal(); - } -} - -// Construct Signature, Struct, and Array heap types using undefined types. -void test_builder() { - std::cout << ";; Test TypeBuilder\n"; - - // (type $sig (func (param (ref $struct)) (result (ref $array) i32))) - // (type $struct (struct (field (ref null $array) (mut rtt 0 $array)))) - // (type $array (array (mut externref))) - - TypeBuilder builder; - assert(builder.size() == 0); - builder.grow(3); - assert(builder.size() == 3); - - makeNominal(builder); - - Type refSig = builder.getTempRefType(builder[0], NonNullable); - Type refStruct = builder.getTempRefType(builder[1], NonNullable); - Type refArray = builder.getTempRefType(builder[2], NonNullable); - Type refNullArray = builder.getTempRefType(builder[2], Nullable); - Type rttArray = builder.getTempRttType(Rtt(0, builder[2])); - Type refNullExt(HeapType::ext, Nullable); - - Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32})); - Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)}); - Array array(Field(refNullExt, Mutable)); - - std::cout << "Before setting heap types:\n"; - std::cout << "(ref $sig) => " << refSig << "\n"; - std::cout << "(ref $struct) => " << refStruct << "\n"; - std::cout << "(ref $array) => " << refArray << "\n"; - std::cout << "(ref null $array) => " << refNullArray << "\n"; - std::cout << "(rtt 0 $array) => " << rttArray << "\n\n"; - - builder[0] = sig; - builder[1] = struct_; - builder[2] = array; - - std::cout << "After setting heap types:\n"; - std::cout << "(ref $sig) => " << refSig << "\n"; - std::cout << "(ref $struct) => " << refStruct << "\n"; - std::cout << "(ref $array) => " << refArray << "\n"; - std::cout << "(ref null $array) => " << refNullArray << "\n"; - std::cout << "(rtt 0 $array) => " << rttArray << "\n\n"; - - std::vector<HeapType> built = builder.build(); - - Type newRefSig = Type(built[0], NonNullable); - Type newRefStruct = Type(built[1], NonNullable); - Type newRefArray = Type(built[2], NonNullable); - Type newRefNullArray = Type(built[2], Nullable); - Type newRttArray = Type(Rtt(0, built[2])); - - std::cout << "After building types:\n"; - std::cout << "(ref $sig) => " << newRefSig << "\n"; - std::cout << "(ref $struct) => " << newRefStruct << "\n"; - std::cout << "(ref $array) => " << newRefArray << "\n"; - std::cout << "(ref null $array) => " << newRefNullArray << "\n"; - std::cout << "(rtt 0 $array) => " << newRttArray << "\n\n"; -} - -// Check that the builder works when there are duplicate definitions -void test_canonicalization() { - std::cout << ";; Test canonicalization\n"; - - // (type $struct (struct (field (ref null $sig) (ref null $sig)))) - // (type $sig (func)) - HeapType sig = Signature(Type::none, Type::none); - HeapType struct_ = Struct({Field(Type(sig, Nullable), Immutable), - Field(Type(sig, Nullable), Immutable)}); - - TypeBuilder builder(4); - makeNominal(builder); - - Type tempSigRef1 = builder.getTempRefType(builder[2], Nullable); - Type tempSigRef2 = builder.getTempRefType(builder[3], Nullable); - - assert(tempSigRef1 != tempSigRef2); - assert(tempSigRef1 != Type(sig, Nullable)); - assert(tempSigRef2 != Type(sig, Nullable)); - - builder[0] = - Struct({Field(tempSigRef1, Immutable), Field(tempSigRef1, Immutable)}); - builder[1] = - Struct({Field(tempSigRef2, Immutable), Field(tempSigRef2, Immutable)}); - builder[2] = Signature(Type::none, Type::none); - builder[3] = Signature(Type::none, Type::none); - - std::vector<HeapType> built = builder.build(); - - assert(built[0] != struct_); - assert(built[1] != struct_); - assert(built[0] != built[1]); - assert(built[2] != sig); - assert(built[3] != sig); - assert(built[2] != built[3]); -} - -// Check that defined basic HeapTypes are handled correctly. -void test_basic() { - std::cout << ";; Test basic\n"; - - TypeBuilder builder(6); - makeNominal(builder); - - Type anyref = builder.getTempRefType(builder[4], Nullable); - Type i31ref = builder.getTempRefType(builder[5], NonNullable); - - builder[0] = Signature(Type::anyref, Type::i31ref); - builder[1] = Signature(anyref, Type::i31ref); - builder[2] = Signature(Type::anyref, i31ref); - builder[3] = Signature(anyref, i31ref); - builder[4] = HeapType::any; - builder[5] = HeapType::i31; - - std::vector<HeapType> built = builder.build(); - - assert(built[0].getSignature() == Signature(Type::anyref, Type::i31ref)); - assert(built[1].getSignature() == built[0].getSignature()); - assert(built[2].getSignature() == built[1].getSignature()); - assert(built[3].getSignature() == built[2].getSignature()); - assert(built[4] == HeapType::any); - assert(built[5] == HeapType::i31); -} - -void test_recursive() { - std::cout << ";; Test recursive types\n"; - - { - // Trivial recursion - std::vector<HeapType> built; - { - TypeBuilder builder(1); - makeNominal(builder); - - Type temp = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp); - built = builder.build(); - } - std::cout << built[0] << "\n\n"; - assert(built[0] == built[0].getSignature().results.getHeapType()); - assert(Type(built[0], Nullable) == built[0].getSignature().results); - } - - { - // Mutual recursion - std::vector<HeapType> built; - { - TypeBuilder builder(2); - makeNominal(builder); - - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp0); - built = builder.build(); - } - std::cout << built[0] << "\n"; - std::cout << built[1] << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - } - - { - // A longer chain of recursion - std::vector<HeapType> built; - { - TypeBuilder builder(5); - makeNominal(builder); - - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type temp4 = builder.getTempRefType(builder[4], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp2); - builder[2] = Signature(Type::none, temp3); - builder[3] = Signature(Type::none, temp4); - builder[4] = Signature(Type::none, temp0); - built = builder.build(); - } - std::cout << built[0] << "\n"; - std::cout << built[1] << "\n"; - std::cout << built[2] << "\n"; - std::cout << built[3] << "\n"; - std::cout << built[4] << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[2]); - assert(built[2].getSignature().results.getHeapType() == built[3]); - assert(built[3].getSignature().results.getHeapType() == built[4]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - assert(built[0] != built[2]); - assert(built[0] != built[3]); - assert(built[0] != built[4]); - assert(built[1] != built[2]); - assert(built[1] != built[3]); - assert(built[1] != built[4]); - assert(built[2] != built[3]); - assert(built[2] != built[4]); - assert(built[3] != built[4]); - } - - { - // Check canonicalization for non-recursive parents and children of - // recursive HeapTypes. - std::vector<HeapType> built; - { - TypeBuilder builder(6); - makeNominal(builder); - - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type tuple0_2 = builder.getTempTupleType({temp0, temp2}); - Type tuple1_3 = builder.getTempTupleType({temp1, temp3}); - builder[0] = Signature(Type::none, tuple0_2); - builder[1] = Signature(Type::none, tuple1_3); - builder[2] = Signature(); - builder[3] = Signature(); - builder[4] = Signature(Type::none, temp0); - builder[5] = Signature(Type::none, temp1); - built = builder.build(); - } - std::cout << built[0] << "\n"; - std::cout << built[1] << "\n"; - std::cout << built[2] << "\n"; - std::cout << built[3] << "\n"; - std::cout << built[4] << "\n"; - std::cout << built[5] << "\n\n"; - assert(built[0] != built[1]); - assert(built[2] != built[3]); - assert(built[4] != built[5]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[5].getSignature().results.getHeapType() == built[1]); - assert(built[0].getSignature().results == - Type({Type(built[0], Nullable), Type(built[2], Nullable)})); - assert(built[1].getSignature().results == - Type({Type(built[1], Nullable), Type(built[3], Nullable)})); - } - - { - // Folded and unfolded - std::vector<HeapType> built; - { - TypeBuilder builder(2); - makeNominal(builder); - - Type temp0 = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp0); - builder[1] = Signature(Type::none, temp0); - built = builder.build(); - } - std::cout << built[0] << "\n"; - std::cout << built[1] << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[0]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - } -} - -void test_subtypes() { - std::cout << ";; Test subtyping\n"; - - auto LUB = [&](HeapType a, HeapType b) { - Type refA = Type(a, Nullable); - Type refB = Type(b, Nullable); - Type lubAB = Type::getLeastUpperBound(refA, refB); - Type lubBA = Type::getLeastUpperBound(refB, refA); - assert(lubAB == lubBA); - assert(lubAB != Type::none); - HeapType lub = lubAB.getHeapType(); - assert(Type::hasLeastUpperBound(refA, refB)); - assert(Type::hasLeastUpperBound(refB, refA)); - assert(Type::isSubType(refA, lubAB)); - assert(Type::isSubType(refB, lubAB)); - assert(HeapType::isSubType(a, lub)); - assert(HeapType::isSubType(b, lub)); - assert(lub == a || !HeapType::isSubType(lub, a)); - assert(lub == b || !HeapType::isSubType(lub, b)); - return lub; - }; - - { - // Basic Types - for (auto other : {HeapType::func, - HeapType::ext, - HeapType::any, - HeapType::eq, - HeapType::i31, - HeapType::data}) { - assert(LUB(HeapType::any, other) == HeapType::any); - } - assert(LUB(HeapType::eq, HeapType::func) == HeapType::any); - assert(LUB(HeapType::i31, HeapType::data) == HeapType::eq); - } - - { - // Identity - std::vector<HeapType> built; - { - TypeBuilder builder(3); - makeNominal(builder); - - builder[0] = Signature(Type::none, Type::none); - builder[1] = Struct{}; - builder[2] = Array(Field(Type::i32, Mutable)); - built = builder.build(); - } - assert(LUB(built[0], built[0]) == built[0]); - assert(LUB(built[1], built[1]) == built[1]); - assert(LUB(built[2], built[2]) == built[2]); - } - - { - // No subtype declarations mean no subtypes - std::vector<HeapType> built; - { - TypeBuilder builder(5); - makeNominal(builder); - - Type structRef0 = builder.getTempRefType(builder[0], Nullable); - Type structRef1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = Struct{}; - builder[1] = Struct{}; - builder[2] = Signature(Type::none, Type::anyref); - builder[3] = Signature(Type::none, structRef0); - builder[4] = Signature(Type::none, structRef1); - built = builder.build(); - } - assert(LUB(built[0], built[1]) == HeapType::data); - assert(LUB(built[2], built[3]) == HeapType::func); - assert(LUB(built[2], built[4]) == HeapType::func); - } - - { - // Subtype declarations, but still no subtypes - std::vector<HeapType> built; - { - TypeBuilder builder(3); - makeNominal(builder); - - builder[0].subTypeOf(builder[1]); - builder[0] = Struct{}; - builder[1] = Struct{}; - builder[2] = Struct{}; - built = builder.build(); - } - assert(LUB(built[0], built[2]) == HeapType::data); - } - - { - // Subtyping of identical types - std::vector<HeapType> built; - { - TypeBuilder builder(6); - makeNominal(builder); - - builder[0].subTypeOf(builder[1]); - builder[2].subTypeOf(builder[3]); - builder[4].subTypeOf(builder[5]); - builder[0] = - Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)}); - builder[1] = - Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)}); - builder[2] = Signature(Type::i32, Type::anyref); - builder[3] = Signature(Type::i32, Type::anyref); - builder[4] = Array(Field(Type::i32, Mutable)); - builder[5] = Array(Field(Type::i32, Mutable)); - built = builder.build(); - } - assert(LUB(built[0], built[1]) == built[1]); - assert(LUB(built[2], built[3]) == built[3]); - assert(LUB(built[4], built[5]) == built[5]); - } - - { - // Width subtyping - std::vector<HeapType> built; - { - TypeBuilder builder(2); - makeNominal(builder); - - builder[0] = Struct({Field(Type::i32, Immutable)}); - builder[1] = - Struct({Field(Type::i32, Immutable), Field(Type::i32, Immutable)}); - builder[1].subTypeOf(builder[0]); - built = builder.build(); - } - assert(LUB(built[1], built[0]) == built[0]); - } - - { - // Depth subtyping - std::vector<HeapType> built; - { - TypeBuilder builder(2); - makeNominal(builder); - - builder[0] = Struct({Field(Type::anyref, Immutable)}); - builder[1] = Struct({Field(Type::funcref, Immutable)}); - builder[1].subTypeOf(builder[0]); - built = builder.build(); - } - assert(LUB(built[1], built[0]) == built[0]); - } - - { - // Mutually recursive subtyping - std::vector<HeapType> built; - { - TypeBuilder builder(4); - makeNominal(builder); - - Type a = builder.getTempRefType(builder[0], Nullable); - Type b = builder.getTempRefType(builder[1], Nullable); - Type c = builder.getTempRefType(builder[2], Nullable); - Type d = builder.getTempRefType(builder[3], Nullable); - builder[1].subTypeOf(builder[0]); - builder[3].subTypeOf(builder[2]); - builder[0] = Struct({Field(c, Immutable)}); - builder[1] = Struct({Field(d, Immutable)}); - builder[2] = Struct({Field(a, Immutable)}); - builder[3] = Struct({Field(b, Immutable)}); - built = builder.build(); - } - assert(LUB(built[0], built[1]) == built[0]); - assert(LUB(built[2], built[3]) == built[2]); - } -} - -int main() { - // Run the tests twice to ensure things still work when the global stores are - // already populated. - for (size_t i = 0; i < 2; ++i) { - test_builder(); - test_canonicalization(); - test_basic(); - test_recursive(); - test_subtypes(); - } -} diff --git a/test/example/type-builder-nominal-new.txt b/test/example/type-builder-nominal-new.txt deleted file mode 100644 index 6f0218e54..000000000 --- a/test/example/type-builder-nominal-new.txt +++ /dev/null @@ -1,94 +0,0 @@ -;; Test TypeBuilder -Before setting heap types: -(ref $sig) => [T](ref [T](func)) -(ref $struct) => [T](ref [T](func)) -(ref $array) => [T](ref [T](func)) -(ref null $array) => [T](ref null [T](func)) -(rtt 0 $array) => [T](rtt 0 [T](func)) - -After setting heap types: -(ref $sig) => [T](ref [T](func (param [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))) (result [T](ref [T](array (mut externref))) i32))) -(ref $struct) => [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref))))))) -(ref $array) => [T](ref [T](array (mut externref))) -(ref null $array) => [T](ref null [T](array (mut externref))) -(rtt 0 $array) => [T](rtt 0 [T](array (mut externref))) - -After building types: -(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32))) -(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref))))))) -(ref $array) => (ref (array (mut externref))) -(ref null $array) => (ref null (array (mut externref))) -(rtt 0 $array) => (rtt 0 (array (mut externref))) - -;; Test canonicalization -;; Test basic -;; Test recursive types -(func (result (ref null ...1))) - -(func (result (ref null (func (result (ref null ...3)))))) -(func (result (ref null (func (result (ref null ...3)))))) - -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) - -(func (result (ref null ...1) (ref null (func)))) -(func (result (ref null ...1) (ref null (func)))) -(func) -(func) -(func (result (ref null (func (result ...1 (ref null (func))))))) -(func (result (ref null (func (result ...1 (ref null (func))))))) - -(func (result (ref null ...1))) -(func (result (ref null (func (result ...1))))) - -;; Test subtyping -;; Test TypeBuilder -Before setting heap types: -(ref $sig) => [T](ref [T](func)) -(ref $struct) => [T](ref [T](func)) -(ref $array) => [T](ref [T](func)) -(ref null $array) => [T](ref null [T](func)) -(rtt 0 $array) => [T](rtt 0 [T](func)) - -After setting heap types: -(ref $sig) => [T](ref [T](func (param [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))) (result [T](ref [T](array (mut externref))) i32))) -(ref $struct) => [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref))))))) -(ref $array) => [T](ref [T](array (mut externref))) -(ref null $array) => [T](ref null [T](array (mut externref))) -(rtt 0 $array) => [T](rtt 0 [T](array (mut externref))) - -After building types: -(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32))) -(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref))))))) -(ref $array) => (ref (array (mut externref))) -(ref null $array) => (ref null (array (mut externref))) -(rtt 0 $array) => (rtt 0 (array (mut externref))) - -;; Test canonicalization -;; Test basic -;; Test recursive types -(func (result (ref null ...1))) - -(func (result (ref null (func (result (ref null ...3)))))) -(func (result (ref null (func (result (ref null ...3)))))) - -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) -(func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null (func (result (ref null ...9))))))))))))))) - -(func (result (ref null ...1) (ref null (func)))) -(func (result (ref null ...1) (ref null (func)))) -(func) -(func) -(func (result (ref null (func (result ...1 (ref null (func))))))) -(func (result (ref null (func (result ...1 (ref null (func))))))) - -(func (result (ref null ...1))) -(func (result (ref null (func (result ...1))))) - -;; Test subtyping |