@@ -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+
10041032void 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