@@ -1148,11 +1148,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
1148
1148
}
1149
1149
};
1150
1150
1151
- // / A class which lays out a specific conformance to a protocol.
1152
- class WitnessTableBuilder : public SILWitnessVisitor <WitnessTableBuilder> {
1151
+ class WitnessTableBuilderBase {
1152
+ protected:
1153
1153
IRGenModule &IGM;
1154
- ConstantArrayBuilder &Table;
1155
- unsigned TableSize = ~0U ; // will get overwritten unconditionally
1156
1154
SILWitnessTable *SILWT;
1157
1155
CanType ConcreteType;
1158
1156
const RootProtocolConformance &Conformance;
@@ -1162,22 +1160,15 @@ class AccessorConformanceInfo : public ConformanceInfo {
1162
1160
SILConditionalConformances;
1163
1161
1164
1162
Optional<FulfillmentMap> Fulfillments;
1165
- SmallVector<std::pair<size_t , const ConformanceInfo *>, 4 >
1166
- SpecializedBaseConformances;
1167
1163
1168
1164
SmallVector<size_t , 4 > ConditionalRequirementPrivateDataIndices;
1169
1165
1170
1166
// Conditional conformances and metadata caches are stored at negative
1171
1167
// offsets, with conditional conformances closest to 0.
1172
1168
unsigned NextPrivateDataIndex = 0 ;
1173
- bool ResilientConformance;
1174
1169
1175
- const ProtocolInfo &PI;
1176
-
1177
- public:
1178
- WitnessTableBuilder (IRGenModule &IGM, ConstantArrayBuilder &table,
1179
- SILWitnessTable *SILWT)
1180
- : IGM(IGM), Table(table), SILWT(SILWT),
1170
+ WitnessTableBuilderBase (IRGenModule &IGM, SILWitnessTable *SILWT)
1171
+ : IGM(IGM), SILWT(SILWT),
1181
1172
ConcreteType (SILWT->getConformance ()->getDeclContext()
1182
1173
->mapTypeIntoContext(
1183
1174
SILWT->getConformance ()->getType())
@@ -1187,7 +1178,94 @@ class AccessorConformanceInfo : public ConformanceInfo {
1187
1178
mapConformanceIntoContext (IGM, Conformance,
1188
1179
Conformance.getDeclContext())),
1189
1180
SILEntries(SILWT->getEntries ()),
1190
- SILConditionalConformances(SILWT->getConditionalConformances ()),
1181
+ SILConditionalConformances(SILWT->getConditionalConformances ()) {}
1182
+
1183
+ void addConditionalConformances () {
1184
+ assert (NextPrivateDataIndex == 0 );
1185
+ for (auto conditional : SILConditionalConformances) {
1186
+ // We don't actually need to know anything about the specific
1187
+ // conformances here, just make sure we get right private data slots.
1188
+ (void )conditional;
1189
+
1190
+ auto reqtIndex = getNextPrivateDataIndex ();
1191
+ ConditionalRequirementPrivateDataIndices.push_back (reqtIndex);
1192
+ }
1193
+ }
1194
+
1195
+ void defineAssociatedTypeWitnessTableAccessFunction (
1196
+ AssociatedConformance requirement,
1197
+ CanType associatedType,
1198
+ ProtocolConformanceRef conformance);
1199
+
1200
+ llvm::Constant *getAssociatedConformanceWitness (
1201
+ AssociatedConformance requirement,
1202
+ CanType associatedType,
1203
+ ProtocolConformanceRef conformance);
1204
+
1205
+ // / Allocate another word of private data storage in the conformance table.
1206
+ unsigned getNextPrivateDataIndex () {
1207
+ return NextPrivateDataIndex++;
1208
+ }
1209
+
1210
+ const FulfillmentMap &getFulfillmentMap () {
1211
+ if (Fulfillments) return *Fulfillments;
1212
+
1213
+ Fulfillments.emplace ();
1214
+ if (ConcreteType->hasArchetype ()) {
1215
+ struct Callback : FulfillmentMap::InterestingKeysCallback {
1216
+ bool isInterestingType (CanType type) const override {
1217
+ return isa<ArchetypeType>(type);
1218
+ }
1219
+ bool hasInterestingType (CanType type) const override {
1220
+ return type->hasArchetype ();
1221
+ }
1222
+ bool hasLimitedInterestingConformances (CanType type) const override {
1223
+ return false ;
1224
+ }
1225
+ GenericSignature::ConformsToArray
1226
+ getInterestingConformances (CanType type) const override {
1227
+ llvm_unreachable (" no limits" );
1228
+ }
1229
+ CanType getSuperclassBound (CanType type) const override {
1230
+ if (auto superclassTy = cast<ArchetypeType>(type)->getSuperclass ())
1231
+ return superclassTy->getCanonicalType ();
1232
+ return CanType ();
1233
+ }
1234
+ } callback;
1235
+ Fulfillments->searchTypeMetadata (IGM, ConcreteType, IsExact,
1236
+ MetadataState::Abstract,
1237
+ /* sourceIndex*/ 0 , MetadataPath (),
1238
+ callback);
1239
+ }
1240
+ return *Fulfillments;
1241
+ }
1242
+
1243
+ // / The top-level entry point.
1244
+ void build () {
1245
+ addConditionalConformances ();
1246
+ }
1247
+
1248
+ public:
1249
+ // / The number of private entries in the witness table.
1250
+ unsigned getTablePrivateSize () const { return NextPrivateDataIndex; }
1251
+ };
1252
+
1253
+ // / A class which lays out a specific conformance to a protocol.
1254
+ class WitnessTableBuilder : public WitnessTableBuilderBase ,
1255
+ public SILWitnessVisitor<WitnessTableBuilder> {
1256
+ ConstantArrayBuilder &Table;
1257
+ unsigned TableSize = ~0U ; // will get overwritten unconditionally
1258
+ SmallVector<std::pair<size_t , const ConformanceInfo *>, 4 >
1259
+ SpecializedBaseConformances;
1260
+
1261
+ bool ResilientConformance;
1262
+
1263
+ const ProtocolInfo &PI;
1264
+
1265
+ public:
1266
+ WitnessTableBuilder (IRGenModule &IGM, ConstantArrayBuilder &table,
1267
+ SILWitnessTable *SILWT)
1268
+ : WitnessTableBuilderBase(IGM, SILWT), Table(table),
1191
1269
ResilientConformance (IGM.isResilientConformance(&Conformance)),
1192
1270
PI(IGM.getProtocolInfo(SILWT->getConformance ()->getProtocol(),
1193
1271
(ResilientConformance
@@ -1197,9 +1275,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
1197
1275
// / The number of entries in the witness table.
1198
1276
unsigned getTableSize () const { return TableSize; }
1199
1277
1200
- // / The number of private entries in the witness table.
1201
- unsigned getTablePrivateSize () const { return NextPrivateDataIndex; }
1202
-
1203
1278
// / The top-level entry point.
1204
1279
void build ();
1205
1280
@@ -1376,75 +1451,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
1376
1451
// / table specialization.
1377
1452
llvm::Constant *buildInstantiationFunction ();
1378
1453
1379
- private:
1380
- void addConditionalConformances () {
1381
- assert (NextPrivateDataIndex == 0 );
1382
- for (auto conditional : SILConditionalConformances) {
1383
- // We don't actually need to know anything about the specific
1384
- // conformances here, just make sure we get right private data slots.
1385
- (void )conditional;
1386
-
1387
- auto reqtIndex = getNextPrivateDataIndex ();
1388
- ConditionalRequirementPrivateDataIndices.push_back (reqtIndex);
1389
- }
1390
- }
1391
-
1392
- void defineAssociatedTypeWitnessTableAccessFunction (
1393
- AssociatedConformance requirement,
1394
- CanType associatedType,
1395
- ProtocolConformanceRef conformance);
1396
-
1397
- llvm::Constant *getAssociatedConformanceWitness (
1398
- AssociatedConformance requirement,
1399
- CanType associatedType,
1400
- ProtocolConformanceRef conformance);
1401
-
1402
- // / Allocate another word of private data storage in the conformance table.
1403
- unsigned getNextPrivateDataIndex () {
1404
- return NextPrivateDataIndex++;
1405
- }
1406
-
1407
- Address getAddressOfPrivateDataSlot (IRGenFunction &IGF, Address table,
1408
- unsigned index) {
1409
- assert (index < NextPrivateDataIndex);
1410
- return IGF.Builder .CreateConstArrayGEP (
1411
- table, privateWitnessTableIndexToTableOffset (index),
1412
- IGF.IGM .getPointerSize ());
1413
- }
1414
-
1415
- const FulfillmentMap &getFulfillmentMap () {
1416
- if (Fulfillments) return *Fulfillments;
1417
-
1418
- Fulfillments.emplace ();
1419
- if (ConcreteType->hasArchetype ()) {
1420
- struct Callback : FulfillmentMap::InterestingKeysCallback {
1421
- bool isInterestingType (CanType type) const override {
1422
- return isa<ArchetypeType>(type);
1423
- }
1424
- bool hasInterestingType (CanType type) const override {
1425
- return type->hasArchetype ();
1426
- }
1427
- bool hasLimitedInterestingConformances (CanType type) const override {
1428
- return false ;
1429
- }
1430
- GenericSignature::ConformsToArray
1431
- getInterestingConformances (CanType type) const override {
1432
- llvm_unreachable (" no limits" );
1433
- }
1434
- CanType getSuperclassBound (CanType type) const override {
1435
- if (auto superclassTy = cast<ArchetypeType>(type)->getSuperclass ())
1436
- return superclassTy->getCanonicalType ();
1437
- return CanType ();
1438
- }
1439
- } callback;
1440
- Fulfillments->searchTypeMetadata (IGM, ConcreteType, IsExact,
1441
- MetadataState::Abstract,
1442
- /* sourceIndex*/ 0 , MetadataPath (),
1443
- callback);
1444
- }
1445
- return *Fulfillments;
1446
- }
1447
-
1448
1454
public:
1449
1455
// / Collect the set of resilient witnesses, which will become part of the
1450
1456
// / protocol conformance descriptor.
@@ -1455,7 +1461,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
1455
1461
1456
1462
// / Build the witness table.
1457
1463
void WitnessTableBuilder::build () {
1458
- addConditionalConformances ();
1464
+ WitnessTableBuilderBase::build ();
1459
1465
visitProtocolDecl (Conformance.getProtocol ());
1460
1466
TableSize = Table.size ();
1461
1467
}
@@ -1491,7 +1497,7 @@ static void buildAssociatedTypeValueName(CanType depAssociatedType,
1491
1497
}
1492
1498
}
1493
1499
1494
- llvm::Constant *WitnessTableBuilder ::getAssociatedConformanceWitness (
1500
+ llvm::Constant *WitnessTableBuilderBase ::getAssociatedConformanceWitness (
1495
1501
AssociatedConformance requirement,
1496
1502
CanType associatedType,
1497
1503
ProtocolConformanceRef conformance) {
@@ -1502,7 +1508,7 @@ llvm::Constant *WitnessTableBuilder::getAssociatedConformanceWitness(
1502
1508
return IGM.getMangledAssociatedConformance (conf, requirement);
1503
1509
}
1504
1510
1505
- void WitnessTableBuilder ::defineAssociatedTypeWitnessTableAccessFunction (
1511
+ void WitnessTableBuilderBase ::defineAssociatedTypeWitnessTableAccessFunction (
1506
1512
AssociatedConformance requirement,
1507
1513
CanType associatedType,
1508
1514
ProtocolConformanceRef associatedConformance) {
@@ -2155,24 +2161,23 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
2155
2161
auto conf = wt->getConformance ();
2156
2162
PrettyStackTraceConformance _st (Context, " emitting witness table for" , conf);
2157
2163
2158
- // Build the witness table.
2159
- ConstantInitBuilder builder (*this );
2160
- auto wtableContents = builder.beginArray (Int8PtrTy);
2161
- WitnessTableBuilder wtableBuilder (*this , wtableContents, wt);
2162
- wtableBuilder.build ();
2163
-
2164
+ unsigned tableSize = 0 ;
2165
+ unsigned tablePrivateSize = 0 ;
2166
+ llvm::GlobalVariable *global = nullptr ;
2167
+ llvm::Constant *instantiationFunction = nullptr ;
2168
+ bool isDependent = isDependentConformance (conf);
2164
2169
SmallVector<llvm::Constant *, 4 > resilientWitnesses;
2165
- // Collect the resilient witnesses to go into the conformance descriptor.
2166
- wtableBuilder.collectResilientWitnesses (resilientWitnesses);
2167
2170
2168
- // Produce the initializer value.
2169
- auto initializer = wtableContents.finishAndCreateFuture ();
2171
+ if (!isResilientConformance (conf)) {
2172
+ // Build the witness table.
2173
+ ConstantInitBuilder builder (*this );
2174
+ auto wtableContents = builder.beginArray (Int8PtrTy);
2175
+ WitnessTableBuilder wtableBuilder (*this , wtableContents, wt);
2176
+ wtableBuilder.build ();
2170
2177
2171
- bool isDependent = isDependentConformance (conf);
2178
+ // Produce the initializer value.
2179
+ auto initializer = wtableContents.finishAndCreateFuture ();
2172
2180
2173
- llvm::GlobalVariable *global = nullptr ;
2174
- unsigned tableSize;
2175
- if (!isResilientConformance (conf)) {
2176
2181
global = cast<llvm::GlobalVariable>(
2177
2182
(isDependent && conf->getDeclContext ()->isGenericContext ())
2178
2183
? getAddrOfWitnessTablePattern (cast<NormalProtocolConformance>(conf),
@@ -2181,20 +2186,36 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
2181
2186
global->setConstant (isConstantWitnessTable (wt));
2182
2187
global->setAlignment (
2183
2188
llvm::MaybeAlign (getWitnessTableAlignment ().getValue ()));
2189
+
2184
2190
tableSize = wtableBuilder.getTableSize ();
2191
+ tablePrivateSize = wtableBuilder.getTablePrivateSize ();
2192
+
2193
+ instantiationFunction = wtableBuilder.buildInstantiationFunction ();
2185
2194
} else {
2195
+ // Build the witness table.
2196
+ ConstantInitBuilder builder (*this );
2197
+ auto wtableContents = builder.beginArray (Int8PtrTy);
2198
+ WitnessTableBuilder wtableBuilder (*this , wtableContents, wt);
2199
+ wtableBuilder.build ();
2200
+
2201
+ // Collect the resilient witnesses to go into the conformance descriptor.
2202
+ wtableBuilder.collectResilientWitnesses (resilientWitnesses);
2203
+
2204
+ // Produce the initializer value.
2205
+ auto initializer = wtableContents.finishAndCreateFuture ();
2186
2206
initializer.abandon ();
2207
+
2187
2208
tableSize = 0 ;
2209
+ tablePrivateSize = wtableBuilder.getTablePrivateSize ();
2188
2210
}
2189
2211
2190
2212
// Collect the information that will go into the protocol conformance
2191
2213
// descriptor.
2192
2214
ConformanceDescription description (conf, wt, global, tableSize,
2193
- wtableBuilder.getTablePrivateSize (),
2194
- isDependent);
2215
+ tablePrivateSize, isDependent);
2195
2216
2196
2217
// Build the instantiation function, we if need one.
2197
- description.instantiationFn = wtableBuilder. buildInstantiationFunction () ;
2218
+ description.instantiationFn = instantiationFunction ;
2198
2219
description.resilientWitnesses = std::move (resilientWitnesses);
2199
2220
2200
2221
// Record this conformance descriptor.
0 commit comments