@@ -133,10 +133,22 @@ bool CheckerLivenessInfo::compute() {
133
133
break ;
134
134
case OperandOwnership::Borrow: {
135
135
if (auto *bbi = dyn_cast<BeginBorrowInst>(user)) {
136
- // Only add borrows to liveness if the borrow isn't lexical. If it is
137
- // a lexical borrow, we have created an entirely new source level
138
- // binding that should be tracked separately.
139
- if (!bbi->isLexical ()) {
136
+ // If we have a lexical begin_borrow, we are going to check its uses
137
+ // separately and emit diagnostics for it. So we just need to add the
138
+ // liveness of the begin_borrow.
139
+ //
140
+ // NOTE: We know that semantically the use lexical lifetime must have
141
+ // a separate lifetime from the base lexical lifetime that we are
142
+ // processing. We do not want to include those uses as transitive uses
143
+ // of our base lexical lifetime. We just want to treat the formation
144
+ // of the new variable as a use. Thus we only include the begin_borrow
145
+ // itself as the use.
146
+ if (bbi->isLexical ()) {
147
+ liveness.updateForUse (bbi, false /* lifetime ending*/ );
148
+ } else {
149
+ // Otherwise, try to update liveness for a borrowing operand
150
+ // use. This will make it so that we add the end_borrows of the
151
+ // liveness use. If we have a reborrow here, we will bail.
140
152
bool failed = !liveness.updateForBorrowingOperand (use);
141
153
if (failed)
142
154
return false ;
@@ -351,24 +363,32 @@ bool MoveKillsCopyableValuesChecker::check() {
351
363
SmallSetVector<SILValue, 32 > valuesToCheck;
352
364
353
365
for (auto *arg : fn->getEntryBlock ()->getSILFunctionArguments ()) {
354
- if (arg->getOwnershipKind () == OwnershipKind::Owned)
366
+ if (arg->getOwnershipKind () == OwnershipKind::Owned) {
367
+ LLVM_DEBUG (llvm::dbgs () << " Found owned arg to check: " << *arg);
355
368
valuesToCheck.insert (arg);
369
+ }
356
370
}
357
371
358
372
for (auto &block : *fn) {
359
373
for (auto &ii : block) {
360
374
if (auto *bbi = dyn_cast<BeginBorrowInst>(&ii)) {
361
- if (bbi->isLexical ())
375
+ if (bbi->isLexical ()) {
376
+ LLVM_DEBUG (llvm::dbgs ()
377
+ << " Found lexical lifetime to check: " << *bbi);
362
378
valuesToCheck.insert (bbi);
379
+ }
363
380
continue ;
364
381
}
365
382
}
366
383
}
367
384
368
- if (valuesToCheck.empty ())
385
+ if (valuesToCheck.empty ()) {
386
+ LLVM_DEBUG (llvm::dbgs () << " No values to check! Exiting early!\n " );
369
387
return false ;
388
+ }
370
389
371
- LLVM_DEBUG (llvm::dbgs () << " Visiting Function: " << fn->getName () << " \n " );
390
+ LLVM_DEBUG (llvm::dbgs ()
391
+ << " Found at least one value to check, performing checking.\n " );
372
392
auto valuesToProcess =
373
393
llvm::makeArrayRef (valuesToCheck.begin (), valuesToCheck.end ());
374
394
auto &mod = fn->getModule ();
@@ -475,6 +495,9 @@ class MoveKillsCopyableValuesCheckerPass : public SILFunctionTransform {
475
495
assert (fn->getModule ().getStage () == SILStage::Raw &&
476
496
" Should only run on Raw SIL" );
477
497
498
+ LLVM_DEBUG (llvm::dbgs () << " *** Checking moved values in fn: "
499
+ << getFunction ()->getName () << ' \n ' );
500
+
478
501
MoveKillsCopyableValuesChecker checker (getFunction ());
479
502
480
503
// If we already had dominance or loop info generated, update them when
0 commit comments