Skip to content

Commit f9b7876

Browse files
authored
Update finalization for exact references (#7353)
Update the finalization of all instructions whose types (or sent types) depend on their operand reference types to handle exact references correctly. Specifically, update `ref.as_non_null`, `br_on_null`, `br_on_non_null`, `br_on_cast`, and `br_on_cast_fail`. Also add TODOs on all instructions that allocate new heap objects to remind us to make their types exact in the future.
1 parent a4966d7 commit f9b7876

File tree

2 files changed

+304
-35
lines changed

2 files changed

+304
-35
lines changed

src/wasm/wasm.cpp

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,7 @@ void MemoryGrow::finalize() {
800800

801801
void RefNull::finalize(HeapType heapType) {
802802
assert(heapType.isBottom());
803+
// TODO: Make this exact.
803804
type = Type(heapType, Nullable);
804805
}
805806

@@ -922,6 +923,7 @@ static void populateTryTableSentTypes(TryTable* curr, Module* wasm) {
922923
// wasm spec defines when GC is enabled (=== non-nullable types are allowed).
923924
// If GC is not enabled then we emit a nullable type in the binary format in
924925
// WasmBinaryWriter::writeType.
926+
// TODO: Make this exact.
925927
Type exnref = Type(HeapType::exn, NonNullable);
926928
for (Index i = 0; i < curr->catchTags.size(); i++) {
927929
auto tagName = curr->catchTags[i];
@@ -976,6 +978,7 @@ void RefI31::finalize() {
976978
if (value->type == Type::unreachable) {
977979
type = Type::unreachable;
978980
} else {
981+
// TODO: Make this exact.
979982
assert(type.isRef() && type.getHeapType().isMaybeShared(HeapType::i31));
980983
}
981984
}
@@ -1011,10 +1014,12 @@ void CallRef::finalize() {
10111014
// unreachable instead (and similar in other GC accessors), although this
10121015
// would currently cause the parser to admit more invalid modules.
10131016
if (type.isRef()) {
1017+
// TODO: Make this exact.
10141018
type = Type(type.getHeapType().getBottom(), NonNullable);
10151019
} else if (type.isTuple()) {
10161020
Tuple elems;
10171021
for (auto t : type) {
1022+
// TODO: Make this exact.
10181023
elems.push_back(
10191024
t.isRef() ? Type(t.getHeapType().getBottom(), NonNullable) : t);
10201025
}
@@ -1071,7 +1076,8 @@ void BrOn::finalize() {
10711076
switch (op) {
10721077
case BrOnNull:
10731078
// If we do not branch, we flow out the existing value as non-null.
1074-
type = Type(ref->type.getHeapType(), NonNullable);
1079+
type =
1080+
Type(ref->type.getHeapType(), NonNullable, ref->type.getExactness());
10751081
break;
10761082
case BrOnNonNull:
10771083
// If we do not branch, we flow out nothing (the spec could also have had
@@ -1081,7 +1087,8 @@ void BrOn::finalize() {
10811087
case BrOnCast:
10821088
if (castType.isNullable()) {
10831089
// Nulls take the branch, so the result is non-nullable.
1084-
type = Type(ref->type.getHeapType(), NonNullable);
1090+
type =
1091+
Type(ref->type.getHeapType(), NonNullable, ref->type.getExactness());
10851092
} else {
10861093
// Nulls do not take the branch, so the result is non-nullable only if
10871094
// the input is.
@@ -1092,7 +1099,9 @@ void BrOn::finalize() {
10921099
if (castType.isNullable()) {
10931100
// Nulls do not take the branch, so the result is non-nullable only if
10941101
// the input is.
1095-
type = Type(castType.getHeapType(), ref->type.getNullability());
1102+
type = Type(castType.getHeapType(),
1103+
ref->type.getNullability(),
1104+
castType.getExactness());
10961105
} else {
10971106
// Nulls take the branch, so the result is non-nullable.
10981107
type = castType;
@@ -1115,11 +1124,14 @@ Type BrOn::getSentType() {
11151124
return Type::unreachable;
11161125
}
11171126
// BrOnNonNull sends the non-nullable type on the branch.
1118-
return Type(ref->type.getHeapType(), NonNullable);
1127+
return Type(
1128+
ref->type.getHeapType(), NonNullable, ref->type.getExactness());
11191129
case BrOnCast:
11201130
// The same as the result type of br_on_cast_fail.
11211131
if (castType.isNullable()) {
1122-
return Type(castType.getHeapType(), ref->type.getNullability());
1132+
return Type(castType.getHeapType(),
1133+
ref->type.getNullability(),
1134+
castType.getExactness());
11231135
} else {
11241136
return castType;
11251137
}
@@ -1129,7 +1141,8 @@ Type BrOn::getSentType() {
11291141
return Type::unreachable;
11301142
}
11311143
if (castType.isNullable()) {
1132-
return Type(ref->type.getHeapType(), NonNullable);
1144+
return Type(
1145+
ref->type.getHeapType(), NonNullable, ref->type.getExactness());
11331146
} else {
11341147
return ref->type;
11351148
}
@@ -1150,6 +1163,7 @@ void StructGet::finalize() {
11501163
} else if (ref->type.isNull()) {
11511164
// See comment on CallRef for explanation.
11521165
if (type.isRef()) {
1166+
// TODO: Make this exact.
11531167
type = Type(type.getHeapType().getBottom(), NonNullable);
11541168
}
11551169
} else {
@@ -1225,6 +1239,7 @@ void ArrayGet::finalize() {
12251239
} else if (ref->type.isNull()) {
12261240
// See comment on CallRef for explanation.
12271241
if (type.isRef()) {
1242+
// TODO: Make this exact.
12281243
type = Type(type.getHeapType().getBottom(), NonNullable);
12291244
}
12301245
} else {
@@ -1302,15 +1317,17 @@ void RefAs::finalize() {
13021317
auto valHeapType = value->type.getHeapType();
13031318
switch (op) {
13041319
case RefAsNonNull:
1305-
type = Type(valHeapType, NonNullable);
1320+
type = Type(valHeapType, NonNullable, value->type.getExactness());
13061321
break;
13071322
case AnyConvertExtern:
13081323
type = Type(HeapTypes::any.getBasic(valHeapType.getShared()),
1309-
value->type.getNullability());
1324+
value->type.getNullability(),
1325+
Inexact);
13101326
break;
13111327
case ExternConvertAny:
13121328
type = Type(HeapTypes::ext.getBasic(valHeapType.getShared()),
1313-
value->type.getNullability());
1329+
value->type.getNullability(),
1330+
Inexact);
13141331
break;
13151332
default:
13161333
WASM_UNREACHABLE("invalid ref.as_*");
@@ -1323,11 +1340,15 @@ void StringNew::finalize() {
13231340
(end && end->type == Type::unreachable)) {
13241341
type = Type::unreachable;
13251342
} else {
1343+
// TODO: Make this exact.
13261344
type = Type(HeapType::string, NonNullable);
13271345
}
13281346
}
13291347

1330-
void StringConst::finalize() { type = Type(HeapType::string, NonNullable); }
1348+
void StringConst::finalize() {
1349+
// TODO: Make this exact.
1350+
type = Type(HeapType::string, NonNullable);
1351+
}
13311352

13321353
void StringMeasure::finalize() {
13331354
if (ref->type == Type::unreachable) {
@@ -1350,6 +1371,7 @@ void StringConcat::finalize() {
13501371
if (left->type == Type::unreachable || right->type == Type::unreachable) {
13511372
type = Type::unreachable;
13521373
} else {
1374+
// TODO: Make this exact.
13531375
type = Type(HeapType::string, NonNullable);
13541376
}
13551377
}
@@ -1375,6 +1397,7 @@ void StringSliceWTF::finalize() {
13751397
end->type == Type::unreachable) {
13761398
type = Type::unreachable;
13771399
} else {
1400+
// TODO: Make this exact.
13781401
type = Type(HeapType::string, NonNullable);
13791402
}
13801403
}

0 commit comments

Comments
 (0)