[region-isolation] When assigning RValues into memory, use tuple_addr_constructor instead of doing it in pieces.

I also included changes to the rest of the SIL optimizer pipeline to ensure that
the part of the optimizer pipeline before we lower tuple_addr_constructor (which
is right after we run TransferNonSendable) work as before.

The reason why I am doing this is that this ensures that diagnostic passes can
tell the difference in between:

```
x = (a, b, c)
```

and

```
x.0 = a
x.1 = b
x.2 = c
```

This is important for things like TransferNonSendable where assigning over the
entire tuple element is treated differently from if one were to initialize it in
pieces using projections.

rdar://117880194
This commit is contained in:
Michael Gottesman
2023-11-05 19:17:46 -08:00
parent d2b5bc33a1
commit b1f69030fc
19 changed files with 425 additions and 78 deletions

View File

@@ -2529,6 +2529,30 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) {
return;
}
if (auto *TACI = dyn_cast<TupleAddrConstructorInst>(Inst)) {
assert(!TACI->isInitializationOfDest() &&
"should not modify copy_addr that already knows it is initialized");
TACI->setIsInitializationOfDest(InitKind);
if (InitKind == IsInitialization)
setStaticInitAccess(TACI->getDest());
// If we had an initialization and had an assignable_but_not_consumable
// noncopyable type, convert it to be an initable_but_not_consumable so that
// we do not consume an uninitialized value.
if (InitKind == IsInitialization) {
if (auto *mmci = dyn_cast<MarkUnresolvedNonCopyableValueInst>(
stripAccessMarkers(TACI->getDest()))) {
if (mmci->getCheckKind() == MarkUnresolvedNonCopyableValueInst::
CheckKind::AssignableButNotConsumable) {
mmci->setCheckKind(MarkUnresolvedNonCopyableValueInst::CheckKind::
InitableButNotConsumable);
}
}
}
return;
}
// Ignore non-stores for SelfInits.
assert(isa<StoreInst>(Inst) && "Unknown store instruction!");
}