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<MarkUnresolvedNonCopyableValueInst *>);
89
91
void checkAddresses ();
90
92
};
91
93
@@ -110,10 +112,75 @@ void MoveOnlyChecker::checkObjects() {
110
112
return ;
111
113
}
112
114
115
+ completeObjectLifetimes (moveIntroducersToProcess.getArrayRef ());
116
+
113
117
MoveOnlyObjectChecker checker{diagnosticEmitter, domTree, poa, allocator};
114
118
madeChange |= checker.check (moveIntroducersToProcess);
115
119
}
116
120
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
+
117
184
void MoveOnlyChecker::checkAddresses () {
118
185
unsigned diagCount = diagnosticEmitter.getDiagnosticCount ();
119
186
SmallSetVector<MarkUnresolvedNonCopyableValueInst *, 32 >
0 commit comments