@@ -249,7 +249,7 @@ static FixLifetimeInst *isFixLifetimeUseOfArray(SILInstruction *user,
249
249
AllocStackInst *alloc = dyn_cast<AllocStackInst>(storeUser->getDest ());
250
250
if (!alloc)
251
251
return nullptr ;
252
- auto fixLifetimeUsers = alloc ->getUsersOfType <FixLifetimeInst>();
252
+ auto fixLifetimeUsers = storeUser ->getUsersOfType <FixLifetimeInst>();
253
253
if (fixLifetimeUsers.empty ())
254
254
return nullptr ;
255
255
auto firstUser = fixLifetimeUsers.begin ();
@@ -278,7 +278,7 @@ static TryApplyInst *isForEachUseOfArray(SILInstruction *user, SILValue array) {
278
278
AllocStackInst *alloc = dyn_cast<AllocStackInst>(storeUser->getDest ());
279
279
if (!alloc)
280
280
return nullptr ;
281
- auto applyUsers = alloc ->getUsersOfType <TryApplyInst>();
281
+ auto applyUsers = storeUser ->getUsersOfType <TryApplyInst>();
282
282
if (applyUsers.empty ())
283
283
return nullptr ;
284
284
auto firstUser = applyUsers.begin ();
@@ -385,12 +385,11 @@ void ArrayInfo::getLastDestroys(
385
385
// / not clean up any resulting dead instructions.
386
386
static void removeForEachCall (TryApplyInst *forEachCall,
387
387
InstructionDeleter &deleter) {
388
- AllocStackInst *allocStack =
389
- dyn_cast<AllocStackInst>(forEachCall->getArgument (1 ));
390
- assert (allocStack);
388
+ auto *sbi = cast<StoreBorrowInst>(forEachCall->getArgument (1 ));
389
+ auto *asi = cast<AllocStackInst>(sbi->getDest ());
391
390
// The allocStack will be used in the forEach call and also in a store
392
391
// instruction and a dealloc_stack instruction. Force delete all of them.
393
- deleter.recursivelyForceDeleteUsersAndFixLifetimes (allocStack );
392
+ deleter.recursivelyForceDeleteUsersAndFixLifetimes (asi );
394
393
}
395
394
396
395
// / Unroll the \c forEachCall on an array, using the information in
@@ -502,12 +501,15 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
502
501
// "error" branch of a try_apply. The error block created here will always
503
502
// jump to the error target of the original forEach.
504
503
auto errorTargetGenerator = [&](SILBasicBlock *insertionBlock,
505
- SILValue borrowedElem ) {
504
+ SILValue borrowedElem, SILValue storeBorrow ) {
506
505
SILBasicBlock *newErrorBB = fun->createBasicBlockBefore (insertionBlock);
507
506
SILValue argument = newErrorBB->createPhiArgument (
508
507
errorArgument->getType (), errorArgument->getOwnershipKind ());
509
508
// Make the errorBB jump to the error target of the original forEach.
510
509
SILBuilderWithScope builder (newErrorBB, forEachCall);
510
+ if (storeBorrow) {
511
+ builder.createEndBorrow (forEachLoc, storeBorrow);
512
+ }
511
513
if (borrowedElem) {
512
514
builder.createEndBorrow (forEachLoc, borrowedElem);
513
515
}
@@ -537,28 +539,33 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
537
539
: forEachCall->getParentBlock ();
538
540
SILBuilderWithScope unrollBuilder (currentBB, forEachCall);
539
541
SILValue borrowedElem;
542
+ SILValue addr;
543
+
540
544
if (arrayElementType.isTrivial (*fun)) {
541
545
unrollBuilder.createStore (forEachLoc, elementCopy, allocStack,
542
546
StoreOwnershipQualifier::Trivial);
547
+ addr = allocStack;
543
548
} else {
544
549
// Borrow the elementCopy and store it in the allocStack. Note that the
545
550
// element's copy is guaranteed to be alive until the array is alive.
546
551
// Therefore it is okay to use a borrow here.
547
552
borrowedElem = unrollBuilder.createBeginBorrow (forEachLoc, elementCopy);
548
- unrollBuilder.createStoreBorrow (forEachLoc, borrowedElem, allocStack);
549
-
550
- SILBuilderWithScope (&nextNormalBB->front (), forEachCall)
551
- .createEndBorrow (forEachLoc, borrowedElem);
553
+ addr =
554
+ unrollBuilder.createStoreBorrow (forEachLoc, borrowedElem, allocStack);
555
+ SILBuilderWithScope builder (&nextNormalBB->front (), forEachCall);
556
+ builder.createEndBorrow (forEachLoc, addr);
557
+ builder.createEndBorrow (forEachLoc, borrowedElem);
552
558
}
553
559
554
560
SILBasicBlock *errorTarget =
555
- errorTargetGenerator (nextNormalBB, borrowedElem);
561
+ errorTargetGenerator (nextNormalBB, borrowedElem,
562
+ isa<StoreBorrowInst>(addr) ? addr : SILValue ());
556
563
// Note that the substitution map must be empty as we are not supporting
557
564
// elements of address-only type. All elements in the array are guaranteed
558
565
// to be loadable. TODO: generalize this to address-only types.
559
566
unrollBuilder.createTryApply (forEachLoc, forEachBodyClosure,
560
- SubstitutionMap (), allocStack ,
561
- nextNormalBB, errorTarget);
567
+ SubstitutionMap (), addr, nextNormalBB ,
568
+ errorTarget);
562
569
nextNormalBB = currentBB;
563
570
}
564
571
0 commit comments