@@ -60,6 +60,11 @@ class OperandOwnershipClassifier
60
60
return getOwnershipKind () == kind;
61
61
}
62
62
63
+ OperandOwnership getBorrowOwnership ();
64
+
65
+ OperandOwnership getFunctionArgOwnership (SILArgumentConvention argConv,
66
+ bool hasCallerScope);
67
+
63
68
OperandOwnership visitFullApply (FullApplySite apply);
64
69
65
70
// Create declarations for all instructions, so we get a warning at compile
@@ -138,7 +143,6 @@ OPERAND_OWNERSHIP(TrivialUse, DebugValueAddr)
138
143
OPERAND_OWNERSHIP(TrivialUse, DeinitExistentialAddr)
139
144
OPERAND_OWNERSHIP(TrivialUse, DestroyAddr)
140
145
OPERAND_OWNERSHIP(TrivialUse, EndAccess)
141
- OPERAND_OWNERSHIP(TrivialUse, EndApply)
142
146
OPERAND_OWNERSHIP(TrivialUse, EndUnpairedAccess)
143
147
OPERAND_OWNERSHIP(TrivialUse, GetAsyncContinuationAddr)
144
148
OPERAND_OWNERSHIP(TrivialUse, IndexAddr)
@@ -216,14 +220,14 @@ OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedAutoreleaseValue)
216
220
OPERAND_OWNERSHIP(PointerEscape, ProjectBox) // The result is a T*.
217
221
OPERAND_OWNERSHIP(PointerEscape, ProjectExistentialBox)
218
222
OPERAND_OWNERSHIP(PointerEscape, UncheckedOwnershipConversion)
223
+ OPERAND_OWNERSHIP(PointerEscape, ConvertEscapeToNoEscape)
219
224
220
225
// Instructions that escape reference bits with unenforced lifetime.
226
+ // TODO: verify that no-escape results are always trivial
221
227
OPERAND_OWNERSHIP(BitwiseEscape, UncheckedBitwiseCast)
222
228
OPERAND_OWNERSHIP(BitwiseEscape, ValueToBridgeObject)
223
229
OPERAND_OWNERSHIP(BitwiseEscape, RefToRawPointer)
224
230
OPERAND_OWNERSHIP(BitwiseEscape, UncheckedTrivialBitCast)
225
- // FIXME: verify that no-escape results are always trivial
226
- OPERAND_OWNERSHIP(BitwiseEscape, ConvertEscapeToNoEscape)
227
231
228
232
// Instructions that end the lifetime of an owned value.
229
233
OPERAND_OWNERSHIP(DestroyingConsume, AutoreleaseValue)
@@ -261,6 +265,7 @@ OPERAND_OWNERSHIP(ForwardingBorrow, OpenExistentialValue)
261
265
OPERAND_OWNERSHIP(ForwardingBorrow, OpenExistentialBoxValue)
262
266
263
267
OPERAND_OWNERSHIP(EndBorrow, EndBorrow)
268
+ OPERAND_OWNERSHIP(EndBorrow, EndApply)
264
269
265
270
#define NEVER_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
266
271
OPERAND_OWNERSHIP (TrivialUse, Load##Name)
@@ -339,10 +344,8 @@ AGGREGATE_OWNERSHIP(UncheckedEnumData)
339
344
AGGREGATE_OWNERSHIP(SwitchEnum)
340
345
#undef AGGREGATE_OWNERSHIP
341
346
342
- // A begin_borrow is conditionally nested.
343
- OperandOwnership
344
- OperandOwnershipClassifier::visitBeginBorrowInst (BeginBorrowInst *borrow) {
345
- switch (borrow->getOperand ().getOwnershipKind ()) {
347
+ OperandOwnership OperandOwnershipClassifier::getBorrowOwnership () {
348
+ switch (getValue ().getOwnershipKind ()) {
346
349
case OwnershipKind::Any:
347
350
llvm_unreachable (" invalid value ownership" );
348
351
case OwnershipKind::None:
@@ -359,6 +362,12 @@ OperandOwnershipClassifier::visitBeginBorrowInst(BeginBorrowInst *borrow) {
359
362
}
360
363
}
361
364
365
+ // A begin_borrow is conditionally nested.
366
+ OperandOwnership
367
+ OperandOwnershipClassifier::visitBeginBorrowInst (BeginBorrowInst *borrow) {
368
+ return getBorrowOwnership ();
369
+ }
370
+
362
371
// MARK: Instructions whose use ownership depends on the operand in question.
363
372
364
373
OperandOwnership OperandOwnershipClassifier::
@@ -399,20 +408,26 @@ OperandOwnershipClassifier::visitStoreBorrowInst(StoreBorrowInst *i) {
399
408
return OperandOwnership::TrivialUse;
400
409
}
401
410
402
- static OperandOwnership getFunctionArgOwnership (SILArgumentConvention argConv) {
411
+ OperandOwnership OperandOwnershipClassifier::getFunctionArgOwnership (
412
+ SILArgumentConvention argConv,
413
+ bool hasCallerScope) {
414
+
403
415
switch (argConv) {
404
416
case SILArgumentConvention::Indirect_In:
405
417
case SILArgumentConvention::Direct_Owned:
406
418
return OperandOwnership::ForwardingConsume;
407
419
408
- // A guaranteed argument is forwarded into the callee. However, from the
420
+ // A guaranteed argument is forwarded into the callee. If the call itself has
421
+ // no scope (i.e. it is a single apply, try_apply or yield), then from the
409
422
// caller's point of view it looks like an instantaneous use. Consequently,
410
423
// owned values may be passed to guaranteed arguments without an explicit
411
- // borrow scope in the caller.
424
+ // borrow scope in the caller. A begin_apply, on the other hand, does have an
425
+ // explicit borrow scope in the caller.
412
426
case SILArgumentConvention::Indirect_In_Constant:
413
427
case SILArgumentConvention::Indirect_In_Guaranteed:
414
428
case SILArgumentConvention::Direct_Guaranteed:
415
- return OperandOwnership::InstantaneousUse;
429
+ return hasCallerScope ? getBorrowOwnership ()
430
+ : OperandOwnership (OperandOwnership::InstantaneousUse);
416
431
417
432
case SILArgumentConvention::Direct_Unowned:
418
433
return OperandOwnership::UnownedInstantaneousUse;
@@ -435,7 +450,8 @@ OperandOwnershipClassifier::visitFullApply(FullApplySite apply) {
435
450
? SILArgumentConvention (apply.getSubstCalleeType ()->getCalleeConvention ())
436
451
: apply.getArgumentConvention (op);
437
452
438
- auto operandOwnership = getFunctionArgOwnership (argConv);
453
+ auto operandOwnership =
454
+ getFunctionArgOwnership (argConv, apply.beginsCoroutineEvaluation ());
439
455
440
456
// Allow passing callee operands with no ownership as guaranteed.
441
457
// FIXME: why do we allow this?
@@ -478,7 +494,7 @@ OperandOwnership OperandOwnershipClassifier::visitYieldInst(YieldInst *i) {
478
494
auto fnType = i->getFunction ()->getLoweredFunctionType ();
479
495
SILArgumentConvention argConv (
480
496
fnType->getYields ()[getOperandIndex ()].getConvention ());
481
- return getFunctionArgOwnership (argConv);
497
+ return getFunctionArgOwnership (argConv, /* hasCallerScope */ false );
482
498
}
483
499
484
500
OperandOwnership OperandOwnershipClassifier::visitReturnInst (ReturnInst *i) {
0 commit comments