@@ -5000,14 +5000,16 @@ class CallEmission {
5000
5000
FormalEvaluationScope initialWritebackScope;
5001
5001
std::optional<ActorIsolation> implicitActorHopTarget;
5002
5002
bool implicitlyThrows;
5003
+ bool canUnwind;
5003
5004
5004
5005
public:
5005
5006
// / Create an emission for a call of the given callee.
5006
5007
CallEmission (SILGenFunction &SGF, Callee &&callee,
5007
5008
FormalEvaluationScope &&writebackScope)
5008
5009
: SGF(SGF), callee(std::move(callee)),
5009
5010
initialWritebackScope (std::move(writebackScope)),
5010
- implicitActorHopTarget(std::nullopt), implicitlyThrows(false ) {}
5011
+ implicitActorHopTarget(std::nullopt), implicitlyThrows(false ),
5012
+ canUnwind(false ) {}
5011
5013
5012
5014
// / A factory method for decomposing the apply expr \p e into a call
5013
5015
// / emission.
@@ -5058,6 +5060,8 @@ class CallEmission {
5058
5060
// / function can throw or not.
5059
5061
void setImplicitlyThrows (bool flag) { implicitlyThrows = flag; }
5060
5062
5063
+ void setCanUnwind (bool flag) { canUnwind = flag; }
5064
+
5061
5065
CleanupHandle applyCoroutine (SmallVectorImpl<ManagedValue> &yields);
5062
5066
5063
5067
RValue apply (SGFContext C = SGFContext()) {
@@ -5115,9 +5119,11 @@ namespace {
5115
5119
// / Cleanup to end a coroutine application.
5116
5120
class EndCoroutineApply : public Cleanup {
5117
5121
SILValue ApplyToken;
5122
+ bool CanUnwind;
5118
5123
std::vector<BeginBorrowInst *> BorrowedMoveOnlyValues;
5119
5124
public:
5120
- EndCoroutineApply (SILValue applyToken) : ApplyToken(applyToken) {}
5125
+ EndCoroutineApply (SILValue applyToken, bool CanUnwind)
5126
+ : ApplyToken(applyToken), CanUnwind(CanUnwind) {}
5121
5127
5122
5128
void setBorrowedMoveOnlyValues (ArrayRef<BeginBorrowInst *> values) {
5123
5129
BorrowedMoveOnlyValues.insert (BorrowedMoveOnlyValues.end (),
@@ -5130,14 +5136,7 @@ class EndCoroutineApply : public Cleanup {
5130
5136
SGF.B .createEndBorrow (l, *i);
5131
5137
SGF.B .createDestroyValue (l, (*i)->getOperand ());
5132
5138
}
5133
- auto *beginApply =
5134
- cast<BeginApplyInst>(ApplyToken->getDefiningInstruction ());
5135
- auto isCalleeAllocated = beginApply->isCalleeAllocated ();
5136
- auto unwindOnCallerError =
5137
- !isCalleeAllocated ||
5138
- SGF.SGM .getASTContext ().LangOpts .hasFeature (
5139
- Feature::CoroutineAccessorsUnwindOnCallerError);
5140
- if (forUnwind && unwindOnCallerError) {
5139
+ if (forUnwind && CanUnwind) {
5141
5140
SGF.B .createAbortApply (l, ApplyToken);
5142
5141
} else {
5143
5142
SGF.B .createEndApply (l, ApplyToken,
@@ -5180,18 +5179,15 @@ CallEmission::applyCoroutine(SmallVectorImpl<ManagedValue> &yields) {
5180
5179
5181
5180
auto fnValue = callee.getFnValue (SGF, borrowedSelf);
5182
5181
5183
- return SGF.emitBeginApply (uncurriedLoc.value (), fnValue,
5182
+ return SGF.emitBeginApply (uncurriedLoc.value (), fnValue, canUnwind,
5184
5183
callee.getSubstitutions (), uncurriedArgs,
5185
5184
calleeTypeInfo.substFnType , options, yields);
5186
5185
}
5187
5186
5188
- CleanupHandle
5189
- SILGenFunction::emitBeginApply (SILLocation loc, ManagedValue fn,
5190
- SubstitutionMap subs,
5191
- ArrayRef<ManagedValue> args,
5192
- CanSILFunctionType substFnType,
5193
- ApplyOptions options,
5194
- SmallVectorImpl<ManagedValue> &yields) {
5187
+ CleanupHandle SILGenFunction::emitBeginApply (
5188
+ SILLocation loc, ManagedValue fn, bool canUnwind, SubstitutionMap subs,
5189
+ ArrayRef<ManagedValue> args, CanSILFunctionType substFnType,
5190
+ ApplyOptions options, SmallVectorImpl<ManagedValue> &yields) {
5195
5191
// Emit the call.
5196
5192
SmallVector<SILValue, 4 > rawResults;
5197
5193
emitRawApply (*this , loc, fn, subs, args, substFnType, options,
@@ -5207,7 +5203,7 @@ SILGenFunction::emitBeginApply(SILLocation loc, ManagedValue fn,
5207
5203
5208
5204
// Push a cleanup to end the application.
5209
5205
// TODO: destroy all the arguments at exactly this point?
5210
- Cleanups.pushCleanup <EndCoroutineApply>(token);
5206
+ Cleanups.pushCleanup <EndCoroutineApply>(token, canUnwind );
5211
5207
auto endApplyHandle = getTopCleanup ();
5212
5208
5213
5209
// Manage all the yielded values.
@@ -6184,7 +6180,7 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn,
6184
6180
std::tuple<MultipleValueInstructionResult *, CleanupHandle, SILValue,
6185
6181
CleanupHandle>
6186
6182
SILGenFunction::emitBeginApplyWithRethrow (SILLocation loc, SILValue fn,
6187
- SILType substFnType,
6183
+ SILType substFnType, bool canUnwind,
6188
6184
SubstitutionMap subs,
6189
6185
ArrayRef<SILValue> args,
6190
6186
SmallVectorImpl<SILValue> &yields) {
@@ -6209,7 +6205,7 @@ SILGenFunction::emitBeginApplyWithRethrow(SILLocation loc, SILValue fn,
6209
6205
deallocCleanup = enterDeallocStackCleanup (allocation);
6210
6206
}
6211
6207
6212
- Cleanups.pushCleanup <EndCoroutineApply>(token);
6208
+ Cleanups.pushCleanup <EndCoroutineApply>(token, canUnwind );
6213
6209
auto abortCleanup = Cleanups.getTopCleanup ();
6214
6210
6215
6211
return {token, abortCleanup, allocation, deallocCleanup};
@@ -7562,6 +7558,21 @@ ManagedValue SILGenFunction::emitAddressorAccessor(
7562
7558
return ManagedValue::forLValue (address);
7563
7559
}
7564
7560
7561
+ bool SILGenFunction::canUnwindAccessorDeclRef (SILDeclRef accessorRef) {
7562
+ auto *accessor =
7563
+ dyn_cast_or_null<AccessorDecl>(accessorRef.getAbstractFunctionDecl ());
7564
+ ASSERT (accessor && " only accessors can unwind" );
7565
+ auto kind = accessor->getAccessorKind ();
7566
+ ASSERT (isYieldingAccessor (kind) && " only yielding accessors can unwind" );
7567
+ if (!requiresFeatureCoroutineAccessors (kind)) {
7568
+ // _read and _modify can unwind
7569
+ return true ;
7570
+ }
7571
+ // Coroutine accessors can only unwind with the experimental feature.
7572
+ return getASTContext ().LangOpts .hasFeature (
7573
+ Feature::CoroutineAccessorsUnwindOnCallerError);
7574
+ }
7575
+
7565
7576
CleanupHandle
7566
7577
SILGenFunction::emitCoroutineAccessor (SILLocation loc, SILDeclRef accessor,
7567
7578
SubstitutionMap substitutions,
@@ -7597,6 +7608,8 @@ SILGenFunction::emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
7597
7608
7598
7609
emission.addCallSite (loc, std::move (subscriptIndices));
7599
7610
7611
+ emission.setCanUnwind (canUnwindAccessorDeclRef (accessor));
7612
+
7600
7613
auto endApplyHandle = emission.applyCoroutine (yields);
7601
7614
7602
7615
return endApplyHandle;
0 commit comments