@@ -857,6 +857,12 @@ struct Struct2Local : PostWalker<Struct2Local> {
857857 }
858858
859859 if (curr->desc ) {
860+ auto descTrap = [&]() {
861+ replaceCurrent (builder.blockify (builder.makeDrop (curr->ref ),
862+ builder.makeDrop (curr->desc ),
863+ builder.makeUnreachable ()));
864+ };
865+
860866 // If we are doing a ref.cast_desc of the optimized allocation, but the
861867 // allocation does not have a descriptor, then we know the cast must fail.
862868 // We also know the cast must fail (except for nulls it might let through)
@@ -888,21 +894,16 @@ struct Struct2Local : PostWalker<Struct2Local> {
888894 } else {
889895 // Either the cast does not allow nulls or we know the value isn't
890896 // null anyway, so the cast certainly fails.
891- replaceCurrent (builder.blockify (builder.makeDrop (curr->ref ),
892- builder.makeDrop (curr->desc ),
893- builder.makeUnreachable ()));
897+ descTrap ();
894898 }
895- } else {
896- assert (allocIsCastRef);
899+ } else if (allocIsCastRef) {
897900 if (!Type::isSubType (allocation->type , curr->type )) {
898901 // The cast fails, so it must trap. We mark such failing casts as
899902 // fully consuming their inputs, so we cannot just emit the explicit
900903 // descriptor equality check below because it would appear to be able
901904 // to propagate the optimized allocation on to the parent (as a null
902905 // value, which might not validate).
903- replaceCurrent (builder.blockify (builder.makeDrop (curr->ref ),
904- builder.makeDrop (curr->desc ),
905- builder.makeUnreachable ()));
906+ descTrap ();
906907 } else {
907908 // The cast succeeds iff the optimized allocation's descriptor is the
908909 // same as the given descriptor and traps otherwise.
@@ -915,6 +916,15 @@ struct Struct2Local : PostWalker<Struct2Local> {
915916 builder.makeRefNull (allocation->type .getHeapType ()),
916917 builder.makeUnreachable ())));
917918 }
919+ } else {
920+ // The allocation is neither the ref nor the descriptor inputs to this
921+ // cast. This can happen if a previous operation led to the StructNew
922+ // being dropped, as a result if it being used in unreachable code (it
923+ // ends up happening because some of the initial analysis, like Parents,
924+ // is stale; we could also recompute Parents after each Struct2Local,
925+ // but it is simple enough to handle this with a trap).
926+ assert (curr->type == Type::unreachable);
927+ descTrap ();
918928 }
919929 } else {
920930 // We know this RefCast receives our allocation, so we can see whether it
0 commit comments