@@ -195,6 +195,8 @@ static SILFunctionConventions getLoweredCallConv(ApplySite call) {
195
195
// / If \p pseudoResult represents multiple results and at least one result is
196
196
// / used, then return the destructure.
197
197
static DestructureTupleInst *getCallDestructure (FullApplySite apply) {
198
+ if (apply.getKind () == FullApplySiteKind::BeginApplyInst)
199
+ return nullptr ;
198
200
if (apply.getSubstCalleeConv ().getNumDirectSILResults () == 1 )
199
201
return nullptr ;
200
202
@@ -640,7 +642,8 @@ void OpaqueValueVisitor::checkForIndirectApply(FullApplySite applySite) {
640
642
++calleeArgIdx;
641
643
}
642
644
643
- if (applySite.getSubstCalleeType ()->hasIndirectFormalResults ()) {
645
+ if (applySite.getSubstCalleeType ()->hasIndirectFormalResults () ||
646
+ applySite.getSubstCalleeType ()->hasIndirectFormalYields ()) {
644
647
pass.indirectApplies .insert (applySite);
645
648
}
646
649
}
@@ -2120,7 +2123,16 @@ void ApplyRewriter::rewriteApply(ArrayRef<SILValue> newCallArgs) {
2120
2123
// will be deleted with its destructure_tuple.
2121
2124
}
2122
2125
2126
+ // / Emit end_borrows for a an incomplete BorrowedValue with only nonlifetime
2127
+ // / ending uses.
2128
+ static void emitEndBorrows (SILValue value, AddressLoweringState &pass);
2129
+
2123
2130
void ApplyRewriter::convertBeginApplyWithOpaqueYield () {
2131
+ // Avoid revisiting this apply.
2132
+ bool erased = pass.indirectApplies .erase (apply);
2133
+ assert (erased && " all yields should be rewritten at the same time" );
2134
+ (void )erased;
2135
+
2124
2136
auto *origCall = cast<BeginApplyInst>(apply.getInstruction ());
2125
2137
SmallVector<SILValue, 4 > opValues;
2126
2138
@@ -2140,11 +2152,33 @@ void ApplyRewriter::convertBeginApplyWithOpaqueYield() {
2140
2152
auto newResults = newCall->getAllResultsBuffer ();
2141
2153
assert (oldResults.size () == newResults.size ());
2142
2154
for (auto i : indices (oldResults)) {
2143
- if (oldResults[i].getType ().isAddressOnly (*pass.function )) {
2144
- pass.valueStorageMap .setStorageAddress (&oldResults[i], &newResults[i]);
2145
- pass.valueStorageMap .getStorage (&oldResults[i]).markRewritten ();
2155
+ auto &oldResult = oldResults[i];
2156
+ auto &newResult = newResults[i];
2157
+ if (oldResult.getType ().isAddressOnly (*pass.function )) {
2158
+ if (!oldResult.getType ().isAddress ()) {
2159
+ pass.valueStorageMap .setStorageAddress (&oldResult, &newResult);
2160
+ pass.valueStorageMap .getStorage (&oldResult).markRewritten ();
2161
+ } else {
2162
+ oldResult.replaceAllUsesWith (&newResult);
2163
+ }
2146
2164
} else {
2147
- oldResults[i].replaceAllUsesWith (&newResults[i]);
2165
+ if (oldResult.getType ().isObject () && newResult.getType ().isAddress ()) {
2166
+ if (oldResult.getOwnershipKind () == OwnershipKind::Guaranteed) {
2167
+ SILValue load =
2168
+ resultBuilder.emitLoadBorrowOperation (callLoc, &newResult);
2169
+ oldResult.replaceAllUsesWith (load);
2170
+ emitEndBorrows (load, pass);
2171
+ } else {
2172
+ auto *load = resultBuilder.createLoad (
2173
+ callLoc, &newResult,
2174
+ newResult.getType ().isTrivial (*pass.function )
2175
+ ? LoadOwnershipQualifier::Trivial
2176
+ : LoadOwnershipQualifier::Take);
2177
+ oldResult.replaceAllUsesWith (load);
2178
+ }
2179
+ } else {
2180
+ oldResult.replaceAllUsesWith (&newResult);
2181
+ }
2148
2182
}
2149
2183
}
2150
2184
}
@@ -2762,10 +2796,6 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
2762
2796
2763
2797
void visitStoreInst (StoreInst *storeInst);
2764
2798
2765
- // / Emit end_borrows for a an incomplete BorrowedValue with only nonlifetime
2766
- // / ending uses.
2767
- void emitEndBorrows (SILValue value);
2768
-
2769
2799
void emitExtract (SingleValueInstruction *extractInst);
2770
2800
2771
2801
void visitSelectEnumInst (SelectEnumInst *sei) {
@@ -2832,7 +2862,7 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
2832
2862
builder.emitLoadBorrowOperation (uncheckedCastInst->getLoc (), destAddr);
2833
2863
uncheckedCastInst->replaceAllUsesWith (load);
2834
2864
pass.deleter .forceDelete (uncheckedCastInst);
2835
- emitEndBorrows (load);
2865
+ emitEndBorrows (load, pass );
2836
2866
}
2837
2867
2838
2868
void visitUnconditionalCheckedCastInst (
@@ -2944,7 +2974,7 @@ void UseRewriter::visitStoreInst(StoreInst *storeInst) {
2944
2974
2945
2975
// / Emit end_borrows for a an incomplete BorrowedValue with only nonlifetime
2946
2976
// / ending uses. This function inserts end_borrows on the lifetime boundary.
2947
- void UseRewriter:: emitEndBorrows (SILValue value) {
2977
+ static void emitEndBorrows (SILValue value, AddressLoweringState &pass ) {
2948
2978
assert (BorrowedValue (value));
2949
2979
2950
2980
// Place end_borrows that cover the load_borrow uses. It is not necessary to
@@ -3002,7 +3032,7 @@ void UseRewriter::emitExtract(SingleValueInstruction *extractInst) {
3002
3032
SILValue loadElement =
3003
3033
builder.emitLoadBorrowOperation (extractInst->getLoc (), extractAddr);
3004
3034
replaceUsesWithLoad (extractInst, loadElement);
3005
- emitEndBorrows (loadElement);
3035
+ emitEndBorrows (loadElement, pass );
3006
3036
}
3007
3037
3008
3038
void UseRewriter::visitStructExtractInst (StructExtractInst *extractInst) {
@@ -3369,14 +3399,27 @@ static void rewriteIndirectApply(FullApplySite apply,
3369
3399
// If all indirect args were loadable, then they still need to be rewritten.
3370
3400
CallArgRewriter (apply, pass).rewriteArguments ();
3371
3401
3372
- if (!apply.getSubstCalleeType ()->hasIndirectFormalResults ()) {
3373
- return ;
3402
+ switch (apply.getKind ()) {
3403
+ case FullApplySiteKind::ApplyInst:
3404
+ case FullApplySiteKind::TryApplyInst: {
3405
+ if (!apply.getSubstCalleeType ()->hasIndirectFormalResults ()) {
3406
+ return ;
3407
+ }
3408
+ // If the call has indirect results and wasn't already rewritten, rewrite it
3409
+ // now. This handles try_apply, which is not rewritten when DefRewriter
3410
+ // visits block arguments. It also handles apply with loadable indirect
3411
+ // results.
3412
+ ApplyRewriter (apply, pass).convertApplyWithIndirectResults ();
3413
+ break ;
3414
+ }
3415
+ case FullApplySiteKind::BeginApplyInst: {
3416
+ if (!apply.getSubstCalleeType ()->hasIndirectFormalYields ()) {
3417
+ return ;
3418
+ }
3419
+ ApplyRewriter (apply, pass).convertBeginApplyWithOpaqueYield ();
3420
+ break ;
3421
+ }
3374
3422
}
3375
-
3376
- // If the call has indirect results and wasn't already rewritten, rewrite it
3377
- // now. This handles try_apply, which is not rewritten when DefRewriter visits
3378
- // block arguments. It also handles apply with loadable indirect results.
3379
- ApplyRewriter (apply, pass).convertApplyWithIndirectResults ();
3380
3423
3381
3424
if (!apply.getInstruction ()->isDeleted ()) {
3382
3425
assert (!getCallDestructure (apply)
0 commit comments