Skip to content

Commit 2e1494d

Browse files
Merge pull request #80701 from nate-chandler/rdar148941214
[CoroutineAccessors] Use yield_once_2 on Darwin and Linux.
2 parents 21480b8 + b76a76b commit 2e1494d

26 files changed

+195
-38
lines changed

include/swift/AST/SILOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ class SILOptions {
338338
// Whether to allow merging traps and cond_fails.
339339
bool MergeableTraps = false;
340340

341+
/// Whether the @yield_once_2 convention is used by accessors added with the
342+
/// CoroutineAccessors feature (i.e. read2/modify2).
343+
bool CoroutineAccessorsUseYieldOnce2 = false;
344+
341345
SILOptions() {}
342346

343347
/// Return a hash code of any components from these options that should

include/swift/Option/FrontendOptions.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,12 @@ def enable_arm64_corocc : Flag<["-"], "enable-arm64-corocc">,
11751175
def disable_arm64_corocc : Flag<["-"], "disable-arm64-corocc">,
11761176
HelpText<"Don't use swiftcorocc for yield_once_2 routines on arm64 variants.">;
11771177

1178+
def enable_callee_allocated_coro_abi : Flag<["-"], "enable-callee-allocated-coro-abi">,
1179+
HelpText<"Override per-platform settings and use yield_once_2.">;
1180+
1181+
def disable_callee_allocated_coro_abi : Flag<["-"], "disable-callee-allocated-coro-abi">,
1182+
HelpText<"Override per-platform settings and don't use yield_once_2.">;
1183+
11781184
def enable_cond_fail_message_annotation : Flag<["-"], "enable-cond-fail-message-annotation">,
11791185
HelpText<"Enable cond_fail message annotation. Will serialize a .o.yaml file per .o file.">;
11801186

lib/DriverTool/sil_opt_main.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,16 @@ struct SILOptOptions {
597597
"enable-address-dependencies",
598598
llvm::cl::desc("Enable enforcement of lifetime dependencies on addressable values."));
599599

600+
llvm::cl::opt<bool> EnableCalleeAllocatedCoroAbi = llvm::cl::opt<bool>(
601+
"enable-callee-allocated-coro-abi",
602+
llvm::cl::desc("Override per-platform settings and use yield_once_2."),
603+
llvm::cl::init(false));
604+
llvm::cl::opt<bool> DisableCalleeAllocatedCoroAbi = llvm::cl::opt<bool>(
605+
"disable-callee-allocated-coro-abi",
606+
llvm::cl::desc(
607+
"Override per-platform settings and don't use yield_once_2."),
608+
llvm::cl::init(false));
609+
600610
llvm::cl::opt<bool> MergeableTraps = llvm::cl::opt<bool>(
601611
"mergeable-traps",
602612
llvm::cl::desc("Enable cond_fail merging."));
@@ -918,6 +928,10 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
918928
options.EnablePackMetadataStackPromotion;
919929

920930
SILOpts.EnableAddressDependencies = options.EnableAddressDependencies;
931+
if (options.EnableCalleeAllocatedCoroAbi)
932+
SILOpts.CoroutineAccessorsUseYieldOnce2 = true;
933+
if (options.DisableCalleeAllocatedCoroAbi)
934+
SILOpts.CoroutineAccessorsUseYieldOnce2 = false;
921935
SILOpts.MergeableTraps = options.MergeableTraps;
922936

923937
if (options.OptModeFlag == OptimizationMode::NotSet) {

lib/Frontend/CompilerInvocation.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,6 +3130,16 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
31303130
Opts.EnableAddressDependencies = Args.hasFlag(
31313131
OPT_enable_address_dependencies, OPT_disable_address_dependencies,
31323132
Opts.EnableAddressDependencies);
3133+
3134+
if (LangOpts.Target.isOSDarwin() || LangOpts.Target.isOSLinux()) {
3135+
// On Darwin and Linux, use yield_once_2 by default.
3136+
Opts.CoroutineAccessorsUseYieldOnce2 = true;
3137+
}
3138+
Opts.CoroutineAccessorsUseYieldOnce2 =
3139+
Args.hasFlag(OPT_enable_callee_allocated_coro_abi,
3140+
OPT_disable_callee_allocated_coro_abi,
3141+
Opts.CoroutineAccessorsUseYieldOnce2);
3142+
31333143
Opts.MergeableTraps = Args.hasArg(OPT_mergeable_traps);
31343144

31353145
return false;

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,5 +1855,8 @@ bool SILDeclRef::isCalleeAllocatedCoroutine() const {
18551855
if (!accessor)
18561856
return false;
18571857

1858-
return requiresFeatureCoroutineAccessors(accessor->getAccessorKind());
1858+
if (!requiresFeatureCoroutineAccessors(accessor->getAccessorKind()))
1859+
return false;
1860+
1861+
return getASTContext().SILOpts.CoroutineAccessorsUseYieldOnce2;
18591862
}

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2481,8 +2481,10 @@ static CanSILFunctionType getSILFunctionType(
24812481

24822482
if (auto accessor = getAsCoroutineAccessor(constant)) {
24832483
auto origAccessor = cast<AccessorDecl>(origConstant->getDecl());
2484+
auto &ctx = origAccessor->getASTContext();
24842485
coroutineKind =
2485-
requiresFeatureCoroutineAccessors(accessor->getAccessorKind())
2486+
(requiresFeatureCoroutineAccessors(accessor->getAccessorKind()) &&
2487+
ctx.SILOpts.CoroutineAccessorsUseYieldOnce2)
24862488
? SILCoroutineKind::YieldOnce2
24872489
: SILCoroutineKind::YieldOnce;
24882490

lib/SILGen/SILGenApply.cpp

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4999,14 +4999,16 @@ class CallEmission {
49994999
FormalEvaluationScope initialWritebackScope;
50005000
std::optional<ActorIsolation> implicitActorHopTarget;
50015001
bool implicitlyThrows;
5002+
bool canUnwind;
50025003

50035004
public:
50045005
/// Create an emission for a call of the given callee.
50055006
CallEmission(SILGenFunction &SGF, Callee &&callee,
50065007
FormalEvaluationScope &&writebackScope)
50075008
: SGF(SGF), callee(std::move(callee)),
50085009
initialWritebackScope(std::move(writebackScope)),
5009-
implicitActorHopTarget(std::nullopt), implicitlyThrows(false) {}
5010+
implicitActorHopTarget(std::nullopt), implicitlyThrows(false),
5011+
canUnwind(false) {}
50105012

50115013
/// A factory method for decomposing the apply expr \p e into a call
50125014
/// emission.
@@ -5057,6 +5059,8 @@ class CallEmission {
50575059
/// function can throw or not.
50585060
void setImplicitlyThrows(bool flag) { implicitlyThrows = flag; }
50595061

5062+
void setCanUnwind(bool flag) { canUnwind = flag; }
5063+
50605064
CleanupHandle applyCoroutine(SmallVectorImpl<ManagedValue> &yields);
50615065

50625066
RValue apply(SGFContext C = SGFContext()) {
@@ -5114,9 +5118,11 @@ namespace {
51145118
/// Cleanup to end a coroutine application.
51155119
class EndCoroutineApply : public Cleanup {
51165120
SILValue ApplyToken;
5121+
bool CanUnwind;
51175122
std::vector<BeginBorrowInst *> BorrowedMoveOnlyValues;
51185123
public:
5119-
EndCoroutineApply(SILValue applyToken) : ApplyToken(applyToken) {}
5124+
EndCoroutineApply(SILValue applyToken, bool CanUnwind)
5125+
: ApplyToken(applyToken), CanUnwind(CanUnwind) {}
51205126

51215127
void setBorrowedMoveOnlyValues(ArrayRef<BeginBorrowInst *> values) {
51225128
BorrowedMoveOnlyValues.insert(BorrowedMoveOnlyValues.end(),
@@ -5129,14 +5135,7 @@ class EndCoroutineApply : public Cleanup {
51295135
SGF.B.createEndBorrow(l, *i);
51305136
SGF.B.createDestroyValue(l, (*i)->getOperand());
51315137
}
5132-
auto *beginApply =
5133-
cast<BeginApplyInst>(ApplyToken->getDefiningInstruction());
5134-
auto isCalleeAllocated = beginApply->isCalleeAllocated();
5135-
auto unwindOnCallerError =
5136-
!isCalleeAllocated ||
5137-
SGF.SGM.getASTContext().LangOpts.hasFeature(
5138-
Feature::CoroutineAccessorsUnwindOnCallerError);
5139-
if (forUnwind && unwindOnCallerError) {
5138+
if (forUnwind && CanUnwind) {
51405139
SGF.B.createAbortApply(l, ApplyToken);
51415140
} else {
51425141
SGF.B.createEndApply(l, ApplyToken,
@@ -5179,18 +5178,15 @@ CallEmission::applyCoroutine(SmallVectorImpl<ManagedValue> &yields) {
51795178

51805179
auto fnValue = callee.getFnValue(SGF, borrowedSelf);
51815180

5182-
return SGF.emitBeginApply(uncurriedLoc.value(), fnValue,
5181+
return SGF.emitBeginApply(uncurriedLoc.value(), fnValue, canUnwind,
51835182
callee.getSubstitutions(), uncurriedArgs,
51845183
calleeTypeInfo.substFnType, options, yields);
51855184
}
51865185

5187-
CleanupHandle
5188-
SILGenFunction::emitBeginApply(SILLocation loc, ManagedValue fn,
5189-
SubstitutionMap subs,
5190-
ArrayRef<ManagedValue> args,
5191-
CanSILFunctionType substFnType,
5192-
ApplyOptions options,
5193-
SmallVectorImpl<ManagedValue> &yields) {
5186+
CleanupHandle SILGenFunction::emitBeginApply(
5187+
SILLocation loc, ManagedValue fn, bool canUnwind, SubstitutionMap subs,
5188+
ArrayRef<ManagedValue> args, CanSILFunctionType substFnType,
5189+
ApplyOptions options, SmallVectorImpl<ManagedValue> &yields) {
51945190
// Emit the call.
51955191
SmallVector<SILValue, 4> rawResults;
51965192
emitRawApply(*this, loc, fn, subs, args, substFnType, options,
@@ -5206,7 +5202,7 @@ SILGenFunction::emitBeginApply(SILLocation loc, ManagedValue fn,
52065202

52075203
// Push a cleanup to end the application.
52085204
// TODO: destroy all the arguments at exactly this point?
5209-
Cleanups.pushCleanup<EndCoroutineApply>(token);
5205+
Cleanups.pushCleanup<EndCoroutineApply>(token, canUnwind);
52105206
auto endApplyHandle = getTopCleanup();
52115207

52125208
// Manage all the yielded values.
@@ -6183,7 +6179,7 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn,
61836179
std::tuple<MultipleValueInstructionResult *, CleanupHandle, SILValue,
61846180
CleanupHandle>
61856181
SILGenFunction::emitBeginApplyWithRethrow(SILLocation loc, SILValue fn,
6186-
SILType substFnType,
6182+
SILType substFnType, bool canUnwind,
61876183
SubstitutionMap subs,
61886184
ArrayRef<SILValue> args,
61896185
SmallVectorImpl<SILValue> &yields) {
@@ -6208,7 +6204,7 @@ SILGenFunction::emitBeginApplyWithRethrow(SILLocation loc, SILValue fn,
62086204
deallocCleanup = enterDeallocStackCleanup(allocation);
62096205
}
62106206

6211-
Cleanups.pushCleanup<EndCoroutineApply>(token);
6207+
Cleanups.pushCleanup<EndCoroutineApply>(token, canUnwind);
62126208
auto abortCleanup = Cleanups.getTopCleanup();
62136209

62146210
return {token, abortCleanup, allocation, deallocCleanup};
@@ -7561,6 +7557,21 @@ ManagedValue SILGenFunction::emitAddressorAccessor(
75617557
return ManagedValue::forLValue(address);
75627558
}
75637559

7560+
bool SILGenFunction::canUnwindAccessorDeclRef(SILDeclRef accessorRef) {
7561+
auto *accessor =
7562+
dyn_cast_or_null<AccessorDecl>(accessorRef.getAbstractFunctionDecl());
7563+
ASSERT(accessor && "only accessors can unwind");
7564+
auto kind = accessor->getAccessorKind();
7565+
ASSERT(isYieldingAccessor(kind) && "only yielding accessors can unwind");
7566+
if (!requiresFeatureCoroutineAccessors(kind)) {
7567+
// _read and _modify can unwind
7568+
return true;
7569+
}
7570+
// Coroutine accessors can only unwind with the experimental feature.
7571+
return getASTContext().LangOpts.hasFeature(
7572+
Feature::CoroutineAccessorsUnwindOnCallerError);
7573+
}
7574+
75647575
CleanupHandle
75657576
SILGenFunction::emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
75667577
SubstitutionMap substitutions,
@@ -7596,6 +7607,8 @@ SILGenFunction::emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
75967607

75977608
emission.addCallSite(loc, std::move(subscriptIndices));
75987609

7610+
emission.setCanUnwind(canUnwindAccessorDeclRef(accessor));
7611+
75997612
auto endApplyHandle = emission.applyCoroutine(yields);
76007613

76017614
return endApplyHandle;

lib/SILGen/SILGenFunction.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
20342034
PreparedArguments &&optionalSubscripts,
20352035
SILType addressType, bool isOnSelfParameter);
20362036

2037+
bool canUnwindAccessorDeclRef(SILDeclRef accessorRef);
20372038
CleanupHandle emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
20382039
SubstitutionMap substitutions,
20392040
ArgumentSource &&optionalSelfValue,
@@ -2301,8 +2302,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
23012302
PreparedArguments &&args, Type overriddenSelfType,
23022303
SGFContext ctx);
23032304

2304-
CleanupHandle emitBeginApply(SILLocation loc, ManagedValue fn,
2305-
SubstitutionMap subs, ArrayRef<ManagedValue> args,
2305+
CleanupHandle emitBeginApply(SILLocation loc, ManagedValue fn, bool canUnwind,
2306+
SubstitutionMap subs,
2307+
ArrayRef<ManagedValue> args,
23062308
CanSILFunctionType substFnType,
23072309
ApplyOptions options,
23082310
SmallVectorImpl<ManagedValue> &yields);
@@ -2315,7 +2317,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
23152317
std::tuple<MultipleValueInstructionResult *, CleanupHandle, SILValue,
23162318
CleanupHandle>
23172319
emitBeginApplyWithRethrow(SILLocation loc, SILValue fn, SILType substFnType,
2318-
SubstitutionMap subs, ArrayRef<SILValue> args,
2320+
bool canUnwind, SubstitutionMap subs,
2321+
ArrayRef<SILValue> args,
23192322
SmallVectorImpl<SILValue> &yields);
23202323
void emitEndApplyWithRethrow(SILLocation loc,
23212324
MultipleValueInstructionResult *token,

lib/SILGen/SILGenLValue.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,9 +2535,9 @@ namespace {
25352535

25362536
// Perform the begin_apply.
25372537
SmallVector<ManagedValue, 1> yields;
2538-
auto cleanup =
2539-
SGF.emitBeginApply(loc, projectFnRef, subs, { base, keyPathValue },
2540-
substFnType, ApplyOptions(), yields);
2538+
auto cleanup = SGF.emitBeginApply(loc, projectFnRef, /*canUnwind=*/true,
2539+
subs, {base, keyPathValue}, substFnType,
2540+
ApplyOptions(), yields);
25412541

25422542
// Push an operation to do the end_apply.
25432543
pushEndApplyWriteback(SGF, loc, cleanup, getTypeData());

lib/SILGen/SILGenPoly.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7045,8 +7045,8 @@ SILGenFunction::emitVTableThunk(SILDeclRef base,
70457045
case SILCoroutineKind::YieldOnce2: {
70467046
SmallVector<SILValue, 4> derivedYields;
70477047
auto tokenAndCleanups = emitBeginApplyWithRethrow(
7048-
loc, derivedRef, SILType::getPrimitiveObjectType(derivedFTy), subs,
7049-
args, derivedYields);
7048+
loc, derivedRef, SILType::getPrimitiveObjectType(derivedFTy),
7049+
canUnwindAccessorDeclRef(base), subs, args, derivedYields);
70507050
auto token = std::get<0>(tokenAndCleanups);
70517051
auto abortCleanup = std::get<1>(tokenAndCleanups);
70527052
auto allocation = std::get<2>(tokenAndCleanups);
@@ -7513,7 +7513,8 @@ void SILGenFunction::emitProtocolWitness(
75137513
case SILCoroutineKind::YieldOnce2: {
75147514
SmallVector<SILValue, 4> witnessYields;
75157515
auto tokenAndCleanups = emitBeginApplyWithRethrow(
7516-
loc, witnessFnRef, witnessSILTy, witnessSubs, args, witnessYields);
7516+
loc, witnessFnRef, witnessSILTy, canUnwindAccessorDeclRef(requirement),
7517+
witnessSubs, args, witnessYields);
75177518
auto token = std::get<0>(tokenAndCleanups);
75187519
auto abortCleanup = std::get<1>(tokenAndCleanups);
75197520
auto allocation = std::get<2>(tokenAndCleanups);

test/IRGen/coroutine_accessors.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %target-swift-emit-irgen \
22
// RUN: %s \
3+
// RUN: -enable-callee-allocated-coro-abi \
34
// RUN: -enable-experimental-feature CoroutineAccessors \
45
// RUN: | %IRGenFileCheck %s
56

test/IRGen/coroutine_accessors_backdeploy_async_56.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %target-swift-emit-irgen \
22
// RUN: %s \
3+
// RUN: -enable-callee-allocated-coro-abi \
34
// RUN: -module-name backdep \
45
// RUN: -target %target-swift-5.6-abi-triple \
56
// RUN: -Onone \

test/IRGen/coroutine_accessors_backdeploy_async_57.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %target-swift-emit-irgen \
22
// RUN: %s \
3+
// RUN: -enable-callee-allocated-coro-abi \
34
// RUN: -module-name backdep \
45
// RUN: -target %target-swift-5.7-abi-triple \
56
// RUN: -Onone \

test/IRGen/coroutine_accessors_popless.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-swift-emit-irgen \
22
// RUN: %s \
33
// RUN: -Onone \
4+
// RUN: -enable-callee-allocated-coro-abi \
45
// RUN: -enable-experimental-feature CoroutineAccessors \
56
// RUN: -enable-arm64-corocc \
67
// RUN: -enable-x86_64-corocc \

test/IRGen/default_override.sil

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %target-swift-frontend \
22
// RUN: %s \
3+
// RUN: -enable-callee-allocated-coro-abi \
34
// RUN: -module-name Library \
45
// RUN: -emit-ir \
56
// RUN: -enable-experimental-feature CoroutineAccessors \

test/IRGen/run-coroutine_accessors.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@
9494
// UNSUPPORTED: wasm
9595
// UNSUPPORTED: OS=wasi
9696
// UNSUPPORTED: CPU=wasm32
97-
// TODO: CoroutineAccessors: Enable on Windows.
98-
// UNSUPPORTED: OS=windows-msvc
9997

10098
// REQUIRES: swift_feature_CoroutineAccessors
10199

test/Interpreter/coroutine_accessors_default_implementations.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// RUN: %target-swift-frontend \
66
// RUN: %t/Library.swift \
77
// RUN: %t/LibImpl.underscored.swift \
8+
// RUN: -enable-callee-allocated-coro-abi \
89
// RUN: -emit-module \
910
// RUN: -module-name Library \
1011
// RUN: -parse-as-library \
@@ -13,6 +14,7 @@
1314

1415
// RUN: %target-swift-frontend \
1516
// RUN: %t/Executable.swift \
17+
// RUN: -enable-callee-allocated-coro-abi \
1618
// RUN: -c \
1719
// RUN: -parse-as-library \
1820
// RUN: -module-name Executable \
@@ -22,6 +24,7 @@
2224
// RUN: %target-build-swift-dylib(%t/%target-library-name(Library)) \
2325
// RUN: %t/Library.swift \
2426
// RUN: %t/LibImpl.nonunderscored.swift \
27+
// RUN: -Xfrontend -enable-callee-allocated-coro-abi \
2528
// RUN: -emit-module \
2629
// RUN: -enable-library-evolution \
2730
// RUN: -enable-experimental-feature CoroutineAccessors \

0 commit comments

Comments
 (0)