summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/module-utils.h54
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-type.h3
-rw-r--r--src/wasm/wasm-binary.cpp271
-rw-r--r--src/wasm/wasm-type.cpp1
-rw-r--r--test/heap-types.wast.from-wast12
-rw-r--r--test/heap-types.wast.fromBinary12
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo12
-rw-r--r--test/lit/forward-declared-types.wast4
-rw-r--r--test/passes/O_all-features_ignore-implicit-traps.txt2
-rw-r--r--test/typed-function-references.wast.from-wast4
-rw-r--r--test/typed-function-references.wast.fromBinary2
-rw-r--r--test/typed-function-references.wast.fromBinary.noDebugInfo2
13 files changed, 216 insertions, 167 deletions
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 29ebcc2b5..84ef3a508 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -433,10 +433,7 @@ inline void collectHeapTypes(Module& wasm,
std::unordered_map<HeapType, Index>& typeIndices) {
struct Counts : public std::unordered_map<HeapType, size_t> {
bool isRelevant(Type type) {
- if (type.isRef()) {
- return !type.getHeapType().isBasic();
- }
- return type.isRtt();
+ return (type.isRef() || type.isRtt()) && !type.getHeapType().isBasic();
}
void note(HeapType type) { (*this)[type]++; }
void maybeNote(Type type) {
@@ -469,10 +466,11 @@ inline void collectHeapTypes(Module& wasm,
} else if (auto* set = curr->dynCast<StructSet>()) {
counts.maybeNote(set->ref->type);
} else if (Properties::isControlFlowStructure(curr)) {
- counts.maybeNote(curr->type);
if (curr->type.isTuple()) {
// TODO: Allow control flow to have input types as well
counts.note(Signature(Type::none, curr->type));
+ } else {
+ counts.maybeNote(curr->type);
}
}
}
@@ -509,8 +507,7 @@ inline void collectHeapTypes(Module& wasm,
}
// A generic utility to traverse the child types of a type.
// TODO: work with tlively to refactor this to a shared place
- auto walkRelevantChildren = [&](HeapType type,
- std::function<void(HeapType)> callback) {
+ auto walkRelevantChildren = [&](HeapType type, auto callback) {
auto callIfRelevant = [&](Type type) {
if (counts.isRelevant(type)) {
callback(type.getHeapType());
@@ -538,7 +535,6 @@ inline void collectHeapTypes(Module& wasm,
// As we do this we may find more and more types, as nested children of
// previous ones. Each such type will appear in the type section once, so
// we just need to visit it once.
- // TODO: handle struct and array fields
std::unordered_set<HeapType> newTypes;
for (auto& pair : counts) {
newTypes.insert(pair.first);
@@ -555,49 +551,9 @@ inline void collectHeapTypes(Module& wasm,
});
}
- // We must sort all the dependencies of a type before it. For example,
- // (func (param (ref (func)))) must appear after (func). To do that, find the
- // depth of dependencies of each type. For example, if A depends on B
- // which depends on C, then A's depth is 2, B's is 1, and C's is 0 (assuming
- // no other dependencies).
- Counts depthOfDependencies;
- std::unordered_map<HeapType, std::unordered_set<HeapType>> isDependencyOf;
- // To calculate the depth of dependencies, we'll do a flow analysis, visiting
- // each type as we find out new things about it.
- std::set<HeapType> toVisit;
- for (auto& pair : counts) {
- auto type = pair.first;
- depthOfDependencies[type] = 0;
- toVisit.insert(type);
- walkRelevantChildren(type, [&](HeapType childType) {
- isDependencyOf[childType].insert(type); // XXX flip?
- });
- }
- while (!toVisit.empty()) {
- auto iter = toVisit.begin();
- auto type = *iter;
- toVisit.erase(iter);
- // Anything that depends on this has a depth of dependencies equal to this
- // type's, plus this type itself.
- auto newDepth = depthOfDependencies[type] + 1;
- if (newDepth > counts.size()) {
- Fatal() << "Cyclic types detected, cannot sort them.";
- }
- for (auto& other : isDependencyOf[type]) {
- if (depthOfDependencies[other] < newDepth) {
- // We found something new to propagate.
- depthOfDependencies[other] = newDepth;
- toVisit.insert(other);
- }
- }
- }
- // Sort by frequency and then simplicity, and also keeping every type
- // before things that depend on it.
+ // Sort by frequency and then simplicity.
std::vector<std::pair<HeapType, size_t>> sorted(counts.begin(), counts.end());
std::sort(sorted.begin(), sorted.end(), [&](auto a, auto b) {
- if (depthOfDependencies[a.first] != depthOfDependencies[b.first]) {
- return depthOfDependencies[a.first] < depthOfDependencies[b.first];
- }
if (a.second != b.second) {
return a.second > b.second;
}
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 99305acb2..3f76a4421 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1322,14 +1322,14 @@ public:
int64_t getS64LEB();
uint64_t getUPtrLEB();
+ bool getBasicType(int32_t code, Type& out);
+ bool getBasicHeapType(int64_t code, HeapType& out);
// Read a value and get a type for it.
Type getType();
// Get a type given the initial S32LEB has already been read, and is provided.
Type getType(int initial);
HeapType getHeapType();
- Mutability getMutability();
- Field getField();
Type getConcreteType();
Name getInlineString();
void verifyInt8(int8_t x);
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 4188c438d..b61fe68a6 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -315,6 +315,9 @@ public:
// 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) {}
+
HeapType(Signature signature);
HeapType(const Struct& struct_);
HeapType(Struct&& struct_);
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 730129892..49d7128dd 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1444,45 +1444,91 @@ uint64_t WasmBinaryBuilder::getUPtrLEB() {
return wasm.memory.is64() ? getU64LEB() : getU32LEB();
}
+bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) {
+ switch (code) {
+ case BinaryConsts::EncodedType::i32:
+ out = Type::i32;
+ return true;
+ case BinaryConsts::EncodedType::i64:
+ out = Type::i64;
+ return true;
+ case BinaryConsts::EncodedType::f32:
+ out = Type::f32;
+ return true;
+ case BinaryConsts::EncodedType::f64:
+ out = Type::f64;
+ return true;
+ case BinaryConsts::EncodedType::v128:
+ out = Type::v128;
+ return true;
+ case BinaryConsts::EncodedType::funcref:
+ out = Type::funcref;
+ return true;
+ case BinaryConsts::EncodedType::externref:
+ out = Type::externref;
+ return true;
+ case BinaryConsts::EncodedType::anyref:
+ out = Type::anyref;
+ return true;
+ case BinaryConsts::EncodedType::eqref:
+ out = Type::eqref;
+ return true;
+ case BinaryConsts::EncodedType::i31ref:
+ // FIXME: for now, force all inputs to be nullable
+ out = Type(HeapType::i31, Nullable);
+ return true;
+ case BinaryConsts::EncodedType::dataref:
+ // FIXME: for now, force all inputs to be nullable
+ out = Type(HeapType::data, Nullable);
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool WasmBinaryBuilder::getBasicHeapType(int64_t code, HeapType& out) {
+ switch (code) {
+ case BinaryConsts::EncodedHeapType::func:
+ out = HeapType::func;
+ return true;
+ case BinaryConsts::EncodedHeapType::extern_:
+ out = HeapType::ext;
+ return true;
+ case BinaryConsts::EncodedHeapType::any:
+ out = HeapType::any;
+ return true;
+ case BinaryConsts::EncodedHeapType::eq:
+ out = HeapType::eq;
+ return true;
+ case BinaryConsts::EncodedHeapType::i31:
+ out = HeapType::i31;
+ return true;
+ case BinaryConsts::EncodedHeapType::data:
+ out = HeapType::data;
+ return true;
+ default:
+ return false;
+ }
+}
+
Type WasmBinaryBuilder::getType(int initial) {
// Single value types are negative; signature indices are non-negative
if (initial >= 0) {
// TODO: Handle block input types properly.
return getSignatureByTypeIndex(initial).results;
}
+ Type type;
+ if (getBasicType(initial, type)) {
+ return type;
+ }
switch (initial) {
// None only used for block signatures. TODO: Separate out?
case BinaryConsts::EncodedType::Empty:
return Type::none;
- case BinaryConsts::EncodedType::i32:
- return Type::i32;
- case BinaryConsts::EncodedType::i64:
- return Type::i64;
- case BinaryConsts::EncodedType::f32:
- return Type::f32;
- case BinaryConsts::EncodedType::f64:
- return Type::f64;
- case BinaryConsts::EncodedType::v128:
- return Type::v128;
- case BinaryConsts::EncodedType::funcref:
- return Type::funcref;
- case BinaryConsts::EncodedType::externref:
- return Type::externref;
- case BinaryConsts::EncodedType::anyref:
- return Type::anyref;
- case BinaryConsts::EncodedType::eqref:
- return Type::eqref;
case BinaryConsts::EncodedType::nullable:
- return Type(getHeapType(), Nullable);
case BinaryConsts::EncodedType::nonnullable:
// FIXME: for now, force all inputs to be nullable
return Type(getHeapType(), Nullable);
- case BinaryConsts::EncodedType::i31ref:
- // FIXME: for now, force all inputs to be nullable
- return Type(HeapType::BasicHeapType::i31, Nullable);
- case BinaryConsts::EncodedType::dataref:
- // FIXME: for now, force all inputs to be nullable
- return Type(HeapType::BasicHeapType::data, Nullable);
case BinaryConsts::EncodedType::rtt_n: {
auto depth = getU32LEB();
auto heapType = getHeapType();
@@ -1508,54 +1554,15 @@ HeapType WasmBinaryBuilder::getHeapType() {
}
return types[type];
}
- switch (type) {
- case BinaryConsts::EncodedHeapType::func:
- return HeapType::func;
- case BinaryConsts::EncodedHeapType::extern_:
- return HeapType::ext;
- case BinaryConsts::EncodedHeapType::any:
- return HeapType::any;
- case BinaryConsts::EncodedHeapType::eq:
- return HeapType::eq;
- case BinaryConsts::EncodedHeapType::i31:
- return HeapType::i31;
- case BinaryConsts::EncodedHeapType::data:
- return HeapType::data;
- default:
- throwError("invalid wasm heap type: " + std::to_string(type));
+ HeapType ht;
+ if (getBasicHeapType(type, ht)) {
+ return ht;
+ } else {
+ throwError("invalid wasm heap type: " + std::to_string(type));
}
WASM_UNREACHABLE("unexpected type");
}
-Mutability WasmBinaryBuilder::getMutability() {
- switch (getU32LEB()) {
- case 0:
- return Immutable;
- case 1:
- return Mutable;
- default:
- throw ParseException("Expected 0 or 1 for mutability");
- }
-}
-
-Field WasmBinaryBuilder::getField() {
- // The value may be a general wasm type, or one of the types only possible in
- // a field.
- auto initial = getS32LEB();
- if (initial == BinaryConsts::EncodedType::i8) {
- auto mutable_ = getMutability();
- return Field(Field::i8, mutable_);
- }
- if (initial == BinaryConsts::EncodedType::i16) {
- auto mutable_ = getMutability();
- return Field(Field::i16, mutable_);
- }
- // It's a regular wasm value.
- auto type = getType(initial);
- auto mutable_ = getMutability();
- return Field(type, mutable_);
-}
-
Type WasmBinaryBuilder::getConcreteType() {
auto type = getType();
if (!type.isConcrete()) {
@@ -1643,37 +1650,121 @@ void WasmBinaryBuilder::readTypes() {
BYN_TRACE("== readTypes\n");
size_t numTypes = getU32LEB();
BYN_TRACE("num: " << numTypes << std::endl);
+ TypeBuilder builder(numTypes);
+
+ auto makeType = [&](int32_t typeCode) {
+ Type type;
+ if (getBasicType(typeCode, type)) {
+ return type;
+ }
+
+ switch (typeCode) {
+ case BinaryConsts::EncodedType::nullable:
+ case BinaryConsts::EncodedType::nonnullable: {
+ // FIXME: for now, force all inputs to be nullable
+ int64_t htCode = getS64LEB(); // TODO: Actually s33
+ HeapType ht;
+ if (getBasicHeapType(htCode, ht)) {
+ return Type(ht, Nullable);
+ }
+ if (size_t(htCode) >= numTypes) {
+ throwError("invalid type index: " + std::to_string(htCode));
+ }
+ return builder.getTempRefType(size_t(htCode), Nullable);
+ }
+ case BinaryConsts::EncodedType::rtt_n:
+ case BinaryConsts::EncodedType::rtt: {
+ auto depth = typeCode == BinaryConsts::EncodedType::rtt ? Rtt::NoDepth
+ : getU32LEB();
+ int64_t htCode = getS64LEB(); // TODO: Actually s33
+ HeapType ht;
+ if (getBasicHeapType(htCode, ht)) {
+ return Type(Rtt(depth, ht));
+ }
+ if (size_t(htCode) >= numTypes) {
+ throwError("invalid type index: " + std::to_string(htCode));
+ }
+ return builder.getTempRttType(htCode, depth);
+ }
+ default:
+ throwError("unexpected type index: " + std::to_string(typeCode));
+ }
+ WASM_UNREACHABLE("unexpected type");
+ };
+
+ auto readType = [&]() { return makeType(getS32LEB()); };
+
+ auto readSignatureDef = [&]() {
+ std::vector<Type> params;
+ std::vector<Type> results;
+ size_t numParams = getU32LEB();
+ BYN_TRACE("num params: " << numParams << std::endl);
+ for (size_t j = 0; j < numParams; j++) {
+ params.push_back(readType());
+ }
+ auto numResults = getU32LEB();
+ BYN_TRACE("num results: " << numResults << std::endl);
+ for (size_t j = 0; j < numResults; j++) {
+ results.push_back(readType());
+ }
+ return Signature(builder.getTempTupleType(params),
+ builder.getTempTupleType(results));
+ };
+
+ auto readMutability = [&]() {
+ switch (getU32LEB()) {
+ case 0:
+ return Immutable;
+ case 1:
+ return Mutable;
+ default:
+ throw ParseException("Expected 0 or 1 for mutability");
+ }
+ };
+
+ auto readFieldDef = [&]() {
+ // The value may be a general wasm type, or one of the types only possible
+ // in a field.
+ auto typeCode = getS32LEB();
+ if (typeCode == BinaryConsts::EncodedType::i8) {
+ auto mutable_ = readMutability();
+ return Field(Field::i8, mutable_);
+ }
+ if (typeCode == BinaryConsts::EncodedType::i16) {
+ auto mutable_ = readMutability();
+ return Field(Field::i16, mutable_);
+ }
+ // It's a regular wasm value.
+ auto type = makeType(typeCode);
+ auto mutable_ = readMutability();
+ return Field(type, mutable_);
+ };
+
+ auto readStructDef = [&]() {
+ FieldList fields;
+ size_t numFields = getU32LEB();
+ BYN_TRACE("num fields: " << numFields << std::endl);
+ for (size_t j = 0; j < numFields; j++) {
+ fields.push_back(readFieldDef());
+ }
+ return Struct(std::move(fields));
+ };
+
for (size_t i = 0; i < numTypes; i++) {
BYN_TRACE("read one\n");
auto form = getS32LEB();
if (form == BinaryConsts::EncodedType::Func) {
- std::vector<Type> params;
- std::vector<Type> results;
- size_t numParams = getU32LEB();
- BYN_TRACE("num params: " << numParams << std::endl);
- for (size_t j = 0; j < numParams; j++) {
- params.push_back(getConcreteType());
- }
- auto numResults = getU32LEB();
- BYN_TRACE("num results: " << numResults << std::endl);
- for (size_t j = 0; j < numResults; j++) {
- results.push_back(getConcreteType());
- }
- types.emplace_back(Signature(Type(params), Type(results)));
+ builder.setHeapType(i, readSignatureDef());
} else if (form == BinaryConsts::EncodedType::Struct) {
- FieldList fields;
- size_t numFields = getU32LEB();
- BYN_TRACE("num fields: " << numFields << std::endl);
- for (size_t j = 0; j < numFields; j++) {
- fields.push_back(getField());
- }
- types.emplace_back(Struct(fields));
+ builder.setHeapType(i, readStructDef());
} else if (form == BinaryConsts::EncodedType::Array) {
- types.emplace_back(Array(getField()));
+ builder.setHeapType(i, Array(readFieldDef()));
} else {
throwError("bad type form " + std::to_string(form));
}
}
+
+ types = builder.build();
}
Name WasmBinaryBuilder::getFunctionName(Index index) {
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 87dd2b289..4936bc3ff 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -1304,7 +1304,6 @@ void Canonicalizer::makeAncestorsFixedPoint() {
std::vector<Canonicalizer::Item> Canonicalizer::getOrderedItems() {
// Topologically sort the Types and HeapTypes so that all children are
// canonicalized before their parents.
-
std::vector<TypeID> sorted;
std::unordered_set<TypeID> seen;
diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast
index 458842a7b..d45e5c37c 100644
--- a/test/heap-types.wast.from-wast
+++ b/test/heap-types.wast.from-wast
@@ -1,20 +1,20 @@
(module
(type ${i32_f32_f64} (struct (field i32) (field f32) (field f64)))
+ (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64})))))
+ (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64])))
(type $[mut:f64] (array (mut f64)))
(type $anyref_=>_none (func (param anyref)))
(type ${} (struct ))
(type ${mut:f32} (struct (field (mut f32))))
(type $none_=>_none (func))
- (type ${i32} (struct (field i32)))
- (type ${i32_i64} (struct (field i32) (field i64)))
- (type $[mut:i32] (array (mut i32)))
- (type $[mut:i8] (array (mut i8)))
- (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64})))))
- (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64])))
(type $rtt_1_${}_=>_none (func (param (rtt 1 ${}))))
(type $rtt_${}_=>_none (func (param (rtt ${}))))
(type $ref?|{i32_f32_f64}|_=>_ref?|{i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}| (func (param (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}))))
(type $ref?|[mut:f64]|_=>_ref?|[ref?|[mut:f64]|]| (func (param (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|]))))
+ (type ${i32} (struct (field i32)))
+ (type ${i32_i64} (struct (field i32) (field i64)))
+ (type $[mut:i32] (array (mut i32)))
+ (type $[mut:i8] (array (mut i8)))
(global $rttparent (rtt 0 ${}) (rtt.canon ${}))
(global $rttchild (rtt 1 ${i32}) (rtt.sub ${i32}
(global.get $rttparent)
diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary
index 5e48da116..303038693 100644
--- a/test/heap-types.wast.fromBinary
+++ b/test/heap-types.wast.fromBinary
@@ -1,20 +1,20 @@
(module
(type ${i32_f32_f64} (struct (field i32) (field f32) (field f64)))
+ (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64})))))
+ (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64])))
(type $[mut:f64] (array (mut f64)))
(type $anyref_=>_none (func (param anyref)))
(type ${} (struct ))
(type ${mut:f32} (struct (field (mut f32))))
(type $none_=>_none (func))
- (type ${i32} (struct (field i32)))
- (type ${i32_i64} (struct (field i32) (field i64)))
- (type $[mut:i32] (array (mut i32)))
- (type $[mut:i8] (array (mut i8)))
- (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64})))))
- (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64])))
(type $rtt_1_${}_=>_none (func (param (rtt 1 ${}))))
(type $rtt_${}_=>_none (func (param (rtt ${}))))
(type $ref?|{i32_f32_f64}|_=>_ref?|{i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}| (func (param (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}))))
(type $ref?|[mut:f64]|_=>_ref?|[ref?|[mut:f64]|]| (func (param (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|]))))
+ (type ${i32} (struct (field i32)))
+ (type ${i32_i64} (struct (field i32) (field i64)))
+ (type $[mut:i32] (array (mut i32)))
+ (type $[mut:i8] (array (mut i8)))
(global $rttparent (rtt 0 ${}) (rtt.canon ${}))
(global $rttchild (rtt 1 ${i32}) (rtt.sub ${i32}
(global.get $rttparent)
diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo
index d49d5fa1e..1ae5792cb 100644
--- a/test/heap-types.wast.fromBinary.noDebugInfo
+++ b/test/heap-types.wast.fromBinary.noDebugInfo
@@ -1,20 +1,20 @@
(module
(type ${i32_f32_f64} (struct (field i32) (field f32) (field f64)))
+ (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64})))))
+ (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64])))
(type $[mut:f64] (array (mut f64)))
(type $anyref_=>_none (func (param anyref)))
(type ${} (struct ))
(type ${mut:f32} (struct (field (mut f32))))
(type $none_=>_none (func))
- (type ${i32} (struct (field i32)))
- (type ${i32_i64} (struct (field i32) (field i64)))
- (type $[mut:i32] (array (mut i32)))
- (type $[mut:i8] (array (mut i8)))
- (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64})))))
- (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64])))
(type $rtt_1_${}_=>_none (func (param (rtt 1 ${}))))
(type $rtt_${}_=>_none (func (param (rtt ${}))))
(type $ref?|{i32_f32_f64}|_=>_ref?|{i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}| (func (param (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}))))
(type $ref?|[mut:f64]|_=>_ref?|[ref?|[mut:f64]|]| (func (param (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|]))))
+ (type ${i32} (struct (field i32)))
+ (type ${i32_i64} (struct (field i32) (field i64)))
+ (type $[mut:i32] (array (mut i32)))
+ (type $[mut:i8] (array (mut i8)))
(global $global$0 (rtt 0 ${}) (rtt.canon ${}))
(global $global$1 (rtt 1 ${i32}) (rtt.sub ${i32}
(global.get $global$0)
diff --git a/test/lit/forward-declared-types.wast b/test/lit/forward-declared-types.wast
index e9b66175b..002e7ceb3 100644
--- a/test/lit/forward-declared-types.wast
+++ b/test/lit/forward-declared-types.wast
@@ -3,9 +3,9 @@
;; RUN: wasm-opt %s -all -S -o - | filecheck %s
;; CHECK: (type $none_=>_none (func))
-;; CHECK: (type $[rtt_2_$none_=>_none] (array (rtt 2 $none_=>_none)))
-;; CHECK: (type ${ref?|[rtt_2_$none_=>_none]|_ref?|none_->_none|} (struct (field (ref null $[rtt_2_$none_=>_none])) (field (ref null $none_=>_none))))
;; CHECK: (type $none_=>_ref?|{ref?|[rtt_2_$none_=>_none]|_ref?|none_->_none|}| (func (result (ref null ${ref?|[rtt_2_$none_=>_none]|_ref?|none_->_none|}))))
+;; CHECK: (type ${ref?|[rtt_2_$none_=>_none]|_ref?|none_->_none|} (struct (field (ref null $[rtt_2_$none_=>_none])) (field (ref null $none_=>_none))))
+;; CHECK: (type $[rtt_2_$none_=>_none] (array (rtt 2 $none_=>_none)))
(module
(type $struct (struct
diff --git a/test/passes/O_all-features_ignore-implicit-traps.txt b/test/passes/O_all-features_ignore-implicit-traps.txt
index 8e57a2e4b..993bd10e5 100644
--- a/test/passes/O_all-features_ignore-implicit-traps.txt
+++ b/test/passes/O_all-features_ignore-implicit-traps.txt
@@ -1,6 +1,6 @@
(module
- (type ${i32} (struct (field i32)))
(type $ref?|{i32}|_=>_none (func (param (ref null ${i32}))))
+ (type ${i32} (struct (field i32)))
(export "foo" (func $0))
(func $0 (; has Stack IR ;) (param $0 (ref null ${i32}))
(nop)
diff --git a/test/typed-function-references.wast.from-wast b/test/typed-function-references.wast.from-wast
index a31eeecea..dde689fa0 100644
--- a/test/typed-function-references.wast.from-wast
+++ b/test/typed-function-references.wast.from-wast
@@ -1,12 +1,12 @@
(module
(type $none_=>_none (func))
(type $i32_=>_i32 (func (param i32) (result i32)))
+ (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32)))
(type $none_=>_eqref (func (result eqref)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_anyref (func (result anyref)))
- (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32)))
- (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32)))
(type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64)))
+ (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32)))
(type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref))))
(func $call-ref
(call_ref
diff --git a/test/typed-function-references.wast.fromBinary b/test/typed-function-references.wast.fromBinary
index 0e4385c84..fb13b73c4 100644
--- a/test/typed-function-references.wast.fromBinary
+++ b/test/typed-function-references.wast.fromBinary
@@ -2,10 +2,10 @@
(type $none_=>_none (func))
(type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
+ (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32)))
(type $none_=>_eqref (func (result eqref)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_anyref (func (result anyref)))
- (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32)))
(type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64)))
(type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref))))
(func $call-ref
diff --git a/test/typed-function-references.wast.fromBinary.noDebugInfo b/test/typed-function-references.wast.fromBinary.noDebugInfo
index ad50ea1f7..7d09438df 100644
--- a/test/typed-function-references.wast.fromBinary.noDebugInfo
+++ b/test/typed-function-references.wast.fromBinary.noDebugInfo
@@ -2,10 +2,10 @@
(type $none_=>_none (func))
(type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
+ (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32)))
(type $none_=>_eqref (func (result eqref)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_anyref (func (result anyref)))
- (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32)))
(type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64)))
(type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref))))
(func $0