@@ -188,6 +188,103 @@ bool swift::findInnerTransitiveGuaranteedUses(
188188 return true ;
189189}
190190
191+ // / Like findInnerTransitiveGuaranteedUses except that rather than it being a
192+ // / precondition that the provided value not be a BorrowedValue, it is a [type-
193+ // / system-enforced] precondition that the provided value be a BorrowedValue.
194+ // /
195+ // / TODO: Merge with findInnerTransitiveGuaranteedUses. Note that at the moment
196+ // / the two are _almost_ identical, but not quite because the other has a
197+ // / #if 0 and not just leaf uses but ALL uses are recorded.
198+ bool swift::findInnerTransitiveGuaranteedUsesOfBorrowedValue (
199+ BorrowedValue borrowedValue, SmallVectorImpl<Operand *> *usePoints) {
200+
201+ auto recordUse = [&](Operand *use) {
202+ if (usePoints && use->getOperandOwnership () != OperandOwnership::NonUse) {
203+ usePoints->push_back (use);
204+ }
205+ };
206+
207+ // Push the value's immediate uses.
208+ //
209+ // TODO: The worklist can be a simple vector without any a membership check if
210+ // destructures are changed to be represented as reborrows. Currently a
211+ // destructure forwards multiple results! This means that the worklist could
212+ // grow exponentially without the membership check. It's fine to do this
213+ // membership check locally in this function (within a borrow scope) because
214+ // it isn't needed for the immediate uses, only the transitive uses.
215+ GraphNodeWorklist<Operand *, 8 > worklist;
216+ for (Operand *use : borrowedValue.value ->getUses ()) {
217+ if (use->getOperandOwnership () != OperandOwnership::NonUse)
218+ worklist.insert (use);
219+ }
220+
221+ // --- Transitively follow forwarded uses and look for escapes.
222+
223+ // usePoints grows in this loop.
224+ while (Operand *use = worklist.pop ()) {
225+ switch (use->getOperandOwnership ()) {
226+ case OperandOwnership::NonUse:
227+ case OperandOwnership::TrivialUse:
228+ case OperandOwnership::ForwardingConsume:
229+ case OperandOwnership::DestroyingConsume:
230+ llvm_unreachable (" this operand cannot handle an inner guaranteed use" );
231+
232+ case OperandOwnership::ForwardingUnowned:
233+ case OperandOwnership::PointerEscape:
234+ return false ;
235+
236+ case OperandOwnership::InstantaneousUse:
237+ case OperandOwnership::UnownedInstantaneousUse:
238+ case OperandOwnership::BitwiseEscape:
239+ // Reborrow only happens when this is called on a value that creates a
240+ // borrow scope.
241+ case OperandOwnership::Reborrow:
242+ // EndBorrow either happens when this is called on a value that creates a
243+ // borrow scope, or when it is pushed as a use when processing a nested
244+ // borrow.
245+ case OperandOwnership::EndBorrow:
246+ recordUse (use);
247+ break ;
248+
249+ case OperandOwnership::InteriorPointer:
250+ if (InteriorPointerOperandKind::get (use) ==
251+ InteriorPointerOperandKind::Invalid)
252+ return false ;
253+ // If our base guaranteed value does not have any consuming uses (consider
254+ // function arguments), we need to be sure to include interior pointer
255+ // operands since we may not get a use from a end_scope instruction.
256+ if (InteriorPointerOperand (use).findTransitiveUses (usePoints) !=
257+ AddressUseKind::NonEscaping) {
258+ return false ;
259+ }
260+ break ;
261+
262+ case OperandOwnership::ForwardingBorrow: {
263+ ForwardingOperand (use).visitForwardedValues ([&](SILValue result) {
264+ // Do not include transitive uses with 'none' ownership
265+ if (result.getOwnershipKind () == OwnershipKind::None)
266+ return true ;
267+ for (auto *resultUse : result->getUses ()) {
268+ if (resultUse->getOperandOwnership () != OperandOwnership::NonUse) {
269+ worklist.insert (resultUse);
270+ }
271+ }
272+ return true ;
273+ });
274+ recordUse (use);
275+ break ;
276+ }
277+ case OperandOwnership::Borrow:
278+ BorrowingOperand (use).visitExtendedScopeEndingUses ([&](Operand *endUse) {
279+ recordUse (endUse);
280+ return true ;
281+ });
282+ break ;
283+ }
284+ }
285+ return true ;
286+ }
287+
191288// Find all use points of \p guaranteedValue within its borrow scope. All use
192289// points will be dominated by \p guaranteedValue.
193290//
0 commit comments