88
88
// alloc_stack %stack
89
89
// %elem1borrow = begin_borrow %elem1copy
90
90
// store_borrow %elem1borrow to %stack
91
- // end_borrow %elem1borrow
92
91
// try_apply %body(%stack) normal normalbb1, error errbb1
93
92
//
94
93
// errbb1(%error : @owned $Error):
95
- // br bb2(%error)
94
+ // end_borrow %elem1borrow
95
+ // br bb2(%error)
96
96
//
97
97
// normalbb1(%res : $()):
98
+ // end_borrow %elem1borrow
98
99
// %elem2borrow = begin_borrow %elem2copy
99
100
// store_borrow %elem2borrow to %stack
100
- // end_borrow %elem2borrow
101
101
// try_apply %body(%stack) normal bb1, error errbb2
102
102
//
103
103
// errbb2(%error : @owned $Error):
104
- // br bb2(%error)
104
+ // end_borrow %elem2borrow
105
+ // br bb2(%error)
105
106
//
106
107
// bb1(%res : $()):
108
+ // end_borrow %elem2borrow
107
109
// dealloc_stack %stack
108
110
// ...
109
111
// bb2(%error : @owned $Error):
@@ -499,12 +501,16 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
499
501
// A generator for creating a basic block for use as the target of the
500
502
// "error" branch of a try_apply. The error block created here will always
501
503
// jump to the error target of the original forEach.
502
- auto errorTargetGenerator = [&](SILBasicBlock *insertionBlock) {
504
+ auto errorTargetGenerator = [&](SILBasicBlock *insertionBlock,
505
+ SILValue borrowedElem ) {
503
506
SILBasicBlock *newErrorBB = fun->createBasicBlockBefore (insertionBlock);
504
507
SILValue argument = newErrorBB->createPhiArgument (
505
508
errorArgument->getType (), errorArgument->getOwnershipKind ());
506
509
// Make the errorBB jump to the error target of the original forEach.
507
510
SILBuilderWithScope builder (newErrorBB, forEachCall);
511
+ if (borrowedElem) {
512
+ builder.createEndBorrow (forEachLoc, borrowedElem);
513
+ }
508
514
builder.createBranch (forEachLoc, errorBB, argument);
509
515
return newErrorBB;
510
516
};
@@ -525,28 +531,34 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
525
531
// error blocks jump to the error target of the original forEach call.
526
532
for (uint64_t num = arrayInfo.getNumElements (); num > 0 ; --num) {
527
533
SILValue elementCopy = elementCopies[num - 1 ];
534
+ // Creating the next normal block ends the borrow scope for borrowedElem
535
+ // from the previous iteration.
528
536
SILBasicBlock *currentBB = num > 1 ? normalTargetGenerator (nextNormalBB)
529
537
: forEachCall->getParentBlock ();
530
538
SILBuilderWithScope unrollBuilder (currentBB, forEachCall);
539
+ SILValue borrowedElem;
531
540
if (arrayElementType.isTrivial (*fun)) {
532
541
unrollBuilder.createStore (forEachLoc, elementCopy, allocStack,
533
542
StoreOwnershipQualifier::Trivial);
534
543
} else {
535
544
// Borrow the elementCopy and store it in the allocStack. Note that the
536
545
// element's copy is guaranteed to be alive until the array is alive.
537
546
// Therefore it is okay to use a borrow here.
538
- SILValue borrowedElem =
539
- unrollBuilder.createBeginBorrow (forEachLoc, elementCopy);
547
+ borrowedElem = unrollBuilder.createBeginBorrow (forEachLoc, elementCopy);
540
548
unrollBuilder.createStoreBorrow (forEachLoc, borrowedElem, allocStack);
541
- unrollBuilder.createEndBorrow (forEachLoc, borrowedElem);
549
+
550
+ SILBuilderWithScope (&nextNormalBB->front (), forEachCall)
551
+ .createEndBorrow (forEachLoc, borrowedElem);
542
552
}
543
- SILBasicBlock *errorTarget = errorTargetGenerator (nextNormalBB);
553
+
554
+ SILBasicBlock *errorTarget =
555
+ errorTargetGenerator (nextNormalBB, borrowedElem);
544
556
// Note that the substitution map must be empty as we are not supporting
545
557
// elements of address-only type. All elements in the array are guaranteed
546
558
// to be loadable. TODO: generalize this to address-only types.
547
559
unrollBuilder.createTryApply (forEachLoc, forEachBodyClosure,
548
- SubstitutionMap (), allocStack, nextNormalBB,
549
- errorTarget);
560
+ SubstitutionMap (), allocStack,
561
+ nextNormalBB, errorTarget);
550
562
nextNormalBB = currentBB;
551
563
}
552
564
0 commit comments