Skip to content

Commit 6581fec

Browse files
committed
[CoroutineAccessors] PtrAuth.
1 parent 35d06c3 commit 6581fec

File tree

14 files changed

+147
-25
lines changed

14 files changed

+147
-25
lines changed

include/swift/ABI/Metadata.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5094,9 +5094,9 @@ struct DynamicReplacementKey {
50945094
uint16_t getExtraDiscriminator() const {
50955095
return flags & 0x0000FFFF;
50965096
}
5097-
bool isAsync() const {
5098-
return ((flags >> 16 ) & 0x1);
5099-
}
5097+
bool isAsync() const { return ((flags >> 16) & 0x1); }
5098+
bool isCalleeAllocatedCoroutine() const { return ((flags >> 16) & 0x2); }
5099+
bool isData() const { return isAsync() || isCalleeAllocatedCoroutine(); }
51005100
};
51015101

51025102
/// A record describing a dynamic function replacement.

include/swift/ABI/MetadataValues.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,23 @@ class MethodDescriptorFlags {
438438

439439
bool isAsync() const { return Value & IsAsyncMask; }
440440

441+
bool isCalleeAllocatedCoroutine() const {
442+
switch (getKind()) {
443+
case Kind::Method:
444+
case Kind::Init:
445+
case Kind::Getter:
446+
case Kind::Setter:
447+
case Kind::ModifyCoroutine:
448+
case Kind::ReadCoroutine:
449+
return false;
450+
case Kind::Read2Coroutine:
451+
case Kind::Modify2Coroutine:
452+
return true;
453+
}
454+
}
455+
456+
bool isData() const { return isAsync() || isCalleeAllocatedCoroutine(); }
457+
441458
uint16_t getExtraDiscriminator() const {
442459
return (Value >> ExtraDiscriminatorShift);
443460
}
@@ -649,6 +666,26 @@ class ProtocolRequirementFlags {
649666

650667
bool isAsync() const { return Value & IsAsyncMask; }
651668

669+
bool isCalleeAllocatedCoroutine() const {
670+
switch (getKind()) {
671+
case Kind::BaseProtocol:
672+
case Kind::Method:
673+
case Kind::Init:
674+
case Kind::Getter:
675+
case Kind::Setter:
676+
case Kind::ReadCoroutine:
677+
case Kind::ModifyCoroutine:
678+
case Kind::AssociatedTypeAccessFunction:
679+
case Kind::AssociatedConformanceAccessFunction:
680+
return false;
681+
case Kind::Read2Coroutine:
682+
case Kind::Modify2Coroutine:
683+
return true;
684+
}
685+
}
686+
687+
bool isData() const { return isAsync() || isCalleeAllocatedCoroutine(); }
688+
652689
bool isSignedWithAddress() const {
653690
return getKind() != Kind::BaseProtocol;
654691
}

include/swift/AST/IRGenOptions.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,26 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
230230

231231
/// Type layout string descriminator.
232232
PointerAuthSchema TypeLayoutString;
233+
234+
/// Like SwiftFunctionPointers but for use with CoroFunctionPointer values.
235+
PointerAuthSchema CoroSwiftFunctionPointers;
236+
237+
/// Like SwiftClassMethods but for use with CoroFunctionPointer values.
238+
PointerAuthSchema CoroSwiftClassMethods;
239+
240+
/// Like ProtocolWitnesses but for use with CoroFunctionPointer values.
241+
PointerAuthSchema CoroProtocolWitnesses;
242+
243+
/// Like SwiftClassMethodPointers but for use with CoroFunctionPointer
244+
/// values.
245+
PointerAuthSchema CoroSwiftClassMethodPointers;
246+
247+
/// Like SwiftDynamicReplacements but for use with CoroFunctionPointer
248+
/// values.
249+
PointerAuthSchema CoroSwiftDynamicReplacements;
250+
251+
/// Like PartialApplyCapture but for use with CoroFunctionPointer values.
252+
PointerAuthSchema CoroPartialApplyCapture;
233253
};
234254

235255
enum class JITDebugArtifact : unsigned {

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,8 @@ FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF,
30933093
auto fnPtr = emitVTableSlotLoad(IGF, slot, method, signature);
30943094
auto &schema = methodType->isAsync()
30953095
? IGF.getOptions().PointerAuth.AsyncSwiftClassMethods
3096+
: methodType->isCalleeAllocatedCoroutine()
3097+
? IGF.getOptions().PointerAuth.CoroSwiftClassMethods
30963098
: IGF.getOptions().PointerAuth.SwiftClassMethods;
30973099
auto authInfo =
30983100
PointerAuthInfo::emit(IGF, schema, slot.getAddress(), method);

lib/IRGen/GenDecl.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1823,9 +1823,15 @@ static llvm::GlobalVariable *getChainEntryForDynamicReplacement(
18231823
IGM.DynamicReplacementLinkEntryTy, linkEntry, indices);
18241824
bool isAsyncFunction =
18251825
entity.hasSILFunction() && entity.getSILFunction()->isAsync();
1826+
bool isCalleeAllocatedCoroutine =
1827+
entity.hasSILFunction() && entity.getSILFunction()
1828+
->getLoweredFunctionType()
1829+
->isCalleeAllocatedCoroutine();
18261830
auto &schema =
18271831
isAsyncFunction
18281832
? IGM.getOptions().PointerAuth.AsyncSwiftDynamicReplacements
1833+
: isCalleeAllocatedCoroutine
1834+
? IGM.getOptions().PointerAuth.CoroSwiftDynamicReplacements
18291835
: IGM.getOptions().PointerAuth.SwiftDynamicReplacements;
18301836
assert(entity.hasSILFunction() || entity.isOpaqueTypeDescriptorAccessor());
18311837
auto authEntity = entity.hasSILFunction()
@@ -2945,8 +2951,14 @@ static llvm::GlobalVariable *createGlobalForDynamicReplacementFunctionKey(
29452951
B.addRelativeAddress(linkEntry);
29462952
bool isAsyncFunction =
29472953
keyEntity.hasSILFunction() && keyEntity.getSILFunction()->isAsync();
2954+
bool isCalleeAllocatedCoroutine =
2955+
keyEntity.hasSILFunction() && keyEntity.getSILFunction()
2956+
->getLoweredFunctionType()
2957+
->isCalleeAllocatedCoroutine();
29482958
auto schema = isAsyncFunction
29492959
? IGM.getOptions().PointerAuth.AsyncSwiftDynamicReplacements
2960+
: isCalleeAllocatedCoroutine
2961+
? IGM.getOptions().PointerAuth.CoroSwiftDynamicReplacements
29502962
: IGM.getOptions().PointerAuth.SwiftDynamicReplacements;
29512963
if (schema) {
29522964
assert(keyEntity.hasSILFunction() ||
@@ -2957,7 +2969,9 @@ static llvm::GlobalVariable *createGlobalForDynamicReplacementFunctionKey(
29572969
B.addInt32((uint32_t)PointerAuthInfo::getOtherDiscriminator(IGM, schema,
29582970
authEntity)
29592971
->getZExtValue() |
2960-
((uint32_t)isAsyncFunction ? 0x10000 : 0x0));
2972+
((uint32_t)isAsyncFunction ? 0x10000
2973+
: isCalleeAllocatedCoroutine ? 0x20000
2974+
: 0x0));
29612975
} else
29622976
B.addInt32(0);
29632977
B.finishAndSetAsInitializer(key);
@@ -3009,6 +3023,8 @@ void IRGenModule::createReplaceableProlog(IRGenFunction &IGF, SILFunction *f) {
30093023

30103024
auto &schema = f->isAsync()
30113025
? getOptions().PointerAuth.AsyncSwiftDynamicReplacements
3026+
: f->getLoweredFunctionType()->isCalleeAllocatedCoroutine()
3027+
? getOptions().PointerAuth.CoroSwiftDynamicReplacements
30123028
: getOptions().PointerAuth.SwiftDynamicReplacements;
30133029
llvm::Value *ReplFn = nullptr, *hasReplFn = nullptr;
30143030

@@ -3227,9 +3243,15 @@ static void emitDynamicallyReplaceableThunk(IRGenModule &IGM,
32273243
forwardedArgs.push_back(&arg);
32283244
bool isAsyncFunction =
32293245
keyEntity.hasSILFunction() && keyEntity.getSILFunction()->isAsync();
3246+
bool isCalleeAllocatedCoroutine =
3247+
keyEntity.hasSILFunction() && keyEntity.getSILFunction()
3248+
->getLoweredFunctionType()
3249+
->isCalleeAllocatedCoroutine();
32303250
auto &schema =
32313251
isAsyncFunction
32323252
? IGM.getOptions().PointerAuth.AsyncSwiftDynamicReplacements
3253+
: isCalleeAllocatedCoroutine
3254+
? IGM.getOptions().PointerAuth.CoroSwiftDynamicReplacements
32333255
: IGM.getOptions().PointerAuth.SwiftDynamicReplacements;
32343256
assert(keyEntity.hasSILFunction() ||
32353257
keyEntity.isOpaqueTypeDescriptorAccessor());
@@ -3356,6 +3378,8 @@ void IRGenModule::emitDynamicReplacementOriginalFunctionThunk(SILFunction *f) {
33563378

33573379
auto &schema = f->isAsync()
33583380
? getOptions().PointerAuth.AsyncSwiftDynamicReplacements
3381+
: f->getLoweredFunctionType()->isCalleeAllocatedCoroutine()
3382+
? getOptions().PointerAuth.CoroSwiftDynamicReplacements
33593383
: getOptions().PointerAuth.SwiftDynamicReplacements;
33603384
auto authInfo = PointerAuthInfo::emit(
33613385
IGF, schema, fnPtrAddr,

lib/IRGen/GenFunc.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,6 +2148,8 @@ static llvm::Value *emitPartialApplicationForwarder(
21482148
subIGF,
21492149
origType->isAsync()
21502150
? IGM.getOptions().PointerAuth.AsyncPartialApplyCapture
2151+
: origType->isCalleeAllocatedCoroutine()
2152+
? IGM.getOptions().PointerAuth.CoroPartialApplyCapture
21512153
: IGM.getOptions().PointerAuth.PartialApplyCapture,
21522154
lastCapturedFieldPtr, PointerAuthEntity::Special::PartialApplyCapture);
21532155

@@ -2158,10 +2160,7 @@ static llvm::Value *emitPartialApplicationForwarder(
21582160
// It comes out of the context as an i8*. Cast to the function type.
21592161
fnPtr = subIGF.Builder.CreateBitCast(fnPtr, fnTy);
21602162

2161-
return FunctionPointer::createSigned(
2162-
origType->isAsync() ? FunctionPointer::Kind::AsyncFunctionPointer
2163-
: FunctionPointer::Kind::Function,
2164-
fnPtr, authInfo, origSig);
2163+
return FunctionPointer::createSigned(origType, fnPtr, authInfo, origSig);
21652164
}();
21662165

21672166
if (origType->isAsync())
@@ -2565,6 +2564,8 @@ std::optional<StackAddress> irgen::emitFunctionPartialApplication(
25652564
if (auto &schema =
25662565
origType->isAsync()
25672566
? IGF.getOptions().PointerAuth.AsyncPartialApplyCapture
2567+
: origType->isCalleeAllocatedCoroutine()
2568+
? IGF.getOptions().PointerAuth.CoroPartialApplyCapture
25682569
: IGF.getOptions().PointerAuth.PartialApplyCapture) {
25692570
auto schemaAuthInfo = PointerAuthInfo::emit(
25702571
IGF, schema, fieldAddr.getAddress(),

lib/IRGen/GenMeta.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,15 @@ static void buildMethodDescriptorFields(IRGenModule &IGM,
298298
if (func->shouldUseObjCDispatch())
299299
flags = flags.withIsDynamic(true);
300300

301+
auto *accessor = dyn_cast<AccessorDecl>(func);
302+
301303
// Include the pointer-auth discriminator.
302-
if (auto &schema = func->hasAsync()
303-
? IGM.getOptions().PointerAuth.AsyncSwiftClassMethods
304-
: IGM.getOptions().PointerAuth.SwiftClassMethods) {
304+
if (auto &schema =
305+
func->hasAsync() ? IGM.getOptions().PointerAuth.AsyncSwiftClassMethods
306+
: accessor &&
307+
requiresFeatureCoroutineAccessors(accessor->getAccessorKind())
308+
? IGM.getOptions().PointerAuth.CoroSwiftClassMethods
309+
: IGM.getOptions().PointerAuth.SwiftClassMethods) {
305310
auto discriminator =
306311
PointerAuthInfo::getOtherDiscriminator(IGM, schema, fn);
307312
flags = flags.withExtraDiscriminator(discriminator->getZExtValue());
@@ -4530,9 +4535,13 @@ namespace {
45304535
VTableEntriesForVFE.push_back(std::pair<Size, SILDeclRef>(offset, fn));
45314536
}
45324537

4538+
auto *accessor = dyn_cast<AccessorDecl>(afd);
45334539
PointerAuthSchema schema =
45344540
afd->hasAsync() ? IGM.getOptions().PointerAuth.AsyncSwiftClassMethods
4535-
: IGM.getOptions().PointerAuth.SwiftClassMethods;
4541+
: accessor &&
4542+
requiresFeatureCoroutineAccessors(accessor->getAccessorKind())
4543+
? IGM.getOptions().PointerAuth.CoroSwiftClassMethods
4544+
: IGM.getOptions().PointerAuth.SwiftClassMethods;
45364545
B.addSignedPointer(ptr, schema, fn);
45374546
}
45384547

lib/IRGen/GenPointerAuth.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ static const PointerAuthSchema &getFunctionPointerSchema(IRGenModule &IGM,
193193
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
194194
if (fnType->isAsync()) {
195195
return options.AsyncSwiftFunctionPointers;
196+
} else if (fnType->isCalleeAllocatedCoroutine()) {
197+
return options.CoroSwiftFunctionPointers;
196198
}
197199

198200
return options.SwiftFunctionPointers;

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,8 @@ class AccessorConformanceInfo : public ConformanceInfo {
16821682
PointerAuthSchema schema =
16831683
isAsyncRequirement
16841684
? IGM.getOptions().PointerAuth.AsyncProtocolWitnesses
1685+
: isCalleeAllocatedCoroutineRequirement
1686+
? IGM.getOptions().PointerAuth.CoroProtocolWitnesses
16851687
: IGM.getOptions().PointerAuth.ProtocolWitnesses;
16861688
Table.addSignedPointer(witness, schema, requirement);
16871689

@@ -4387,6 +4389,8 @@ FunctionPointer irgen::emitWitnessMethodValue(IRGenFunction &IGF,
43874389

43884390
auto &schema = fnType->isAsync()
43894391
? IGF.getOptions().PointerAuth.AsyncProtocolWitnesses
4392+
: fnType->isCalleeAllocatedCoroutine()
4393+
? IGF.getOptions().PointerAuth.CoroProtocolWitnesses
43904394
: IGF.getOptions().PointerAuth.ProtocolWitnesses;
43914395
auto authInfo = PointerAuthInfo::emit(IGF, schema, slot.getAddress(), member);
43924396

lib/IRGen/GenThunk.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,10 @@ void IRGenModule::emitMethodLookupFunction(ClassDecl *classDecl) {
805805
if (auto &schema =
806806
entry->getImplementation()->getLoweredFunctionType()->isAsync()
807807
? IGM.getOptions().PointerAuth.AsyncSwiftClassMethods
808+
: entry->getImplementation()
809+
->getLoweredFunctionType()
810+
->isCalleeAllocatedCoroutine()
811+
? IGM.getOptions().PointerAuth.CoroSwiftClassMethods
808812
: IGM.getOptions().PointerAuth.SwiftClassMethods) {
809813
auto discriminator =
810814
PointerAuthInfo::getOtherDiscriminator(IGM, schema, method);

lib/IRGen/IRGen.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,24 @@ static void setPointerAuthOptions(PointerAuthOptions &opts,
923923
opts.RelativeProtocolWitnessTable = PointerAuthSchema(
924924
dataKey, /*address*/ false, Discrimination::Constant,
925925
SpecialPointerAuthDiscriminators::RelativeProtocolWitnessTable);
926+
927+
opts.CoroSwiftFunctionPointers =
928+
PointerAuthSchema(dataKey, /*address*/ false, Discrimination::Type);
929+
930+
opts.CoroSwiftClassMethods =
931+
PointerAuthSchema(dataKey, /*address*/ true, Discrimination::Decl);
932+
933+
opts.CoroProtocolWitnesses =
934+
PointerAuthSchema(dataKey, /*address*/ true, Discrimination::Decl);
935+
936+
opts.CoroSwiftClassMethodPointers =
937+
PointerAuthSchema(dataKey, /*address*/ false, Discrimination::Decl);
938+
939+
opts.CoroSwiftDynamicReplacements =
940+
PointerAuthSchema(dataKey, /*address*/ true, Discrimination::Decl);
941+
942+
opts.CoroPartialApplyCapture =
943+
PointerAuthSchema(nonABIDataKey, /*address*/ true, Discrimination::Decl);
926944
}
927945

928946
std::unique_ptr<llvm::TargetMachine>

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8369,6 +8369,8 @@ void IRGenSILFunction::visitSuperMethodInst(swift::SuperMethodInst *i) {
83698369

83708370
auto &schema = methodType->isAsync()
83718371
? getOptions().PointerAuth.AsyncSwiftClassMethodPointers
8372+
: methodType->isCalleeAllocatedCoroutine()
8373+
? getOptions().PointerAuth.CoroSwiftClassMethodPointers
83728374
: getOptions().PointerAuth.SwiftClassMethodPointers;
83738375
auto authInfo =
83748376
PointerAuthInfo::emit(*this, schema, /*storageAddress=*/nullptr, method);

stdlib/public/runtime/Metadata.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ static void swift_objc_classCopyFixupHandler(Class oldClass, Class newClass) {
410410
reinterpret_cast<void **>(&dest[i]),
411411
reinterpret_cast<void *const *>(&src[i]),
412412
descriptors[i].Flags.getExtraDiscriminator(),
413-
!descriptors[i].Flags.isAsync(),
413+
!descriptors[i].Flags.isData(),
414414
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable
415415
// might be proven unused and null'ed)
416416
}
@@ -3609,7 +3609,7 @@ static void copySuperclassMetadataToSubclass(ClassMetadata *theClass,
36093609
reinterpret_cast<void **>(&dest[i]),
36103610
reinterpret_cast<void *const *>(&src[i]),
36113611
descriptors[i].Flags.getExtraDiscriminator(),
3612-
!descriptors[i].Flags.isAsync(),
3612+
!descriptors[i].Flags.isData(),
36133613
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable
36143614
// might be proven unused and null'ed)
36153615
}
@@ -3659,7 +3659,7 @@ static void initClassVTable(ClassMetadata *self) {
36593659
swift_ptrauth_init_code_or_data(
36603660
&classWords[vtableOffset + i], methodDescription.getImpl(),
36613661
methodDescription.Flags.getExtraDiscriminator(),
3662-
!methodDescription.Flags.isAsync());
3662+
!methodDescription.Flags.isData());
36633663
}
36643664
}
36653665

@@ -3697,10 +3697,9 @@ static void initClassVTable(ClassMetadata *self) {
36973697
auto baseVTable = baseClass->getVTableDescriptor();
36983698
auto offset = (baseVTable->getVTableOffset(baseClass) +
36993699
(baseMethod - baseClassMethods.data()));
3700-
swift_ptrauth_init_code_or_data(&classWords[offset],
3701-
descriptor.getImpl(),
3700+
swift_ptrauth_init_code_or_data(&classWords[offset], descriptor.getImpl(),
37023701
baseMethod->Flags.getExtraDiscriminator(),
3703-
!baseMethod->Flags.isAsync());
3702+
!baseMethod->Flags.isData());
37043703
}
37053704
}
37063705
}
@@ -4352,7 +4351,7 @@ swift::swift_lookUpClassMethod(const ClassMetadata *metadata,
43524351
#if SWIFT_PTRAUTH
43534352
// Re-sign the return value without the address.
43544353
unsigned extra = method->Flags.getExtraDiscriminator();
4355-
if (method->Flags.isAsync()) {
4354+
if (method->Flags.isData()) {
43564355
return ptrauth_auth_and_resign(
43574356
*methodPtr, ptrauth_key_process_independent_data,
43584357
ptrauth_blend_discriminator(methodPtr, extra),
@@ -6097,7 +6096,7 @@ static void initProtocolWitness(void **slot, void *witness,
60976096
case ProtocolRequirementFlags::Kind::Modify2Coroutine:
60986097
swift_ptrauth_init_code_or_data(slot, witness,
60996098
reqt.Flags.getExtraDiscriminator(),
6100-
!reqt.Flags.isAsync());
6099+
!reqt.Flags.isData());
61016100
return;
61026101

61036102
case ProtocolRequirementFlags::Kind::AssociatedConformanceAccessFunction:
@@ -6139,7 +6138,7 @@ static void copyProtocolWitness(void **dest, void * const *src,
61396138
case ProtocolRequirementFlags::Kind::ModifyCoroutine:
61406139
case ProtocolRequirementFlags::Kind::Modify2Coroutine:
61416140
swift_ptrauth_copy_code_or_data(
6142-
dest, src, reqt.Flags.getExtraDiscriminator(), !reqt.Flags.isAsync(),
6141+
dest, src, reqt.Flags.getExtraDiscriminator(), !reqt.Flags.isData(),
61436142
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable
61446143
// might be proven unused and null'ed)
61456144
return;

0 commit comments

Comments
 (0)