Skip to content

Commit 1866114

Browse files
authored
[Stack Switching] Handle null children consistently as in call_ref (#7794)
1 parent f6d887e commit 1866114

File tree

1 file changed

+32
-32
lines changed

1 file changed

+32
-32
lines changed

src/wasm/wasm.cpp

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,34 @@ void I31Get::finalize() {
10011001
}
10021002
}
10031003

1004+
// If an instruction depends on a child for its type, for example call_ref
1005+
// whose type should be the return values of the function signature in its
1006+
// target, then we must handle the case of the child being null. In that case,
1007+
// we can't read signature information from the child, but it doesn't matter, as
1008+
// the call will trap anyhow. We could update the type to be unreachable, but
1009+
// that would violate the invariant that non-branch instructions other than
1010+
// `unreachable` can only be unreachable if they have unreachable children. This
1011+
// makes the result type as close to `unreachable` as possible without
1012+
// actually making it unreachable. TODO: consider just making this
1013+
// unreachable instead (and similar in other GC accessors), although this
1014+
// would currently cause the parser to admit more invalid modules.
1015+
static Type getMaximallyUninhabitable(Type type) {
1016+
if (type.isRef()) {
1017+
// We can make a reference uninhabitable.
1018+
return Type(type.getHeapType().getBottom(), NonNullable);
1019+
} else if (type.isTuple()) {
1020+
// We can make a tuple's elements uninhabitable.
1021+
Tuple elems;
1022+
for (auto t : type) {
1023+
elems.push_back(t.isRef() ? Type(t.getHeapType().getBottom(), NonNullable)
1024+
: t);
1025+
}
1026+
return Type(elems);
1027+
}
1028+
// Other things can be left as is.
1029+
return type;
1030+
}
1031+
10041032
void CallRef::finalize() {
10051033
if (handleUnreachableOperands(this)) {
10061034
return;
@@ -1015,26 +1043,7 @@ void CallRef::finalize() {
10151043
}
10161044
assert(target->type.isRef());
10171045
if (target->type.isNull()) {
1018-
// If this call_ref has been optimized to have a null reference, then it
1019-
// will definitely trap. We could update the type to be unreachable, but
1020-
// that would violate the invariant that non-branch instructions other than
1021-
// `unreachable` can only be unreachable if they have unreachable children.
1022-
// Make the result type as close to `unreachable` as possible without
1023-
// actually making it unreachable. TODO: consider just making this
1024-
// unreachable instead (and similar in other GC accessors), although this
1025-
// would currently cause the parser to admit more invalid modules.
1026-
if (type.isRef()) {
1027-
// TODO: Make this exact.
1028-
type = Type(type.getHeapType().getBottom(), NonNullable);
1029-
} else if (type.isTuple()) {
1030-
Tuple elems;
1031-
for (auto t : type) {
1032-
// TODO: Make this exact.
1033-
elems.push_back(
1034-
t.isRef() ? Type(t.getHeapType().getBottom(), NonNullable) : t);
1035-
}
1036-
type = Type(elems);
1037-
}
1046+
type = getMaximallyUninhabitable(type);
10381047
return;
10391048
}
10401049
assert(target->type.getHeapType().isSignature());
@@ -1528,10 +1537,7 @@ void Resume::finalize() {
15281537
return;
15291538
}
15301539
if (cont->type.isNull()) {
1531-
// This will never be executed and the instruction will not be emitted.
1532-
// Model this with an uninhabitable cast type.
1533-
// TODO: This is not quite right yet.
1534-
type = cont->type.with(NonNullable);
1540+
type = getMaximallyUninhabitable(type);
15351541
return;
15361542
}
15371543

@@ -1550,10 +1556,7 @@ void ResumeThrow::finalize() {
15501556
return;
15511557
}
15521558
if (cont->type.isNull()) {
1553-
// This will never be executed and the instruction will not be emitted.
1554-
// Model this with an uninhabitable cast type.
1555-
// TODO: This is not quite right yet.
1556-
type = cont->type.with(NonNullable);
1559+
type = getMaximallyUninhabitable(type);
15571560
return;
15581561
}
15591562

@@ -1572,10 +1575,7 @@ void StackSwitch::finalize() {
15721575
return;
15731576
}
15741577
if (cont->type.isNull()) {
1575-
// This will never be executed and the instruction will not be emitted.
1576-
// Model this with an uninhabitable cast type.
1577-
// TODO: This is not quite right yet.
1578-
type = cont->type.with(NonNullable);
1578+
type = getMaximallyUninhabitable(type);
15791579
return;
15801580
}
15811581

0 commit comments

Comments
 (0)