30
30
#include " swift/SIL/FieldSensitivePrunedLiveness.h"
31
31
#include " swift/SIL/InstructionUtils.h"
32
32
#include " swift/SIL/MemAccessUtils.h"
33
+ #include " swift/SIL/OSSALifetimeCompletion.h"
33
34
#include " swift/SIL/OwnershipUtils.h"
34
35
#include " swift/SIL/PrunedLiveness.h"
35
36
#include " swift/SIL/SILArgument.h"
@@ -86,6 +87,7 @@ struct MoveOnlyChecker {
86
87
}
87
88
88
89
void checkObjects ();
90
+ void completeObjectLifetimes (ArrayRef<MarkMustCheckInst *>);
89
91
void checkAddresses ();
90
92
};
91
93
@@ -109,10 +111,75 @@ void MoveOnlyChecker::checkObjects() {
109
111
return ;
110
112
}
111
113
114
+ completeObjectLifetimes (moveIntroducersToProcess.getArrayRef ());
115
+
112
116
MoveOnlyObjectChecker checker{diagnosticEmitter, domTree, poa, allocator};
113
117
madeChange |= checker.check (moveIntroducersToProcess);
114
118
}
115
119
120
+ void MoveOnlyChecker::completeObjectLifetimes (
121
+ ArrayRef<MarkMustCheckInst *> insts) {
122
+ // TODO: Delete once OSSALifetimeCompletion is run as part of SILGenCleanup.
123
+ OSSALifetimeCompletion completion (fn, domTree);
124
+
125
+ // Collect all values derived from each mark_unresolved_non_copyable_value
126
+ // instruction via ownership instructions and phis.
127
+ ValueWorklist transitiveValues (fn);
128
+ for (auto *inst : insts) {
129
+ transitiveValues.push (inst);
130
+ }
131
+ while (auto value = transitiveValues.pop ()) {
132
+ for (auto *use : value->getUses ()) {
133
+ auto *user = use->getUser ();
134
+ switch (user->getKind ()) {
135
+ case SILInstructionKind::BeginBorrowInst:
136
+ case SILInstructionKind::CopyValueInst:
137
+ case SILInstructionKind::MoveValueInst:
138
+ transitiveValues.pushIfNotVisited (cast<SingleValueInstruction>(user));
139
+ break ;
140
+ case SILInstructionKind::BranchInst: {
141
+ PhiOperand po (use);
142
+ transitiveValues.pushIfNotVisited (po.getValue ());
143
+ break ;
144
+ }
145
+ default : {
146
+ auto *forward = OwnershipForwardingMixin::get (user);
147
+ if (!forward)
148
+ continue ;
149
+ OwnershipForwardingMixin::visitForwardedValues (
150
+ user, [&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
+ if (!transitiveValues.isVisited (arg))
174
+ continue ;
175
+ if (completion.completeOSSALifetime (arg) ==
176
+ LifetimeCompletion::WasCompleted) {
177
+ madeChange = true ;
178
+ }
179
+ }
180
+ }
181
+ }
182
+
116
183
void MoveOnlyChecker::checkAddresses () {
117
184
unsigned diagCount = diagnosticEmitter.getDiagnosticCount ();
118
185
SmallSetVector<MarkMustCheckInst *, 32 > moveIntroducersToProcess;
0 commit comments