3030#include " swift/SIL/FieldSensitivePrunedLiveness.h"
3131#include " swift/SIL/InstructionUtils.h"
3232#include " swift/SIL/MemAccessUtils.h"
33+ #include " swift/SIL/OSSALifetimeCompletion.h"
3334#include " swift/SIL/OwnershipUtils.h"
3435#include " swift/SIL/PrunedLiveness.h"
3536#include " swift/SIL/SILArgument.h"
@@ -86,6 +87,7 @@ struct MoveOnlyChecker {
8687 }
8788
8889 void checkObjects ();
90+ void completeObjectLifetimes (ArrayRef<MarkUnresolvedNonCopyableValueInst *>);
8991 void checkAddresses ();
9092};
9193
@@ -110,10 +112,75 @@ void MoveOnlyChecker::checkObjects() {
110112 return ;
111113 }
112114
115+ completeObjectLifetimes (moveIntroducersToProcess.getArrayRef ());
116+
113117 MoveOnlyObjectChecker checker{diagnosticEmitter, domTree, poa, allocator};
114118 madeChange |= checker.check (moveIntroducersToProcess);
115119}
116120
121+ void MoveOnlyChecker::completeObjectLifetimes (
122+ ArrayRef<MarkUnresolvedNonCopyableValueInst *> insts) {
123+ // TODO: Delete once OSSALifetimeCompletion is run as part of SILGenCleanup.
124+ OSSALifetimeCompletion completion (fn, domTree);
125+
126+ // Collect all values derived from each mark_unresolved_non_copyable_value
127+ // instruction via ownership instructions and phis.
128+ ValueWorklist transitiveValues (fn);
129+ for (auto *inst : insts) {
130+ transitiveValues.push (inst);
131+ }
132+ while (auto value = transitiveValues.pop ()) {
133+ for (auto *use : value->getUses ()) {
134+ auto *user = use->getUser ();
135+ switch (user->getKind ()) {
136+ case SILInstructionKind::BeginBorrowInst:
137+ case SILInstructionKind::CopyValueInst:
138+ case SILInstructionKind::MoveValueInst:
139+ transitiveValues.pushIfNotVisited (cast<SingleValueInstruction>(user));
140+ break ;
141+ case SILInstructionKind::BranchInst: {
142+ PhiOperand po (use);
143+ transitiveValues.pushIfNotVisited (po.getValue ());
144+ break ;
145+ }
146+ default : {
147+ auto forward = ForwardingOperation (user);
148+ if (!forward)
149+ continue ;
150+ forward.visitForwardedValues ([&transitiveValues](auto forwarded) {
151+ transitiveValues.pushIfNotVisited (forwarded);
152+ return true ;
153+ });
154+ break ;
155+ }
156+ }
157+ }
158+ }
159+ // Complete the lifetime of each collected value. This is a subset of the
160+ // work that SILGenCleanup will do.
161+ for (auto *block : poa->get (fn)->getPostOrder ()) {
162+ for (SILInstruction &inst : reverse (*block)) {
163+ for (auto result : inst.getResults ()) {
164+ if (!transitiveValues.isVisited (result))
165+ continue ;
166+ if (completion.completeOSSALifetime (result) ==
167+ LifetimeCompletion::WasCompleted) {
168+ madeChange = true ;
169+ }
170+ }
171+ }
172+ for (SILArgument *arg : block->getArguments ()) {
173+ assert (!arg->isReborrow () && " reborrows not legal at this SIL stage" );
174+ if (!transitiveValues.isVisited (arg))
175+ continue ;
176+ if (completion.completeOSSALifetime (arg) ==
177+ LifetimeCompletion::WasCompleted) {
178+ madeChange = true ;
179+ }
180+ }
181+ }
182+ }
183+
117184void MoveOnlyChecker::checkAddresses () {
118185 unsigned diagCount = diagnosticEmitter.getDiagnosticCount ();
119186 SmallSetVector<MarkUnresolvedNonCopyableValueInst *, 32 >
0 commit comments