@@ -249,7 +249,7 @@ static FixLifetimeInst *isFixLifetimeUseOfArray(SILInstruction *user,
249249 AllocStackInst *alloc = dyn_cast<AllocStackInst>(storeUser->getDest ());
250250 if (!alloc)
251251 return nullptr ;
252- auto fixLifetimeUsers = alloc ->getUsersOfType <FixLifetimeInst>();
252+ auto fixLifetimeUsers = storeUser ->getUsersOfType <FixLifetimeInst>();
253253 if (fixLifetimeUsers.empty ())
254254 return nullptr ;
255255 auto firstUser = fixLifetimeUsers.begin ();
@@ -278,7 +278,7 @@ static TryApplyInst *isForEachUseOfArray(SILInstruction *user, SILValue array) {
278278 AllocStackInst *alloc = dyn_cast<AllocStackInst>(storeUser->getDest ());
279279 if (!alloc)
280280 return nullptr ;
281- auto applyUsers = alloc ->getUsersOfType <TryApplyInst>();
281+ auto applyUsers = storeUser ->getUsersOfType <TryApplyInst>();
282282 if (applyUsers.empty ())
283283 return nullptr ;
284284 auto firstUser = applyUsers.begin ();
@@ -385,12 +385,11 @@ void ArrayInfo::getLastDestroys(
385385// / not clean up any resulting dead instructions.
386386static void removeForEachCall (TryApplyInst *forEachCall,
387387 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 ());
391390 // The allocStack will be used in the forEach call and also in a store
392391 // instruction and a dealloc_stack instruction. Force delete all of them.
393- deleter.recursivelyForceDeleteUsersAndFixLifetimes (allocStack );
392+ deleter.recursivelyForceDeleteUsersAndFixLifetimes (asi );
394393}
395394
396395// / Unroll the \c forEachCall on an array, using the information in
@@ -502,12 +501,15 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
502501 // "error" branch of a try_apply. The error block created here will always
503502 // jump to the error target of the original forEach.
504503 auto errorTargetGenerator = [&](SILBasicBlock *insertionBlock,
505- SILValue borrowedElem ) {
504+ SILValue borrowedElem, SILValue storeBorrow ) {
506505 SILBasicBlock *newErrorBB = fun->createBasicBlockBefore (insertionBlock);
507506 SILValue argument = newErrorBB->createPhiArgument (
508507 errorArgument->getType (), errorArgument->getOwnershipKind ());
509508 // Make the errorBB jump to the error target of the original forEach.
510509 SILBuilderWithScope builder (newErrorBB, forEachCall);
510+ if (storeBorrow) {
511+ builder.createEndBorrow (forEachLoc, storeBorrow);
512+ }
511513 if (borrowedElem) {
512514 builder.createEndBorrow (forEachLoc, borrowedElem);
513515 }
@@ -537,28 +539,33 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
537539 : forEachCall->getParentBlock ();
538540 SILBuilderWithScope unrollBuilder (currentBB, forEachCall);
539541 SILValue borrowedElem;
542+ SILValue addr;
543+
540544 if (arrayElementType.isTrivial (*fun)) {
541545 unrollBuilder.createStore (forEachLoc, elementCopy, allocStack,
542546 StoreOwnershipQualifier::Trivial);
547+ addr = allocStack;
543548 } else {
544549 // Borrow the elementCopy and store it in the allocStack. Note that the
545550 // element's copy is guaranteed to be alive until the array is alive.
546551 // Therefore it is okay to use a borrow here.
547552 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);
552558 }
553559
554560 SILBasicBlock *errorTarget =
555- errorTargetGenerator (nextNormalBB, borrowedElem);
561+ errorTargetGenerator (nextNormalBB, borrowedElem,
562+ isa<StoreBorrowInst>(addr) ? addr : SILValue ());
556563 // Note that the substitution map must be empty as we are not supporting
557564 // elements of address-only type. All elements in the array are guaranteed
558565 // to be loadable. TODO: generalize this to address-only types.
559566 unrollBuilder.createTryApply (forEachLoc, forEachBodyClosure,
560- SubstitutionMap (), allocStack ,
561- nextNormalBB, errorTarget);
567+ SubstitutionMap (), addr, nextNormalBB ,
568+ errorTarget);
562569 nextNormalBB = currentBB;
563570 }
564571
0 commit comments