@@ -1164,18 +1164,42 @@ void IRGenerator::emitTypeMetadataRecords() {
1164
1164
}
1165
1165
}
1166
1166
1167
+ void IRGenerator::
1168
+ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords (
1169
+ IRGenModule &IGM, CanType typeWithCanonicalMetadataPrespecialization,
1170
+ NominalTypeDecl &decl) {
1171
+ // The accessor depends on canonical metadata records because they are
1172
+ // returned from the function when the arguments match.
1173
+ //
1174
+ // TODO: Once work of looking through canonical prespecialized metadata has
1175
+ // been moved into getGenericMetadata, this reemission will no longer
1176
+ // be necessary.
1177
+ auto *accessor = IGM.getAddrOfTypeMetadataAccessFunction (
1178
+ decl.getDeclaredType ()->getCanonicalType (), NotForDefinition);
1179
+ accessor->deleteBody ();
1180
+ IGM.IRGen .noteUseOfMetadataAccessor (&decl);
1181
+
1182
+ // The type context descriptor depends on canonical metadata records because
1183
+ // pointers to them are attached as trailing objects to it.
1184
+ //
1185
+ // Don't call
1186
+ //
1187
+ // noteUseOfTypeContextDescriptor
1188
+ //
1189
+ // here because we don't want to reemit metadata.
1190
+ emitLazyTypeContextDescriptor (IGM, &decl, RequireMetadata);
1191
+ }
1192
+
1167
1193
// / Emit any lazy definitions (of globals or functions or whatever
1168
1194
// / else) that we require.
1169
1195
void IRGenerator::emitLazyDefinitions () {
1170
1196
while (!LazyTypeMetadata.empty () ||
1171
1197
!LazySpecializedTypeMetadataRecords.empty () ||
1172
1198
!LazyTypeContextDescriptors.empty () ||
1173
- !LazyOpaqueTypeDescriptors.empty () ||
1174
- !LazyFieldDescriptors.empty () ||
1175
- !LazyFunctionDefinitions.empty () ||
1176
- !LazyWitnessTables.empty () ||
1177
- !LazyCanonicalSpecializedMetadataAccessors.empty ()) {
1178
-
1199
+ !LazyOpaqueTypeDescriptors.empty () || !LazyFieldDescriptors.empty () ||
1200
+ !LazyFunctionDefinitions.empty () || !LazyWitnessTables.empty () ||
1201
+ !LazyCanonicalSpecializedMetadataAccessors.empty () ||
1202
+ !LazyMetadataAccessors.empty ()) {
1179
1203
// Emit any lazy type metadata we require.
1180
1204
while (!LazyTypeMetadata.empty ()) {
1181
1205
NominalTypeDecl *type = LazyTypeMetadata.pop_back_val ();
@@ -1187,10 +1211,23 @@ void IRGenerator::emitLazyDefinitions() {
1187
1211
emitLazyTypeMetadata (*IGM.get (), type);
1188
1212
}
1189
1213
while (!LazySpecializedTypeMetadataRecords.empty ()) {
1190
- CanType type = LazySpecializedTypeMetadataRecords.pop_back_val ();
1191
- auto *nominal = type->getNominalOrBoundGenericNominal ();
1192
- CurrentIGMPtr IGM = getGenModule (nominal->getDeclContext ());
1193
- emitLazySpecializedGenericTypeMetadata (*IGM.get (), type);
1214
+ CanType theType;
1215
+ TypeMetadataCanonicality canonicality;
1216
+ std::tie (theType, canonicality) =
1217
+ LazySpecializedTypeMetadataRecords.pop_back_val ();
1218
+ auto *nominal = theType->getNominalOrBoundGenericNominal ();
1219
+ CurrentIGMPtr IGMPtr = getGenModule (nominal->getDeclContext ());
1220
+ auto &IGM = *IGMPtr.get ();
1221
+ // A new canonical prespecialized metadata changes both the type
1222
+ // descriptor (adding a new entry to the trailing list of metadata) and
1223
+ // the metadata accessor (adding a new list of generic arguments against
1224
+ // which to compare the arguments to the function). Consequently, it is
1225
+ // necessary to force these to be reemitted.
1226
+ if (canonicality == TypeMetadataCanonicality::Canonical) {
1227
+ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords (
1228
+ IGM, theType, *nominal);
1229
+ }
1230
+ emitLazySpecializedGenericTypeMetadata (IGM, theType);
1194
1231
}
1195
1232
while (!LazyTypeContextDescriptors.empty ()) {
1196
1233
NominalTypeDecl *type = LazyTypeContextDescriptors.pop_back_val ();
@@ -1236,17 +1273,25 @@ void IRGenerator::emitLazyDefinitions() {
1236
1273
LazyCanonicalSpecializedMetadataAccessors.pop_back_val ();
1237
1274
auto *nominal = theType->getAnyNominal ();
1238
1275
assert (nominal);
1276
+ CurrentIGMPtr IGMPtr = getGenModule (nominal->getDeclContext ());
1277
+ auto &IGM = *IGMPtr.get ();
1278
+ // TODO: Once non-canonical accessors are available, this variable should
1279
+ // reflect the canonicality of the accessor rather than always being
1280
+ // canonical.
1281
+ auto canonicality = TypeMetadataCanonicality::Canonical;
1282
+ if (canonicality == TypeMetadataCanonicality::Canonical) {
1283
+ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords (
1284
+ IGM, theType, *nominal);
1285
+ }
1286
+ emitLazyCanonicalSpecializedMetadataAccessor (IGM, theType);
1287
+ }
1288
+ while (!LazyMetadataAccessors.empty ()) {
1289
+ NominalTypeDecl *nominal = LazyMetadataAccessors.pop_back_val ();
1239
1290
CurrentIGMPtr IGM = getGenModule (nominal->getDeclContext ());
1240
- emitLazyCanonicalSpecializedMetadataAccessor (*IGM.get (), theType );
1291
+ emitLazyMetadataAccessor (*IGM.get (), nominal );
1241
1292
}
1242
1293
}
1243
1294
1244
- while (!LazyMetadataAccessors.empty ()) {
1245
- NominalTypeDecl *nominal = LazyMetadataAccessors.pop_back_val ();
1246
- CurrentIGMPtr IGM = getGenModule (nominal->getDeclContext ());
1247
- emitLazyMetadataAccessor (*IGM.get (), nominal);
1248
- }
1249
-
1250
1295
FinishedEmittingLazyDefinitions = true ;
1251
1296
}
1252
1297
@@ -1442,17 +1487,19 @@ static bool typeKindCanBePrespecialized(TypeKind theKind) {
1442
1487
}
1443
1488
}
1444
1489
1445
- void IRGenerator::noteUseOfSpecializedGenericTypeMetadata (CanType type) {
1446
- assert (typeKindCanBePrespecialized (type->getKind ()));
1447
- auto key = type->getAnyNominal ();
1490
+ void IRGenerator::noteUseOfSpecializedGenericTypeMetadata (
1491
+ IRGenModule &IGM, CanType theType, TypeMetadataCanonicality canonicality) {
1492
+ assert (typeKindCanBePrespecialized (theType->getKind ()));
1493
+ auto key = theType->getAnyNominal ();
1448
1494
assert (key);
1449
1495
assert (key->isGenericContext ());
1450
- auto &enqueuedSpecializedTypes = CanonicalSpecializationsForGenericTypes[key];
1496
+ auto &enqueuedSpecializedTypes =
1497
+ MetadataPrespecializationsForGenericTypes[key];
1451
1498
if (llvm::all_of (enqueuedSpecializedTypes,
1452
- [&](CanType enqueued) { return enqueued != type ; })) {
1499
+ [&](auto enqueued) { return enqueued. first != theType ; })) {
1453
1500
assert (!FinishedEmittingLazyDefinitions);
1454
- LazySpecializedTypeMetadataRecords.push_back (type );
1455
- enqueuedSpecializedTypes.push_back (type );
1501
+ LazySpecializedTypeMetadataRecords.push_back ({theType, canonicality} );
1502
+ enqueuedSpecializedTypes.push_back ({theType, canonicality} );
1456
1503
}
1457
1504
}
1458
1505
@@ -4032,7 +4079,8 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
4032
4079
if (shouldPrespecializeGenericMetadata ()) {
4033
4080
if (auto nominal = concreteType->getAnyNominal ()) {
4034
4081
if (nominal->isGenericContext ()) {
4035
- IRGen.noteUseOfSpecializedGenericTypeMetadata (concreteType);
4082
+ IRGen.noteUseOfSpecializedGenericTypeMetadata (*this , concreteType,
4083
+ canonicality);
4036
4084
}
4037
4085
}
4038
4086
}
0 commit comments