Skip to content

Commit 49a2831

Browse files
committed
[CoroutineAccessors] Old ABI may be used via flag.
Add a setting to IRGenOptions and key off of it to emit yield_once_2 coroutines using either (1) the same code-path as yield_once coroutines or (2) a new, not-yet implemented code-path. Add flags to set the value in both directions. During bringup, by default, use the existing caller-allocated ABI.
1 parent 11b5d27 commit 49a2831

File tree

7 files changed

+109
-22
lines changed

7 files changed

+109
-22
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ class IRGenOptions {
485485

486486
unsigned EmitAsyncFramePushPopMetadata : 1;
487487

488+
// Whether to use the yield_once ABI when emitting yield_once_2 coroutines.
489+
unsigned EmitYieldOnce2AsYieldOnce : 1;
490+
488491
// Whether to force emission of a frame for all async functions
489492
// (LLVM's 'frame-pointer=all').
490493
unsigned AsyncFramePointerAll : 1;
@@ -577,10 +580,10 @@ class IRGenOptions {
577580
EmitGenericRODatas(true), NoPreallocatedInstantiationCaches(false),
578581
DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false),
579582
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
580-
UseFragileResilientProtocolWitnesses(false),
581-
EnableHotColdSplit(false), EmitAsyncFramePushPopMetadata(false),
582-
AsyncFramePointerAll(false),
583-
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),
583+
UseFragileResilientProtocolWitnesses(false), EnableHotColdSplit(false),
584+
EmitAsyncFramePushPopMetadata(false), EmitYieldOnce2AsYieldOnce(true),
585+
AsyncFramePointerAll(false), CmdArgs(),
586+
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
584587
TypeInfoFilter(TypeInfoDumpFilter::All),
585588
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),
586589
CASObjMode(llvm::CASBackendMode::Native) {

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,9 @@ SUPPRESSIBLE_EXPERIMENTAL_FEATURE(CoroutineAccessors, true)
430430
/// modify/read single-yield coroutines always execute code post-yield code
431431
EXPERIMENTAL_FEATURE(CoroutineAccessorsUnwindOnCallerError, false)
432432

433+
/// modify/read coroutines use the callee-allocated ABI
434+
EXPERIMENTAL_FEATURE(CoroutineAccessorsAllocateInCallee, false)
435+
433436
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
434437
#undef EXPERIMENTAL_FEATURE
435438
#undef UPCOMING_FEATURE

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ UNINTERESTING_FEATURE(WarnUnsafe)
297297
UNINTERESTING_FEATURE(SafeInterop)
298298
UNINTERESTING_FEATURE(AssumeResilientCxxTypes)
299299
UNINTERESTING_FEATURE(CoroutineAccessorsUnwindOnCallerError)
300+
UNINTERESTING_FEATURE(CoroutineAccessorsAllocateInCallee)
300301

301302
bool swift::usesFeatureIsolatedDeinit(const Decl *decl) {
302303
if (auto cd = dyn_cast<ClassDecl>(decl)) {

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,6 +3473,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
34733473
Args.hasFlag(OPT_enable_fragile_resilient_protocol_witnesses,
34743474
OPT_disable_fragile_resilient_protocol_witnesses,
34753475
Opts.UseFragileResilientProtocolWitnesses);
3476+
Opts.EmitYieldOnce2AsYieldOnce =
3477+
!LangOpts.hasFeature(Feature::CoroutineAccessorsAllocateInCallee);
34763478
Opts.EnableHotColdSplit =
34773479
Args.hasFlag(OPT_enable_split_cold_code,
34783480
OPT_disable_split_cold_code,

lib/IRGen/GenCall.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,15 @@ static Size getCoroutineContextSize(IRGenModule &IGM,
7979
switch (fnType->getCoroutineKind()) {
8080
case SILCoroutineKind::None:
8181
llvm_unreachable("expand a coroutine");
82+
case SILCoroutineKind::YieldOnce2:
83+
if (IGM.IRGen.Opts.EmitYieldOnce2AsYieldOnce) {
84+
LLVM_FALLTHROUGH;
85+
} else {
86+
llvm::report_fatal_error(
87+
"callee allocated coroutines do not have fixed-size buffers");
88+
}
8289
case SILCoroutineKind::YieldOnce:
8390
return getYieldOnceCoroutineBufferSize(IGM);
84-
case SILCoroutineKind::YieldOnce2:
85-
llvm::report_fatal_error(
86-
"callee allocated coroutines do not have fixed-size buffers");
8791
case SILCoroutineKind::YieldMany:
8892
return getYieldManyCoroutineBufferSize(IGM);
8993
}
@@ -1811,8 +1815,13 @@ void SignatureExpansion::expandParameters(
18111815
// First, if this is a coroutine, add the coroutine-context parameter.
18121816
switch (FnType->getCoroutineKind()) {
18131817
case SILCoroutineKind::None:
1814-
case SILCoroutineKind::YieldOnce2:
18151818
break;
1819+
case SILCoroutineKind::YieldOnce2:
1820+
if (IGM.IRGen.Opts.EmitYieldOnce2AsYieldOnce) {
1821+
LLVM_FALLTHROUGH;
1822+
} else {
1823+
break;
1824+
}
18161825

18171826
case SILCoroutineKind::YieldOnce:
18181827
case SILCoroutineKind::YieldMany:
@@ -2522,14 +2531,18 @@ class SyncCallEmission final : public CallEmission {
25222531

25232532
// Pass along the coroutine buffer.
25242533
switch (origCalleeType->getCoroutineKind()) {
2525-
case SILCoroutineKind::YieldMany:
2534+
case SILCoroutineKind::YieldOnce2:
2535+
if (IGF.IGM.IRGen.Opts.EmitYieldOnce2AsYieldOnce) {
2536+
LLVM_FALLTHROUGH;
2537+
} else {
2538+
llvm::report_fatal_error("unimplemented");
2539+
break;
2540+
}
25262541
case SILCoroutineKind::YieldOnce:
2542+
case SILCoroutineKind::YieldMany:
25272543
original.transferInto(adjusted, 1);
25282544
break;
25292545

2530-
case SILCoroutineKind::YieldOnce2:
2531-
llvm::report_fatal_error("unimplemented");
2532-
break;
25332546
case SILCoroutineKind::None:
25342547
break;
25352548
}
@@ -4446,12 +4459,16 @@ irgen::getCoroutineResumeFunctionPointerAuth(IRGenModule &IGM,
44464459
case SILCoroutineKind::YieldMany:
44474460
return { IGM.getOptions().PointerAuth.YieldManyResumeFunctions,
44484461
PointerAuthEntity::forYieldTypes(fnType) };
4462+
case SILCoroutineKind::YieldOnce2:
4463+
if (IGM.IRGen.Opts.EmitYieldOnce2AsYieldOnce) {
4464+
LLVM_FALLTHROUGH;
4465+
} else {
4466+
return {IGM.getOptions().PointerAuth.YieldOnce2ResumeFunctions,
4467+
PointerAuthEntity::forYieldTypes(fnType)};
4468+
}
44494469
case SILCoroutineKind::YieldOnce:
44504470
return { IGM.getOptions().PointerAuth.YieldOnceResumeFunctions,
44514471
PointerAuthEntity::forYieldTypes(fnType) };
4452-
case SILCoroutineKind::YieldOnce2:
4453-
return {IGM.getOptions().PointerAuth.YieldOnce2ResumeFunctions,
4454-
PointerAuthEntity::forYieldTypes(fnType)};
44554472
}
44564473
llvm_unreachable("bad coroutine kind");
44574474
}

lib/IRGen/IRGenSIL.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,12 +2130,16 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
21302130
switch (funcTy->getCoroutineKind()) {
21312131
case SILCoroutineKind::None:
21322132
break;
2133+
case SILCoroutineKind::YieldOnce2:
2134+
if (IGF.IGM.IRGen.Opts.EmitYieldOnce2AsYieldOnce) {
2135+
LLVM_FALLTHROUGH;
2136+
} else {
2137+
emitYieldOnce2CoroutineEntry(IGF, funcTy, *emission);
2138+
break;
2139+
}
21332140
case SILCoroutineKind::YieldOnce:
21342141
emitYieldOnceCoroutineEntry(IGF, funcTy, *emission);
21352142
break;
2136-
case SILCoroutineKind::YieldOnce2:
2137-
emitYieldOnce2CoroutineEntry(IGF, funcTy, *emission);
2138-
break;
21392143
case SILCoroutineKind::YieldMany:
21402144
emitYieldManyCoroutineEntry(IGF, funcTy, *emission);
21412145
break;
@@ -3786,14 +3790,18 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {
37863790
case SILCoroutineKind::None:
37873791
break;
37883792

3793+
case SILCoroutineKind::YieldOnce2:
3794+
if (IGM.IRGen.Opts.EmitYieldOnce2AsYieldOnce) {
3795+
LLVM_FALLTHROUGH;
3796+
} else {
3797+
// @yield_once_2 coroutines allocate in the callee
3798+
break;
3799+
}
3800+
37893801
case SILCoroutineKind::YieldOnce:
37903802
coroutineBuffer = emitAllocYieldOnceCoroutineBuffer(*this);
37913803
break;
37923804

3793-
case SILCoroutineKind::YieldOnce2:
3794-
// @yield_once_2 coroutines allocate in the callee
3795-
break;
3796-
37973805
case SILCoroutineKind::YieldMany:
37983806
coroutineBuffer = emitAllocYieldManyCoroutineBuffer(*this);
37993807
break;

test/IRGen/coroutine_accessors.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %target-swift-emit-irgen \
2+
// RUN: %s \
3+
// RUN: -enable-experimental-feature CoroutineAccessors \
4+
// RUN: | %IRGenFileCheck %s --check-prefix=CHECK-OLD
5+
6+
// For now, a crash is expected when attempting to use the callee-allocated ABI:
7+
// it's not implemented.
8+
// RUN: not --crash \
9+
// RUN: %target-swift-emit-irgen \
10+
// RUN: %s \
11+
// RUN: -enable-experimental-feature CoroutineAccessors \
12+
// RUN: -enable-experimental-feature CoroutineAccessorsAllocateInCallee
13+
14+
// REQUIRES: asserts
15+
16+
public struct S {
17+
public var o: any AnyObject
18+
public var _i: Int = 0
19+
20+
public var irm: Int {
21+
// CHECK-OLD-LABEL: define{{.*}} { ptr, i64 } @"$s19coroutine_accessors1SV3irmSivy"(
22+
// CHECK-OLD-SAME: ptr noalias dereferenceable(32) %0,
23+
// CHECK-OLD-SAME: ptr %1,
24+
// CHECK-OLD-SAME: i64 %2
25+
// CHECK-OLD-SAME: )
26+
// CHECK-OLD-SAME: {
27+
// CHECK-OLD: }
28+
read {
29+
yield _i
30+
}
31+
// CHECK-OLD-LABEL: define{{.*}} { ptr, ptr } @"$s19coroutine_accessors1SV3irmSivx"(
32+
// CHECK-OLD-SAME: ptr noalias dereferenceable(32) %0,
33+
// CHECK-OLD-SAME: ptr nocapture swiftself dereferenceable(16) %1
34+
// CHECK-OLD-SAME: )
35+
// CHECK-OLD-SAME: {
36+
// CHECK-OLD: }
37+
modify {
38+
yield &_i
39+
}
40+
// CHECK-OLD-LABEL: define{{.*}} i64 @"$s19coroutine_accessors1SV3irmSivg"(
41+
// CHECK-OLD-SAME: ptr %0,
42+
// CHECK-OLD-SAME: i64 %1
43+
// CHECK-OLD-SAME: ) #0
44+
// CHECK-OLD-SAME: {
45+
// CHECK-OLD: }
46+
// CHECK-OLD-LABEL: define{{.*}} void @"$s19coroutine_accessors1SV3irmSivs"(
47+
// CHECK-OLD-SAME: i64 %0,
48+
// CHECK-OLD-SAME: ptr nocapture swiftself dereferenceable(16) %1
49+
// CHECK-OLD-SAME: )
50+
// CHECK-OLD-SAME: {
51+
// CHECK-OLD: }
52+
} // public var irm
53+
}

0 commit comments

Comments
 (0)