Skip to content

Commit e5a4b6b

Browse files
committed
Fix OperandOwnership for end_apply and convert_escape_to_noescape
1 parent 034b440 commit e5a4b6b

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ class OperandOwnershipClassifier
6060
return getOwnershipKind() == kind;
6161
}
6262

63+
OperandOwnership getBorrowOwnership();
64+
65+
OperandOwnership getFunctionArgOwnership(SILArgumentConvention argConv,
66+
bool hasCallerScope);
67+
6368
OperandOwnership visitFullApply(FullApplySite apply);
6469

6570
// Create declarations for all instructions, so we get a warning at compile
@@ -138,7 +143,6 @@ OPERAND_OWNERSHIP(TrivialUse, DebugValueAddr)
138143
OPERAND_OWNERSHIP(TrivialUse, DeinitExistentialAddr)
139144
OPERAND_OWNERSHIP(TrivialUse, DestroyAddr)
140145
OPERAND_OWNERSHIP(TrivialUse, EndAccess)
141-
OPERAND_OWNERSHIP(TrivialUse, EndApply)
142146
OPERAND_OWNERSHIP(TrivialUse, EndUnpairedAccess)
143147
OPERAND_OWNERSHIP(TrivialUse, GetAsyncContinuationAddr)
144148
OPERAND_OWNERSHIP(TrivialUse, IndexAddr)
@@ -216,14 +220,14 @@ OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedAutoreleaseValue)
216220
OPERAND_OWNERSHIP(PointerEscape, ProjectBox) // The result is a T*.
217221
OPERAND_OWNERSHIP(PointerEscape, ProjectExistentialBox)
218222
OPERAND_OWNERSHIP(PointerEscape, UncheckedOwnershipConversion)
223+
OPERAND_OWNERSHIP(PointerEscape, ConvertEscapeToNoEscape)
219224

220225
// Instructions that escape reference bits with unenforced lifetime.
226+
// TODO: verify that no-escape results are always trivial
221227
OPERAND_OWNERSHIP(BitwiseEscape, UncheckedBitwiseCast)
222228
OPERAND_OWNERSHIP(BitwiseEscape, ValueToBridgeObject)
223229
OPERAND_OWNERSHIP(BitwiseEscape, RefToRawPointer)
224230
OPERAND_OWNERSHIP(BitwiseEscape, UncheckedTrivialBitCast)
225-
// FIXME: verify that no-escape results are always trivial
226-
OPERAND_OWNERSHIP(BitwiseEscape, ConvertEscapeToNoEscape)
227231

228232
// Instructions that end the lifetime of an owned value.
229233
OPERAND_OWNERSHIP(DestroyingConsume, AutoreleaseValue)
@@ -261,6 +265,7 @@ OPERAND_OWNERSHIP(ForwardingBorrow, OpenExistentialValue)
261265
OPERAND_OWNERSHIP(ForwardingBorrow, OpenExistentialBoxValue)
262266

263267
OPERAND_OWNERSHIP(EndBorrow, EndBorrow)
268+
OPERAND_OWNERSHIP(EndBorrow, EndApply)
264269

265270
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
266271
OPERAND_OWNERSHIP(TrivialUse, Load##Name)
@@ -339,10 +344,8 @@ AGGREGATE_OWNERSHIP(UncheckedEnumData)
339344
AGGREGATE_OWNERSHIP(SwitchEnum)
340345
#undef AGGREGATE_OWNERSHIP
341346

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()) {
346349
case OwnershipKind::Any:
347350
llvm_unreachable("invalid value ownership");
348351
case OwnershipKind::None:
@@ -359,6 +362,12 @@ OperandOwnershipClassifier::visitBeginBorrowInst(BeginBorrowInst *borrow) {
359362
}
360363
}
361364

365+
// A begin_borrow is conditionally nested.
366+
OperandOwnership
367+
OperandOwnershipClassifier::visitBeginBorrowInst(BeginBorrowInst *borrow) {
368+
return getBorrowOwnership();
369+
}
370+
362371
// MARK: Instructions whose use ownership depends on the operand in question.
363372

364373
OperandOwnership OperandOwnershipClassifier::
@@ -399,20 +408,26 @@ OperandOwnershipClassifier::visitStoreBorrowInst(StoreBorrowInst *i) {
399408
return OperandOwnership::TrivialUse;
400409
}
401410

402-
static OperandOwnership getFunctionArgOwnership(SILArgumentConvention argConv) {
411+
OperandOwnership OperandOwnershipClassifier::getFunctionArgOwnership(
412+
SILArgumentConvention argConv,
413+
bool hasCallerScope) {
414+
403415
switch (argConv) {
404416
case SILArgumentConvention::Indirect_In:
405417
case SILArgumentConvention::Direct_Owned:
406418
return OperandOwnership::ForwardingConsume;
407419

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
409422
// caller's point of view it looks like an instantaneous use. Consequently,
410423
// 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.
412426
case SILArgumentConvention::Indirect_In_Constant:
413427
case SILArgumentConvention::Indirect_In_Guaranteed:
414428
case SILArgumentConvention::Direct_Guaranteed:
415-
return OperandOwnership::InstantaneousUse;
429+
return hasCallerScope ? getBorrowOwnership()
430+
: OperandOwnership(OperandOwnership::InstantaneousUse);
416431

417432
case SILArgumentConvention::Direct_Unowned:
418433
return OperandOwnership::UnownedInstantaneousUse;
@@ -435,7 +450,8 @@ OperandOwnershipClassifier::visitFullApply(FullApplySite apply) {
435450
? SILArgumentConvention(apply.getSubstCalleeType()->getCalleeConvention())
436451
: apply.getArgumentConvention(op);
437452

438-
auto operandOwnership = getFunctionArgOwnership(argConv);
453+
auto operandOwnership =
454+
getFunctionArgOwnership(argConv, apply.beginsCoroutineEvaluation());
439455

440456
// Allow passing callee operands with no ownership as guaranteed.
441457
// FIXME: why do we allow this?
@@ -478,7 +494,7 @@ OperandOwnership OperandOwnershipClassifier::visitYieldInst(YieldInst *i) {
478494
auto fnType = i->getFunction()->getLoweredFunctionType();
479495
SILArgumentConvention argConv(
480496
fnType->getYields()[getOperandIndex()].getConvention());
481-
return getFunctionArgOwnership(argConv);
497+
return getFunctionArgOwnership(argConv, /*hasCallerScope*/false);
482498
}
483499

484500
OperandOwnership OperandOwnershipClassifier::visitReturnInst(ReturnInst *i) {

0 commit comments

Comments
 (0)