@@ -1001,6 +1001,34 @@ void I31Get::finalize() {
1001
1001
}
1002
1002
}
1003
1003
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
+
1004
1032
void CallRef::finalize () {
1005
1033
if (handleUnreachableOperands (this )) {
1006
1034
return ;
@@ -1015,26 +1043,7 @@ void CallRef::finalize() {
1015
1043
}
1016
1044
assert (target->type .isRef ());
1017
1045
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);
1038
1047
return ;
1039
1048
}
1040
1049
assert (target->type .getHeapType ().isSignature ());
@@ -1528,10 +1537,7 @@ void Resume::finalize() {
1528
1537
return ;
1529
1538
}
1530
1539
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);
1535
1541
return ;
1536
1542
}
1537
1543
@@ -1550,10 +1556,7 @@ void ResumeThrow::finalize() {
1550
1556
return ;
1551
1557
}
1552
1558
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);
1557
1560
return ;
1558
1561
}
1559
1562
@@ -1572,10 +1575,7 @@ void StackSwitch::finalize() {
1572
1575
return ;
1573
1576
}
1574
1577
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);
1579
1579
return ;
1580
1580
}
1581
1581
0 commit comments