Skip to content

Commit 3f59a7d

Browse files
authored
[NFC] Add type.with(...) API to update reference types (#7359)
There are many places where we have to copy a reference type with some modification, for example to make it refer to a different heap type or to make it non-nullable or nullable. Previously the only way to do this was with the `Type` constructor, retrieving and passing in the unmodified fields of the old type explicitly. With the addition of exact types, all of these sites have to be updated to additionally propagate the old type's exactness. To simplify these call sites and make them more robust against future additions to the structure of reference types, introduce new APIs to update just a single part of a reference type at a time.
1 parent 626e212 commit 3f59a7d

File tree

4 files changed

+21
-21
lines changed

4 files changed

+21
-21
lines changed

src/ir/type-updating.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,7 @@ void GlobalTypeRewriter::mapTypes(const TypeMap& oldToNewTypes) {
205205

206206
Type getNew(Type type) {
207207
if (type.isRef()) {
208-
return Type(getNew(type.getHeapType()),
209-
type.getNullability(),
210-
type.getExactness());
208+
return type.with(getNew(type.getHeapType()));
211209
}
212210
if (type.isTuple()) {
213211
auto tuple = type.getTuple();
@@ -467,7 +465,7 @@ void handleNonDefaultableLocals(Function* func, Module& wasm) {
467465
Type getValidLocalType(Type type, FeatureSet features) {
468466
assert(type.isConcrete());
469467
if (type.isNonNullable()) {
470-
return Type(type.getHeapType(), Nullable, type.getExactness());
468+
return type.with(Nullable);
471469
}
472470
if (type.isTuple()) {
473471
std::vector<Type> elems(type.size());

src/passes/LocalSubtyping.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,7 @@ struct LocalSubtyping : public WalkerPass<PostWalker<LocalSubtyping>> {
152152
// Remove non-nullability if we disallow that in locals.
153153
if (newType.isNonNullable()) {
154154
if (cannotBeNonNullable.count(i)) {
155-
newType =
156-
Type(newType.getHeapType(), Nullable, newType.getExactness());
155+
newType = newType.with(Nullable);
157156
}
158157
} else if (!newType.isDefaultable()) {
159158
// Aside from the case we just handled of allowed non-nullability, we

src/wasm-type.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,17 @@ class Type {
398398
return isExact() ? Exact : Inexact;
399399
}
400400

401+
// Return a new reference type with some part updated to the specified value.
402+
Type with(HeapType heapType) {
403+
return Type(heapType, getNullability(), getExactness());
404+
}
405+
Type with(Nullability nullability) {
406+
return Type(getHeapType(), nullability, getExactness());
407+
}
408+
Type with(Exactness exactness) {
409+
return Type(getHeapType(), getNullability(), exactness);
410+
}
411+
401412
private:
402413
template<bool (Type::*pred)() const> bool hasPredicate() {
403414
for (const auto& type : *this) {

src/wasm/wasm.cpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,8 +1076,7 @@ void BrOn::finalize() {
10761076
switch (op) {
10771077
case BrOnNull:
10781078
// If we do not branch, we flow out the existing value as non-null.
1079-
type =
1080-
Type(ref->type.getHeapType(), NonNullable, ref->type.getExactness());
1079+
type = ref->type.with(NonNullable);
10811080
break;
10821081
case BrOnNonNull:
10831082
// If we do not branch, we flow out nothing (the spec could also have had
@@ -1087,8 +1086,7 @@ void BrOn::finalize() {
10871086
case BrOnCast:
10881087
if (castType.isNullable()) {
10891088
// Nulls take the branch, so the result is non-nullable.
1090-
type =
1091-
Type(ref->type.getHeapType(), NonNullable, ref->type.getExactness());
1089+
type = ref->type.with(NonNullable);
10921090
} else {
10931091
// Nulls do not take the branch, so the result is non-nullable only if
10941092
// the input is.
@@ -1099,9 +1097,7 @@ void BrOn::finalize() {
10991097
if (castType.isNullable()) {
11001098
// Nulls do not take the branch, so the result is non-nullable only if
11011099
// the input is.
1102-
type = Type(castType.getHeapType(),
1103-
ref->type.getNullability(),
1104-
castType.getExactness());
1100+
type = castType.with(ref->type.getNullability());
11051101
} else {
11061102
// Nulls take the branch, so the result is non-nullable.
11071103
type = castType;
@@ -1124,14 +1120,11 @@ Type BrOn::getSentType() {
11241120
return Type::unreachable;
11251121
}
11261122
// BrOnNonNull sends the non-nullable type on the branch.
1127-
return Type(
1128-
ref->type.getHeapType(), NonNullable, ref->type.getExactness());
1123+
return ref->type.with(NonNullable);
11291124
case BrOnCast:
11301125
// The same as the result type of br_on_cast_fail.
11311126
if (castType.isNullable()) {
1132-
return Type(castType.getHeapType(),
1133-
ref->type.getNullability(),
1134-
castType.getExactness());
1127+
return castType.with(ref->type.getNullability());
11351128
} else {
11361129
return castType;
11371130
}
@@ -1141,8 +1134,7 @@ Type BrOn::getSentType() {
11411134
return Type::unreachable;
11421135
}
11431136
if (castType.isNullable()) {
1144-
return Type(
1145-
ref->type.getHeapType(), NonNullable, ref->type.getExactness());
1137+
return ref->type.with(NonNullable);
11461138
} else {
11471139
return ref->type;
11481140
}
@@ -1317,7 +1309,7 @@ void RefAs::finalize() {
13171309
auto valHeapType = value->type.getHeapType();
13181310
switch (op) {
13191311
case RefAsNonNull:
1320-
type = Type(valHeapType, NonNullable, value->type.getExactness());
1312+
type = value->type.with(NonNullable);
13211313
break;
13221314
case AnyConvertExtern:
13231315
type = Type(HeapTypes::any.getBasic(valHeapType.getShared()),

0 commit comments

Comments
 (0)