@@ -1423,6 +1423,7 @@ void IRGenerator::emitLazyDefinitions() {
14231423 assert (LazySpecializedTypeMetadataRecords.empty ());
14241424 assert (LazyTypeContextDescriptors.empty ());
14251425 assert (LazyOpaqueTypeDescriptors.empty ());
1426+ assert (LazyExtensionDescriptors.empty ());
14261427 assert (LazyFieldDescriptors.empty ());
14271428 // LazyFunctionDefinitions are allowed, but they must not be generic
14281429 for (SILFunction *f : LazyFunctionDefinitions) {
@@ -1438,7 +1439,9 @@ void IRGenerator::emitLazyDefinitions() {
14381439 while (!LazyTypeMetadata.empty () ||
14391440 !LazySpecializedTypeMetadataRecords.empty () ||
14401441 !LazyTypeContextDescriptors.empty () ||
1441- !LazyOpaqueTypeDescriptors.empty () || !LazyFieldDescriptors.empty () ||
1442+ !LazyOpaqueTypeDescriptors.empty () ||
1443+ !LazyExtensionDescriptors.empty () ||
1444+ !LazyFieldDescriptors.empty () ||
14421445 !LazyFunctionDefinitions.empty () || !LazyWitnessTables.empty () ||
14431446 !LazyCanonicalSpecializedMetadataAccessors.empty () ||
14441447 !LazyMetadataAccessors.empty () ||
@@ -1494,6 +1497,15 @@ void IRGenerator::emitLazyDefinitions() {
14941497 CurrentIGMPtr IGM = getGenModule (type->getDeclContext ());
14951498 IGM->emitOpaqueTypeDecl (type);
14961499 }
1500+ while (!LazyExtensionDescriptors.empty ()) {
1501+ ExtensionDecl *ext = LazyExtensionDescriptors.back ();
1502+ LazyExtensionDescriptors.pop_back ();
1503+ auto &entry = LazyExtensions.find (ext)->second ;
1504+ assert (entry.IsDescriptorUsed && !entry.IsDescriptorEmitted );
1505+ entry.IsDescriptorEmitted = true ;
1506+ CurrentIGMPtr IGM = getGenModule (ext->getDeclContext ());
1507+ IGM->getAddrOfExtensionContextDescriptor (ext);
1508+ }
14971509 while (!LazyFieldDescriptors.empty ()) {
14981510 NominalTypeDecl *type = LazyFieldDescriptors.pop_back_val ();
14991511 CurrentIGMPtr IGM = getGenModule (type->getDeclContext ());
@@ -1804,6 +1816,18 @@ void IRGenerator::noteUseOfOpaqueTypeDescriptor(OpaqueTypeDecl *opaque) {
18041816 }
18051817}
18061818
1819+ void IRGenerator::noteUseOfExtensionDescriptor (ExtensionDecl *ext) {
1820+ auto insertResult = LazyExtensions.try_emplace (ext);
1821+ auto &entry = insertResult.first ->second ;
1822+
1823+ bool isNovelUseOfDescriptor = !entry.IsDescriptorUsed ;
1824+ entry.IsDescriptorUsed = true ;
1825+
1826+ if (isNovelUseOfDescriptor) {
1827+ LazyExtensionDescriptors.push_back (ext);
1828+ }
1829+ }
1830+
18071831static std::string getDynamicReplacementSection (IRGenModule &IGM) {
18081832 std::string sectionName;
18091833 switch (IGM.TargetInfo .OutputObjectFormat ) {
@@ -4065,11 +4089,11 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity) {
40654089 return indirect ();
40664090}
40674091
4068- static TypeEntityReference
4069- getContextDescriptorEntityReference (IRGenModule &IGM, const LinkEntity &entity){
4092+ TypeEntityReference
4093+ IRGenModule:: getContextDescriptorEntityReference (const LinkEntity &entity) {
40704094 // TODO: consider using a symbolic reference (i.e. a symbol string
40714095 // to be looked up dynamically) for types defined outside the module.
4072- auto ref = IGM. getAddrOfLLVMVariableOrGOTEquivalent (entity);
4096+ auto ref = getAddrOfLLVMVariableOrGOTEquivalent (entity);
40734097 auto kind = ref.isIndirect ()
40744098 ? TypeReferenceKind::IndirectTypeDescriptor
40754099 : TypeReferenceKind::DirectTypeDescriptor;
@@ -4081,15 +4105,15 @@ getTypeContextDescriptorEntityReference(IRGenModule &IGM,
40814105 NominalTypeDecl *decl) {
40824106 auto entity = LinkEntity::forNominalTypeDescriptor (decl);
40834107 IGM.IRGen .noteUseOfTypeContextDescriptor (decl, DontRequireMetadata);
4084- return getContextDescriptorEntityReference (IGM, entity);
4108+ return IGM. getContextDescriptorEntityReference (entity);
40854109}
40864110
40874111static TypeEntityReference
40884112getProtocolDescriptorEntityReference (IRGenModule &IGM, ProtocolDecl *protocol) {
40894113 assert (!protocol->hasClangNode () &&
40904114 " objc protocols don't have swift protocol descriptors" );
40914115 auto entity = LinkEntity::forProtocolDescriptor (protocol);
4092- return getContextDescriptorEntityReference (IGM, entity);
4116+ return IGM. getContextDescriptorEntityReference (entity);
40934117}
40944118
40954119static TypeEntityReference
@@ -4113,7 +4137,7 @@ IRGenModule::getTypeEntityReference(GenericTypeDecl *decl) {
41134137 if (auto opaque = dyn_cast<OpaqueTypeDecl>(decl)) {
41144138 auto entity = LinkEntity::forOpaqueTypeDescriptor (opaque);
41154139 IRGen.noteUseOfOpaqueTypeDescriptor (opaque);
4116- return getContextDescriptorEntityReference (* this , entity);
4140+ return getContextDescriptorEntityReference (entity);
41174141 }
41184142
41194143 if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
@@ -4360,12 +4384,28 @@ llvm::Constant *IRGenModule::emitSwiftProtocols(bool asContiguousArray) {
43604384 return nullptr ;
43614385}
43624386
4387+ // / Determine whether the given protocol conformance can be found via
4388+ // / metadata for dynamic lookup.
4389+ static bool conformanceIsVisibleViaMetadata (
4390+ RootProtocolConformance *conformance) {
4391+ auto normal = dyn_cast<NormalProtocolConformance>(conformance);
4392+ if (!normal)
4393+ return true ;
4394+
4395+ // Conformances of a protocol to another protocol cannot be looked up
4396+ // dynamically.
4397+ return !normal->isConformanceOfProtocol ();
4398+ }
4399+
4400+
43634401void IRGenModule::addProtocolConformance (ConformanceDescription &&record) {
43644402
43654403 emitProtocolConformance (record);
43664404
4367- // Add this conformance to the conformance list.
4368- ProtocolConformances.push_back (std::move (record));
4405+ if (conformanceIsVisibleViaMetadata (record.conformance )) {
4406+ // Add this conformance to the conformance list.
4407+ ProtocolConformances.push_back (std::move (record));
4408+ }
43694409}
43704410
43714411void IRGenModule::addAccessibleFunction (SILFunction *func) {
0 commit comments