@@ -824,7 +824,17 @@ void IRGenerator::emitGlobalTopLevel() {
824
824
// Emit witness tables.
825
825
for (SILWitnessTable &wt : PrimaryIGM->getSILModule ().getWitnessTableList ()) {
826
826
CurrentIGMPtr IGM = getGenModule (wt.getConformance ()->getDeclContext ());
827
+ #ifndef NDEBUG
828
+ IGM->EligibleConfs .collect (&wt);
829
+ IGM->CurrentWitnessTable = &wt;
830
+ #endif
831
+
827
832
IGM->emitSILWitnessTable (&wt);
833
+
834
+ #ifndef NDEBUG
835
+ IGM->EligibleConfs .clear ();
836
+ IGM->CurrentWitnessTable = nullptr ;
837
+ #endif
828
838
}
829
839
830
840
for (auto Iter : *this ) {
@@ -1049,7 +1059,8 @@ static SILLinkage getNonUniqueSILLinkage(FormalLinkage linkage,
1049
1059
1050
1060
static SILLinkage getConformanceLinkage (IRGenModule &IGM,
1051
1061
const ProtocolConformance *conf) {
1052
- if (auto wt = IGM.getSILModule ().lookUpWitnessTable (conf)) {
1062
+ if (auto wt = IGM.getSILModule ().lookUpWitnessTable (conf,
1063
+ /* deserializeLazily*/ false )) {
1053
1064
return wt->getLinkage ();
1054
1065
} else {
1055
1066
return SILLinkage::PublicExternal;
@@ -1232,18 +1243,25 @@ bool LinkEntity::isFragile(IRGenModule &IGM) const {
1232
1243
case Kind::SILGlobalVariable:
1233
1244
return getSILGlobalVariable ()->isFragile ();
1234
1245
1235
- case Kind::DirectProtocolWitnessTable: {
1236
- if (auto wt = IGM.getSILModule ().lookUpWitnessTable (
1237
- getProtocolConformance ())) {
1238
- return wt->isFragile ();
1239
- } else {
1240
- return false ;
1241
- }
1242
- }
1243
-
1246
+ case Kind::ReflectionAssociatedTypeDescriptor:
1247
+ case Kind::ReflectionSuperclassDescriptor:
1248
+ return false ;
1249
+
1244
1250
default :
1245
1251
break ;
1246
1252
}
1253
+ if (isProtocolConformanceKind (getKind ())) {
1254
+ if (SILWitnessTable *wt = IGM.getSILModule ().lookUpWitnessTable (
1255
+ getProtocolConformance (), false )) {
1256
+ SILLinkage L = wt->getLinkage ();
1257
+ // We don't deserialize the fragile attribute correctly. But we know that
1258
+ // if the witness table was deserialized (= available externally) and it's
1259
+ // not public, it must be fragile.
1260
+ if (swift::isAvailableExternally (L) && !hasPublicVisibility (L))
1261
+ return true ;
1262
+ return wt->isFragile ();
1263
+ }
1264
+ }
1247
1265
return false ;
1248
1266
}
1249
1267
@@ -1835,6 +1853,75 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, Alignment alignment,
1835
1853
llvm_unreachable (" bad reference kind" );
1836
1854
}
1837
1855
1856
+ void IRGenModule::checkEligibleConf (const ProtocolConformance *Conf) {
1857
+ #ifndef NDEBUG
1858
+ if (EligibleConfs.isUsed (Conf))
1859
+ return ;
1860
+
1861
+ if (CurrentInst) {
1862
+ llvm::errs () << " ## Conformance: " ;
1863
+ Conf->dump ();
1864
+ llvm::errs () << " ## Inst: " ;
1865
+ CurrentInst->dump ();
1866
+ llvm_unreachable (
1867
+ " ConformanceCollector is missing a conformance in instruction" );
1868
+ }
1869
+ if (CurrentWitnessTable) {
1870
+ llvm_unreachable (
1871
+ " ConformanceCollector is missing a conformance in witness table" );
1872
+ }
1873
+ #endif
1874
+ }
1875
+
1876
+ void IRGenModule::checkEligibleMetaType (NominalTypeDecl *NT) {
1877
+ #ifndef NDEBUG
1878
+ if (!NT || EligibleConfs.isMetaTypeEscaping (NT))
1879
+ return ;
1880
+
1881
+ if (CurrentInst) {
1882
+ // Ignore instructions which may use a metatype but do not let escape it.
1883
+ switch (CurrentInst->getKind ()) {
1884
+ case ValueKind::DestroyAddrInst:
1885
+ case ValueKind::StructElementAddrInst:
1886
+ case ValueKind::TupleElementAddrInst:
1887
+ case ValueKind::InjectEnumAddrInst:
1888
+ case ValueKind::SwitchEnumAddrInst:
1889
+ case ValueKind::SelectEnumAddrInst:
1890
+ case ValueKind::IndexAddrInst:
1891
+ case ValueKind::RefElementAddrInst:
1892
+ case ValueKind::AllocValueBufferInst:
1893
+ case ValueKind::ProjectValueBufferInst:
1894
+ case ValueKind::ProjectBoxInst:
1895
+ case ValueKind::CopyAddrInst:
1896
+ case ValueKind::UncheckedRefCastAddrInst:
1897
+ case ValueKind::AllocStackInst:
1898
+ case ValueKind::SuperMethodInst:
1899
+ case ValueKind::WitnessMethodInst:
1900
+ case ValueKind::DeallocRefInst:
1901
+ case ValueKind::AllocGlobalInst:
1902
+ return ;
1903
+ case ValueKind::ApplyInst:
1904
+ case ValueKind::TryApplyInst:
1905
+ case ValueKind::PartialApplyInst:
1906
+ // It's not trivial to find the non-escaping vs. escaping meta-
1907
+ // types of an apply. Therefore we just trust the ConformanceCollector
1908
+ // that it does the right job.
1909
+ return ;
1910
+ default :
1911
+ break ;
1912
+ }
1913
+ llvm::errs () << " ## NominalType: " << NT->getName () << " \n ## Inst: " ;
1914
+ CurrentInst->dump ();
1915
+ llvm_unreachable (
1916
+ " ConformanceCollector is missing a metatype in instruction" );
1917
+ }
1918
+ if (CurrentWitnessTable) {
1919
+ llvm_unreachable (
1920
+ " ConformanceCollector is missing a metatype in witness table" );
1921
+ }
1922
+ #endif
1923
+ }
1924
+
1838
1925
// / A convenient wrapper around getAddrOfLLVMVariable which uses the
1839
1926
// / default type as the definition type.
1840
1927
llvm::Constant *
@@ -2368,6 +2455,7 @@ llvm::Function *
2368
2455
IRGenModule::getAddrOfTypeMetadataAccessFunction (CanType type,
2369
2456
ForDefinition_t forDefinition) {
2370
2457
assert (!type->hasArchetype () && !type->hasTypeParameter ());
2458
+ checkEligibleMetaType (type->getNominalOrBoundGenericNominal ());
2371
2459
LinkEntity entity = LinkEntity::forTypeMetadataAccessFunction (type);
2372
2460
llvm::Function *&entry = GlobalFuncs[entity];
2373
2461
if (entry) {
@@ -2389,6 +2477,7 @@ IRGenModule::getAddrOfGenericTypeMetadataAccessFunction(
2389
2477
ForDefinition_t forDefinition) {
2390
2478
assert (!genericArgs.empty ());
2391
2479
assert (nominal->isGenericContext ());
2480
+ checkEligibleMetaType (nominal);
2392
2481
2393
2482
auto type = nominal->getDeclaredType ()->getCanonicalType ();
2394
2483
assert (type->hasUnboundGenericType ());
@@ -2411,6 +2500,7 @@ llvm::Constant *
2411
2500
IRGenModule::getAddrOfTypeMetadataLazyCacheVariable (CanType type,
2412
2501
ForDefinition_t forDefinition) {
2413
2502
assert (!type->hasArchetype () && !type->hasTypeParameter ());
2503
+ checkEligibleMetaType (type->getNominalOrBoundGenericNominal ());
2414
2504
LinkEntity entity = LinkEntity::forTypeMetadataLazyCacheVariable (type);
2415
2505
return getAddrOfLLVMVariable (entity, getPointerAlignment (), forDefinition,
2416
2506
TypeMetadataPtrTy, DebugTypeInfo ());
@@ -2570,6 +2660,7 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
2570
2660
SymbolReferenceKind refKind) {
2571
2661
assert (isPattern || !isa<UnboundGenericType>(concreteType));
2572
2662
2663
+ checkEligibleMetaType (concreteType->getNominalOrBoundGenericNominal ());
2573
2664
llvm::Type *defaultVarTy;
2574
2665
unsigned adjustmentIndex;
2575
2666
Alignment alignment = getPointerAlignment ();
@@ -2664,6 +2755,7 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
2664
2755
llvm::Constant *IRGenModule::getAddrOfNominalTypeDescriptor (NominalTypeDecl *D,
2665
2756
llvm::Type *definitionType) {
2666
2757
assert (definitionType && " not defining nominal type descriptor?" );
2758
+ checkEligibleMetaType (D);
2667
2759
auto entity = LinkEntity::forNominalTypeDescriptor (D);
2668
2760
return getAddrOfLLVMVariable (entity, getPointerAlignment (),
2669
2761
definitionType, definitionType,
@@ -3040,6 +3132,7 @@ IRGenModule::getResilienceExpansionForLayout(SILGlobalVariable *global) {
3040
3132
llvm::Constant *IRGenModule::
3041
3133
getAddrOfGenericWitnessTableCache (const NormalProtocolConformance *conf,
3042
3134
ForDefinition_t forDefinition) {
3135
+ checkEligibleConf (conf);
3043
3136
auto entity = LinkEntity::forGenericProtocolWitnessTableCache (conf);
3044
3137
auto expectedTy = getGenericWitnessTableCacheTy ();
3045
3138
auto storageTy = (forDefinition ? expectedTy : nullptr );
@@ -3050,6 +3143,7 @@ getAddrOfGenericWitnessTableCache(const NormalProtocolConformance *conf,
3050
3143
llvm::Function *
3051
3144
IRGenModule::getAddrOfGenericWitnessTableInstantiationFunction (
3052
3145
const NormalProtocolConformance *conf) {
3146
+ checkEligibleConf (conf);
3053
3147
auto forDefinition = ForDefinition;
3054
3148
3055
3149
LinkEntity entity =
@@ -3096,6 +3190,7 @@ llvm::Function *
3096
3190
IRGenModule::getAddrOfWitnessTableAccessFunction (
3097
3191
const NormalProtocolConformance *conf,
3098
3192
ForDefinition_t forDefinition) {
3193
+ checkEligibleConf (conf);
3099
3194
LinkEntity entity = LinkEntity::forProtocolWitnessTableAccessFunction (conf);
3100
3195
llvm::Function *&entry = GlobalFuncs[entity];
3101
3196
if (entry) {
@@ -3122,6 +3217,7 @@ IRGenModule::getAddrOfWitnessTableLazyAccessFunction(
3122
3217
const NormalProtocolConformance *conf,
3123
3218
CanType conformingType,
3124
3219
ForDefinition_t forDefinition) {
3220
+ checkEligibleConf (conf);
3125
3221
LinkEntity entity =
3126
3222
LinkEntity::forProtocolWitnessTableLazyAccessFunction (conf, conformingType);
3127
3223
llvm::Function *&entry = GlobalFuncs[entity];
@@ -3146,6 +3242,7 @@ IRGenModule::getAddrOfWitnessTableLazyCacheVariable(
3146
3242
CanType conformingType,
3147
3243
ForDefinition_t forDefinition) {
3148
3244
assert (!conformingType->hasArchetype ());
3245
+ checkEligibleConf (conf);
3149
3246
LinkEntity entity =
3150
3247
LinkEntity::forProtocolWitnessTableLazyCacheVariable (conf, conformingType);
3151
3248
return getAddrOfLLVMVariable (entity, getPointerAlignment (),
@@ -3162,6 +3259,7 @@ IRGenModule::getAddrOfWitnessTableLazyCacheVariable(
3162
3259
llvm::Constant*
3163
3260
IRGenModule::getAddrOfWitnessTable (const NormalProtocolConformance *conf,
3164
3261
llvm::Type *storageTy) {
3262
+ checkEligibleConf (conf);
3165
3263
auto entity = LinkEntity::forDirectProtocolWitnessTable (conf);
3166
3264
return getAddrOfLLVMVariable (entity, getPointerAlignment (), storageTy,
3167
3265
WitnessTableTy, DebugTypeInfo ());
@@ -3171,6 +3269,7 @@ llvm::Function *
3171
3269
IRGenModule::getAddrOfAssociatedTypeMetadataAccessFunction (
3172
3270
const NormalProtocolConformance *conformance,
3173
3271
AssociatedTypeDecl *associate) {
3272
+ checkEligibleConf (conformance);
3174
3273
auto forDefinition = ForDefinition;
3175
3274
3176
3275
LinkEntity entity =
@@ -3192,6 +3291,7 @@ IRGenModule::getAddrOfAssociatedTypeWitnessTableAccessFunction(
3192
3291
const NormalProtocolConformance *conformance,
3193
3292
AssociatedTypeDecl *associate,
3194
3293
ProtocolDecl *associateProtocol) {
3294
+ checkEligibleConf (conformance);
3195
3295
auto forDefinition = ForDefinition;
3196
3296
3197
3297
assert (conformance->getProtocol () == associate->getProtocol ());
0 commit comments