Skip to content

Commit 0063af5

Browse files
Merge pull request #80520 from nate-chandler/general-coro/20250403/1
[CoroutineAccessors] Use async bit in descriptors.
2 parents 1f80e50 + 66ca0d8 commit 0063af5

File tree

3 files changed

+42
-29
lines changed

3 files changed

+42
-29
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,6 @@ class MethodDescriptorFlags {
374374
Setter,
375375
ModifyCoroutine,
376376
ReadCoroutine,
377-
Read2Coroutine,
378-
Modify2Coroutine,
379377
};
380378

381379
private:
@@ -438,23 +436,27 @@ class MethodDescriptorFlags {
438436
/// Note that 'init' is not considered an instance member.
439437
bool isInstance() const { return Value & IsInstanceMask; }
440438

441-
bool isAsync() const { return Value & IsAsyncMask; }
439+
bool _hasAsyncBitSet() const { return Value & IsAsyncMask; }
442440

443-
bool isCalleeAllocatedCoroutine() const {
441+
bool isAsync() const { return !isCoroutine() && _hasAsyncBitSet(); }
442+
443+
bool isCoroutine() const {
444444
switch (getKind()) {
445445
case Kind::Method:
446446
case Kind::Init:
447447
case Kind::Getter:
448448
case Kind::Setter:
449+
return false;
449450
case Kind::ModifyCoroutine:
450451
case Kind::ReadCoroutine:
451-
return false;
452-
case Kind::Read2Coroutine:
453-
case Kind::Modify2Coroutine:
454452
return true;
455453
}
456454
}
457455

456+
bool isCalleeAllocatedCoroutine() const {
457+
return isCoroutine() && _hasAsyncBitSet();
458+
}
459+
458460
bool isData() const { return isAsync() || isCalleeAllocatedCoroutine(); }
459461

460462
uint16_t getExtraDiscriminator() const {
@@ -615,8 +617,6 @@ class ProtocolRequirementFlags {
615617
ModifyCoroutine,
616618
AssociatedTypeAccessFunction,
617619
AssociatedConformanceAccessFunction,
618-
Read2Coroutine,
619-
Modify2Coroutine,
620620
};
621621

622622
private:
@@ -666,26 +666,30 @@ class ProtocolRequirementFlags {
666666
/// Note that 'init' is not considered an instance member.
667667
bool isInstance() const { return Value & IsInstanceMask; }
668668

669-
bool isAsync() const { return Value & IsAsyncMask; }
669+
bool _hasAsyncBitSet() const { return Value & IsAsyncMask; }
670670

671-
bool isCalleeAllocatedCoroutine() const {
671+
bool isAsync() const { return !isCoroutine() && _hasAsyncBitSet(); }
672+
673+
bool isCoroutine() const {
672674
switch (getKind()) {
673675
case Kind::BaseProtocol:
674676
case Kind::Method:
675677
case Kind::Init:
676678
case Kind::Getter:
677679
case Kind::Setter:
678-
case Kind::ReadCoroutine:
679-
case Kind::ModifyCoroutine:
680680
case Kind::AssociatedTypeAccessFunction:
681681
case Kind::AssociatedConformanceAccessFunction:
682682
return false;
683-
case Kind::Read2Coroutine:
684-
case Kind::Modify2Coroutine:
683+
case Kind::ReadCoroutine:
684+
case Kind::ModifyCoroutine:
685685
return true;
686686
}
687687
}
688688

689+
bool isCalleeAllocatedCoroutine() const {
690+
return isCoroutine() && _hasAsyncBitSet();
691+
}
692+
689693
bool isData() const { return isAsync() || isCalleeAllocatedCoroutine(); }
690694

691695
bool isSignedWithAddress() const {

lib/IRGen/GenMeta.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,22 +255,24 @@ static Flags getMethodDescriptorFlags(ValueDecl *fn) {
255255
return flags;
256256
}
257257

258-
auto kind = [&] {
258+
auto kindAndIsCalleeAllocatedCoroutine =
259+
[&]() -> std::pair<typename Flags::Kind, bool> {
259260
auto accessor = dyn_cast<AccessorDecl>(fn);
260-
if (!accessor) return Flags::Kind::Method;
261+
if (!accessor)
262+
return {Flags::Kind::Method, false};
261263
switch (accessor->getAccessorKind()) {
262264
case AccessorKind::Get:
263-
return Flags::Kind::Getter;
265+
return {Flags::Kind::Getter, false};
264266
case AccessorKind::Set:
265-
return Flags::Kind::Setter;
267+
return {Flags::Kind::Setter, false};
266268
case AccessorKind::Read:
267-
return Flags::Kind::ReadCoroutine;
269+
return {Flags::Kind::ReadCoroutine, false};
268270
case AccessorKind::Read2:
269-
return Flags::Kind::Read2Coroutine;
271+
return {Flags::Kind::ReadCoroutine, true};
270272
case AccessorKind::Modify:
271-
return Flags::Kind::ModifyCoroutine;
273+
return {Flags::Kind::ModifyCoroutine, false};
272274
case AccessorKind::Modify2:
273-
return Flags::Kind::Modify2Coroutine;
275+
return {Flags::Kind::ModifyCoroutine, true};
274276
#define OPAQUE_ACCESSOR(ID, KEYWORD)
275277
#define ACCESSOR(ID) \
276278
case AccessorKind::ID:
@@ -280,9 +282,20 @@ static Flags getMethodDescriptorFlags(ValueDecl *fn) {
280282
}
281283
llvm_unreachable("bad kind");
282284
}();
283-
bool hasAsync = false;
285+
auto kind = kindAndIsCalleeAllocatedCoroutine.first;
286+
287+
// Because no async old-ABI accessor coroutines exist or presumably ever will
288+
// (if async coroutines accessors are added, they will presumably be new-ABI),
289+
// the pairs {Flags::Kind::ReadCoroutine, isAsync} and
290+
// {Flags::Kind::ModifyCoroutine, isAsync} can't mean "async old-ABI
291+
// accessor coroutine". As such, we repurpose that pair to mean "new-ABI
292+
// accessor coroutine". This has the important virtue of resulting in ptrauth
293+
// authing/signing coro function pointers as data on old OSes where the bit
294+
// means "async" and where adding new accessor kinds requires a back
295+
// deployment library.
296+
bool hasAsync = kindAndIsCalleeAllocatedCoroutine.second;
284297
if (auto *afd = dyn_cast<AbstractFunctionDecl>(fn))
285-
hasAsync = afd->hasAsync();
298+
hasAsync |= afd->hasAsync();
286299
return Flags(kind).withIsInstance(!fn->isStatic()).withIsAsync(hasAsync);
287300
}
288301

stdlib/public/runtime/Metadata.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6162,9 +6162,7 @@ static void initProtocolWitness(void **slot, void *witness,
61626162
case ProtocolRequirementFlags::Kind::Getter:
61636163
case ProtocolRequirementFlags::Kind::Setter:
61646164
case ProtocolRequirementFlags::Kind::ReadCoroutine:
6165-
case ProtocolRequirementFlags::Kind::Read2Coroutine:
61666165
case ProtocolRequirementFlags::Kind::ModifyCoroutine:
6167-
case ProtocolRequirementFlags::Kind::Modify2Coroutine:
61686166
swift_ptrauth_init_code_or_data(slot, witness,
61696167
reqt.Flags.getExtraDiscriminator(),
61706168
!reqt.Flags.isData());
@@ -6205,9 +6203,7 @@ static void copyProtocolWitness(void **dest, void * const *src,
62056203
case ProtocolRequirementFlags::Kind::Getter:
62066204
case ProtocolRequirementFlags::Kind::Setter:
62076205
case ProtocolRequirementFlags::Kind::ReadCoroutine:
6208-
case ProtocolRequirementFlags::Kind::Read2Coroutine:
62096206
case ProtocolRequirementFlags::Kind::ModifyCoroutine:
6210-
case ProtocolRequirementFlags::Kind::Modify2Coroutine:
62116207
swift_ptrauth_copy_code_or_data(
62126208
dest, src, reqt.Flags.getExtraDiscriminator(), !reqt.Flags.isData(),
62136209
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable

0 commit comments

Comments
 (0)