@@ -179,26 +179,18 @@ OPERAND_OWNERSHIP(None, UnconditionalCheckedCastAddr)
179
179
OPERAND_OWNERSHIP(None, AllocValueBuffer)
180
180
OPERAND_OWNERSHIP(None, DeallocValueBuffer)
181
181
182
- // Point-in-time uses of any ownership.
183
- OPERAND_OWNERSHIP(InstantaneousUse, CopyValue)
184
- OPERAND_OWNERSHIP(InstantaneousUse, DebugValue)
182
+ // Use an owned or guaranteed value only for the duration of the operation.
185
183
OPERAND_OWNERSHIP(InstantaneousUse, ExistentialMetatype)
186
184
OPERAND_OWNERSHIP(InstantaneousUse, FixLifetime)
187
185
OPERAND_OWNERSHIP(InstantaneousUse, WitnessMethod)
188
186
OPERAND_OWNERSHIP(InstantaneousUse, DynamicMethodBranch)
189
187
OPERAND_OWNERSHIP(InstantaneousUse, ValueMetatype)
190
188
OPERAND_OWNERSHIP(InstantaneousUse, IsEscapingClosure)
191
189
OPERAND_OWNERSHIP(InstantaneousUse, ClassMethod)
192
- OPERAND_OWNERSHIP(InstantaneousUse, ObjCMethod)
193
- OPERAND_OWNERSHIP(InstantaneousUse, ObjCSuperMethod)
194
190
OPERAND_OWNERSHIP(InstantaneousUse, SuperMethod)
195
191
OPERAND_OWNERSHIP(InstantaneousUse, BridgeObjectToWord)
196
192
OPERAND_OWNERSHIP(InstantaneousUse, ClassifyBridgeObject)
197
- OPERAND_OWNERSHIP(InstantaneousUse, CopyBlock)
198
193
OPERAND_OWNERSHIP(InstantaneousUse, SetDeallocating)
199
- OPERAND_OWNERSHIP(InstantaneousUse, UnmanagedRetainValue)
200
- OPERAND_OWNERSHIP(InstantaneousUse, UnmanagedReleaseValue)
201
- OPERAND_OWNERSHIP(InstantaneousUse, UnmanagedAutoreleaseValue)
202
194
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
203
195
OPERAND_OWNERSHIP (InstantaneousUse, RefTo##Name) \
204
196
OPERAND_OWNERSHIP(InstantaneousUse, Name##ToRef) \
@@ -208,6 +200,16 @@ OPERAND_OWNERSHIP(InstantaneousUse, UnmanagedAutoreleaseValue)
208
200
OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value)
209
201
#include " swift/AST/ReferenceStorage.def"
210
202
203
+ // Unowned uses ignore the value's ownership
204
+ OPERAND_OWNERSHIP (UnownedInstantaneousUse, DebugValue)
205
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, CopyBlock)
206
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, CopyValue)
207
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, ObjCMethod)
208
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, ObjCSuperMethod)
209
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedRetainValue)
210
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedReleaseValue)
211
+ OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedAutoreleaseValue)
212
+
211
213
// Instructions that currently violate structural ownership requirements,
212
214
// and therefore completely defeat canonicalization and optimization of any
213
215
// OSSA value that they use.
@@ -278,39 +280,63 @@ OPERAND_OWNERSHIP(EndBorrow, EndBorrow)
278
280
279
281
#undef OPERAND_OWNERSHIP
280
282
281
- // Conditionally either ForwardingConsume or ForwardingBorrow, depending on
282
- // instruction result's dynamic ownership kind.
283
- #define FORWARD_ANY_OWNERSHIP (INST ) \
284
- OperandOwnership \
285
- OperandOwnershipClassifier::visit##INST##Inst(INST##Inst *i) { \
286
- return i->getOwnershipKind ().getForwardingOperandOwnership (); \
283
+ // Forwarding operations are conditionally either ForwardingConsumes or
284
+ // ForwardingBorrows, depending on the instruction's constant ownership
285
+ // attribute.
286
+ #define FORWARDING_OWNERSHIP (INST ) \
287
+ OperandOwnership OperandOwnershipClassifier::visit##INST##Inst( \
288
+ INST##Inst *i) { \
289
+ return i->getOwnershipKind ().getForwardingOperandOwnership ( \
290
+ /* allowUnowned*/ false ); \
291
+ }
292
+ FORWARDING_OWNERSHIP (Object)
293
+ FORWARDING_OWNERSHIP(OpenExistentialRef)
294
+ FORWARDING_OWNERSHIP(ConvertFunction)
295
+ FORWARDING_OWNERSHIP(RefToBridgeObject)
296
+ FORWARDING_OWNERSHIP(BridgeObjectToRef)
297
+ FORWARDING_OWNERSHIP(UnconditionalCheckedCast)
298
+ FORWARDING_OWNERSHIP(InitExistentialRef)
299
+ FORWARDING_OWNERSHIP(DifferentiableFunction)
300
+ FORWARDING_OWNERSHIP(LinearFunction)
301
+ #undef FORWARDING_OWNERSHIP
302
+
303
+ // Arbitrary value casts are forwarding instructions that are also allowed to
304
+ // propagate Unowned values. If the result is Unowned, then the operand must
305
+ // also be Unowned.
306
+ #define FORWARDING_ANY_OWNERSHIP (INST ) \
307
+ OperandOwnership OperandOwnershipClassifier::visit##INST##Inst( \
308
+ INST##Inst *i) { \
309
+ return i->getOwnershipKind ().getForwardingOperandOwnership ( \
310
+ /* allowUnowned*/ true ); \
287
311
}
288
- FORWARD_ANY_OWNERSHIP (Object)
289
- FORWARD_ANY_OWNERSHIP(Enum)
290
- FORWARD_ANY_OWNERSHIP(OpenExistentialRef)
291
- FORWARD_ANY_OWNERSHIP(Upcast)
292
- FORWARD_ANY_OWNERSHIP(UncheckedRefCast)
293
- FORWARD_ANY_OWNERSHIP(ConvertFunction)
294
- FORWARD_ANY_OWNERSHIP(RefToBridgeObject)
295
- FORWARD_ANY_OWNERSHIP(BridgeObjectToRef)
296
- FORWARD_ANY_OWNERSHIP(UnconditionalCheckedCast)
297
- FORWARD_ANY_OWNERSHIP(UncheckedEnumData)
298
- FORWARD_ANY_OWNERSHIP(InitExistentialRef)
299
- FORWARD_ANY_OWNERSHIP(DifferentiableFunction)
300
- FORWARD_ANY_OWNERSHIP(LinearFunction)
301
- FORWARD_ANY_OWNERSHIP(UncheckedValueCast)
302
- FORWARD_ANY_OWNERSHIP(SwitchEnum)
303
- FORWARD_ANY_OWNERSHIP(CheckedCastBranch)
304
- FORWARD_ANY_OWNERSHIP(Return)
305
-
306
- // FIXME: Guaranteed Tuple, Struct, and Destructure should be Reborrow, not
307
- // ForwardingBorrow, because the borrowed value is different on either side of
308
- // the operation and the lifetimes of borrowed members could differ.
309
- FORWARD_ANY_OWNERSHIP(Tuple)
310
- FORWARD_ANY_OWNERSHIP(Struct)
311
- FORWARD_ANY_OWNERSHIP(DestructureStruct)
312
- FORWARD_ANY_OWNERSHIP(DestructureTuple)
313
- #undef FORWARD_ANY_OWNERSHIP
312
+ FORWARDING_ANY_OWNERSHIP (Upcast)
313
+ FORWARDING_ANY_OWNERSHIP(UncheckedRefCast)
314
+ FORWARDING_ANY_OWNERSHIP(UncheckedValueCast)
315
+ FORWARDING_ANY_OWNERSHIP(CheckedCastBranch)
316
+ #undef FORWARDING_ANY_OWNERSHIP
317
+
318
+ // Any valid ownership kind can be combined with values of None ownership, but
319
+ // they cannot be combined with each other. An aggregates result ownership is
320
+ // the meet of its operands' ownership. A destructured member has the same
321
+ // ownership as its aggregate unless its type gives it None ownership.
322
+ //
323
+ // TODO: Aggregate operations should be Reborrows, not ForwardingBorrows,
324
+ // because the borrowed value is different on either side of the operation and
325
+ // the lifetimes of borrowed members could differ.
326
+ #define AGGREGATE_OWNERSHIP (INST ) \
327
+ OperandOwnership OperandOwnershipClassifier::visit##INST##Inst( \
328
+ INST##Inst *i) { \
329
+ return i->getOwnershipKind ().getForwardingOperandOwnership ( \
330
+ /* allowUnowned*/ true ); \
331
+ }
332
+ AGGREGATE_OWNERSHIP (Tuple)
333
+ AGGREGATE_OWNERSHIP(Struct)
334
+ AGGREGATE_OWNERSHIP(DestructureStruct)
335
+ AGGREGATE_OWNERSHIP(DestructureTuple)
336
+ AGGREGATE_OWNERSHIP(Enum)
337
+ AGGREGATE_OWNERSHIP(UncheckedEnumData)
338
+ AGGREGATE_OWNERSHIP(SwitchEnum)
339
+ #undef AGGREGATE_OWNERSHIP
314
340
315
341
// A begin_borrow is conditionally nested.
316
342
OperandOwnership
@@ -321,7 +347,10 @@ OperandOwnershipClassifier::visitBeginBorrowInst(BeginBorrowInst *borrow) {
321
347
case OwnershipKind::None:
322
348
return OperandOwnership::None;
323
349
case OwnershipKind::Unowned:
324
- return OperandOwnership::InstantaneousUse;
350
+ // FIXME: disallow borrowing an Unowned value. Temporarily model it as an
351
+ // instantaneous use until SILGenFunction::emitClassMemberDestruction is
352
+ // fixed.
353
+ return OperandOwnership::UnownedInstantaneousUse;
325
354
case OwnershipKind::Guaranteed:
326
355
return OperandOwnership::NestedBorrow;
327
356
case OwnershipKind::Owned:
@@ -344,17 +373,21 @@ OperandOwnershipClassifier::visitSelectEnumInst(SelectEnumInst *i) {
344
373
if (getValue () == i->getEnumOperand ()) {
345
374
return OperandOwnership::InstantaneousUse;
346
375
}
347
- return getOwnershipKind ().getForwardingOperandOwnership ();
376
+ return getOwnershipKind ().getForwardingOperandOwnership (
377
+ /* allowUnowned*/ true );
348
378
}
349
379
350
380
OperandOwnership OperandOwnershipClassifier::visitBranchInst (BranchInst *bi) {
351
381
ValueOwnershipKind destBlockArgOwnershipKind =
352
382
bi->getDestBB ()->getArgument (getOperandIndex ())->getOwnershipKind ();
353
383
384
+ // FIXME: remove this special case once all aggregate operations behave just
385
+ // like phis.
354
386
if (destBlockArgOwnershipKind == OwnershipKind::Guaranteed) {
355
387
return OperandOwnership::Reborrow;
356
388
}
357
- return destBlockArgOwnershipKind.getForwardingOperandOwnership ();
389
+ return destBlockArgOwnershipKind.getForwardingOperandOwnership (
390
+ /* allowUnowned*/ true );
358
391
}
359
392
360
393
OperandOwnership
@@ -378,9 +411,11 @@ static OperandOwnership getFunctionArgOwnership(SILArgumentConvention argConv) {
378
411
case SILArgumentConvention::Indirect_In_Constant:
379
412
case SILArgumentConvention::Indirect_In_Guaranteed:
380
413
case SILArgumentConvention::Direct_Guaranteed:
381
- case SILArgumentConvention::Direct_Unowned:
382
414
return OperandOwnership::InstantaneousUse;
383
415
416
+ case SILArgumentConvention::Direct_Unowned:
417
+ return OperandOwnership::UnownedInstantaneousUse;
418
+
384
419
case SILArgumentConvention::Indirect_Out:
385
420
case SILArgumentConvention::Indirect_Inout:
386
421
case SILArgumentConvention::Indirect_InoutAliasable:
@@ -445,6 +480,20 @@ OperandOwnership OperandOwnershipClassifier::visitYieldInst(YieldInst *i) {
445
480
return getFunctionArgOwnership (argConv);
446
481
}
447
482
483
+ OperandOwnership OperandOwnershipClassifier::visitReturnInst (ReturnInst *i) {
484
+ switch (i->getOwnershipKind ()) {
485
+ case OwnershipKind::Any:
486
+ case OwnershipKind::Guaranteed:
487
+ llvm_unreachable (" invalid value ownership" );
488
+ case OwnershipKind::None:
489
+ return OperandOwnership::None;
490
+ case OwnershipKind::Unowned:
491
+ return OperandOwnership::UnownedInstantaneousUse;
492
+ case OwnershipKind::Owned:
493
+ return OperandOwnership::ForwardingConsume;
494
+ }
495
+ }
496
+
448
497
OperandOwnership OperandOwnershipClassifier::visitAssignInst (AssignInst *i) {
449
498
if (getValue () != i->getSrc ()) {
450
499
return OperandOwnership::None;
@@ -476,14 +525,15 @@ OperandOwnership OperandOwnershipClassifier::visitCopyBlockWithoutEscapingInst(
476
525
if (getValue () == i->getClosure ()) {
477
526
return OperandOwnership::ForwardingConsume;
478
527
}
479
- return OperandOwnership::InstantaneousUse ;
528
+ return OperandOwnership::UnownedInstantaneousUse ;
480
529
}
481
530
482
531
OperandOwnership
483
532
OperandOwnershipClassifier::visitMarkDependenceInst (MarkDependenceInst *mdi) {
484
533
// If we are analyzing "the value", we forward ownership.
485
534
if (getValue () == mdi->getValue ()) {
486
- return getOwnershipKind ().getForwardingOperandOwnership ();
535
+ return getOwnershipKind ().getForwardingOperandOwnership (
536
+ /* allowUnowned*/ true );
487
537
}
488
538
// FIXME: Add an end_dependence instruction so we can treat mark_dependence as
489
539
// a borrow of the base (mark_dependence %base -> end_dependence is analogous
0 commit comments