Skip to content

Commit abbc633

Browse files
committed
IRGen: support associated-type and associated-conformance witness table entries
Associated-type entries are simply skipped. Associated-conformance entries point to the specialized conformance witness tables.
1 parent 792dee2 commit abbc633

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
120120

121121
/// Swift protocol witness table associated conformance witness table
122122
/// access functions.
123+
/// In Embedded Swift used for associated conformance witness table
124+
/// pointers.
123125
PointerAuthSchema ProtocolAssociatedTypeWitnessTableAccessFunctions;
124126

125127
/// Swift class v-table functions.

lib/IRGen/GenProto.cpp

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,9 @@ namespace {
946946
}
947947

948948
void addAssociatedType(AssociatedType requirement) {
949+
// In Embedded Swift witness tables don't have associated-types entries.
950+
if (requirement.getAssociation()->getASTContext().LangOpts.hasFeature(Feature::Embedded))
951+
return;
949952
Entries.push_back(WitnessTableEntry::forAssociatedType(requirement));
950953
}
951954

@@ -1671,6 +1674,10 @@ class AccessorConformanceInfo : public ConformanceInfo {
16711674
auto &entry = SILEntries.front();
16721675
SILEntries = SILEntries.slice(1);
16731676

1677+
// In Embedded Swift witness tables don't have associated-types entries.
1678+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded))
1679+
return;
1680+
16741681
#ifndef NDEBUG
16751682
assert(entry.getKind() == SILWitnessTable::AssociatedType
16761683
&& "sil witness table does not match protocol");
@@ -1735,6 +1742,16 @@ class AccessorConformanceInfo : public ConformanceInfo {
17351742
"offset doesn't match ProtocolInfo layout");
17361743
#endif
17371744

1745+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
1746+
// In Embedded Swift associated-conformance entries simply point to the witness table
1747+
// of the associated conformance.
1748+
llvm::Constant *witnessEntry = IGM.getAddrOfWitnessTable(associatedConformance.getConcrete());
1749+
auto &schema = IGM.getOptions().PointerAuth
1750+
.ProtocolAssociatedTypeWitnessTableAccessFunctions;
1751+
Table.addSignedPointer(witnessEntry, schema, requirement);
1752+
return;
1753+
}
1754+
17381755
llvm::Constant *witnessEntry =
17391756
getAssociatedConformanceWitness(requirement, associate,
17401757
associatedConformance);
@@ -2670,11 +2687,11 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
26702687
// Produce the initializer value.
26712688
auto initializer = wtableContents.finishAndCreateFuture();
26722689

2690+
auto *normalConf = dyn_cast<NormalProtocolConformance>(conf);
26732691
global = cast<llvm::GlobalVariable>(
26742692
(isDependent && conf->getDeclContext()->isGenericContext() &&
2675-
!useRelativeProtocolWitnessTable)
2676-
? getAddrOfWitnessTablePattern(cast<NormalProtocolConformance>(conf),
2677-
initializer)
2693+
!useRelativeProtocolWitnessTable && normalConf)
2694+
? getAddrOfWitnessTablePattern(normalConf, initializer)
26782695
: getAddrOfWitnessTable(conf, initializer));
26792696
// Eelative protocol witness tables are always constant. They don't cache
26802697
// results in the table.
@@ -3321,6 +3338,18 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF,
33213338

33223339
if (!source) return MetadataResponse();
33233340

3341+
AssociatedConformance associatedConformanceRef(sourceProtocol,
3342+
association,
3343+
associatedRequirement);
3344+
3345+
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
3346+
// In Embedded Swift associated-conformance entries simply point to the witness table
3347+
// of the associated conformance.
3348+
llvm::Value *sourceWTable = source.getMetadata();
3349+
llvm::Value *associatedWTable = emitAssociatedConformanceValue(IGF, sourceWTable, associatedConformanceRef);
3350+
return MetadataResponse::forComplete(associatedWTable);
3351+
}
3352+
33243353
auto *sourceMetadata =
33253354
IGF.emitAbstractTypeMetadataRef(sourceType);
33263355

@@ -3394,10 +3423,7 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF,
33943423

33953424
auto sourceWTable = source.getMetadata();
33963425

3397-
AssociatedConformance associatedConformanceRef(sourceProtocol,
3398-
association,
3399-
associatedRequirement);
3400-
auto associatedWTable =
3426+
auto associatedWTable =
34013427
emitAssociatedTypeWitnessTableRef(IGF, sourceMetadata, sourceWTable,
34023428
associatedConformanceRef,
34033429
associatedMetadata);
@@ -4329,6 +4355,29 @@ FunctionPointer irgen::emitWitnessMethodValue(IRGenFunction &IGF,
43294355
signature);
43304356
}
43314357

4358+
llvm::Value *irgen::emitAssociatedConformanceValue(IRGenFunction &IGF,
4359+
llvm::Value *wtable,
4360+
const AssociatedConformance &conf) {
4361+
auto proto = conf.getSourceProtocol();
4362+
assert(!IGF.IGM.isResilient(proto, ResilienceExpansion::Maximal));
4363+
4364+
// Find the witness we're interested in.
4365+
auto &fnProtoInfo = IGF.IGM.getProtocolInfo(proto, ProtocolInfoKind::Full);
4366+
auto index = fnProtoInfo.getAssociatedConformanceIndex(conf);
4367+
assert(!IGF.IGM.IRGen.Opts.UseRelativeProtocolWitnessTables);
4368+
4369+
wtable = IGF.optionallyLoadFromConditionalProtocolWitnessTable(wtable);
4370+
auto slot =
4371+
slotForLoadOfOpaqueWitness(IGF, wtable, index.forProtocolWitnessTable(),
4372+
false/*isRelativeTable*/);
4373+
llvm::Value *confPointer = IGF.emitInvariantLoad(slot);
4374+
if (auto &schema = IGF.getOptions().PointerAuth.ProtocolAssociatedTypeWitnessTableAccessFunctions) {
4375+
auto authInfo = PointerAuthInfo::emit(IGF, schema, slot.getAddress(), conf);
4376+
confPointer = emitPointerAuthAuth(IGF, confPointer, authInfo);
4377+
}
4378+
return confPointer;
4379+
}
4380+
43324381
FunctionPointer irgen::emitWitnessMethodValue(
43334382
IRGenFunction &IGF, CanType baseTy, llvm::Value **baseMetadataCache,
43344383
SILDeclRef member, ProtocolConformanceRef conformance) {

lib/IRGen/GenProto.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ namespace irgen {
7373
SILDeclRef member,
7474
ProtocolConformanceRef conformance);
7575

76+
llvm::Value *emitAssociatedConformanceValue(IRGenFunction &IGF,
77+
llvm::Value *wtable,
78+
const AssociatedConformance &conf);
79+
7680
/// Compute the index into a witness table for a resilient protocol given
7781
/// a reference to a descriptor of one of the requirements in that witness
7882
/// table.

0 commit comments

Comments
 (0)