summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm-type.h19
-rw-r--r--src/wasm/wasm-binary.cpp4
-rw-r--r--src/wasm/wasm-s-parser.cpp2
-rw-r--r--src/wasm/wasm-type.cpp51
-rw-r--r--test/example/type-builder-nominal-new.cpp463
-rw-r--r--test/example/type-builder-nominal-new.txt94
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