Skip to content

Commit 305af04

Browse files
committed
IRGen: Split off WitnessTableBuilderBase from WitnessTableBuilder
1 parent c61ead1 commit 305af04

File tree

1 file changed

+127
-106
lines changed

1 file changed

+127
-106
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 127 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,11 +1148,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
11481148
}
11491149
};
11501150

1151-
/// A class which lays out a specific conformance to a protocol.
1152-
class WitnessTableBuilder : public SILWitnessVisitor<WitnessTableBuilder> {
1151+
class WitnessTableBuilderBase {
1152+
protected:
11531153
IRGenModule &IGM;
1154-
ConstantArrayBuilder &Table;
1155-
unsigned TableSize = ~0U; // will get overwritten unconditionally
11561154
SILWitnessTable *SILWT;
11571155
CanType ConcreteType;
11581156
const RootProtocolConformance &Conformance;
@@ -1162,22 +1160,15 @@ class AccessorConformanceInfo : public ConformanceInfo {
11621160
SILConditionalConformances;
11631161

11641162
Optional<FulfillmentMap> Fulfillments;
1165-
SmallVector<std::pair<size_t, const ConformanceInfo *>, 4>
1166-
SpecializedBaseConformances;
11671163

11681164
SmallVector<size_t, 4> ConditionalRequirementPrivateDataIndices;
11691165

11701166
// Conditional conformances and metadata caches are stored at negative
11711167
// offsets, with conditional conformances closest to 0.
11721168
unsigned NextPrivateDataIndex = 0;
1173-
bool ResilientConformance;
11741169

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),
11811172
ConcreteType(SILWT->getConformance()->getDeclContext()
11821173
->mapTypeIntoContext(
11831174
SILWT->getConformance()->getType())
@@ -1187,7 +1178,94 @@ class AccessorConformanceInfo : public ConformanceInfo {
11871178
mapConformanceIntoContext(IGM, Conformance,
11881179
Conformance.getDeclContext())),
11891180
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),
11911269
ResilientConformance(IGM.isResilientConformance(&Conformance)),
11921270
PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol(),
11931271
(ResilientConformance
@@ -1197,9 +1275,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
11971275
/// The number of entries in the witness table.
11981276
unsigned getTableSize() const { return TableSize; }
11991277

1200-
/// The number of private entries in the witness table.
1201-
unsigned getTablePrivateSize() const { return NextPrivateDataIndex; }
1202-
12031278
/// The top-level entry point.
12041279
void build();
12051280

@@ -1376,75 +1451,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
13761451
/// table specialization.
13771452
llvm::Constant *buildInstantiationFunction();
13781453

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-
14481454
public:
14491455
/// Collect the set of resilient witnesses, which will become part of the
14501456
/// protocol conformance descriptor.
@@ -1455,7 +1461,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
14551461

14561462
/// Build the witness table.
14571463
void WitnessTableBuilder::build() {
1458-
addConditionalConformances();
1464+
WitnessTableBuilderBase::build();
14591465
visitProtocolDecl(Conformance.getProtocol());
14601466
TableSize = Table.size();
14611467
}
@@ -1491,7 +1497,7 @@ static void buildAssociatedTypeValueName(CanType depAssociatedType,
14911497
}
14921498
}
14931499

1494-
llvm::Constant *WitnessTableBuilder::getAssociatedConformanceWitness(
1500+
llvm::Constant *WitnessTableBuilderBase::getAssociatedConformanceWitness(
14951501
AssociatedConformance requirement,
14961502
CanType associatedType,
14971503
ProtocolConformanceRef conformance) {
@@ -1502,7 +1508,7 @@ llvm::Constant *WitnessTableBuilder::getAssociatedConformanceWitness(
15021508
return IGM.getMangledAssociatedConformance(conf, requirement);
15031509
}
15041510

1505-
void WitnessTableBuilder::defineAssociatedTypeWitnessTableAccessFunction(
1511+
void WitnessTableBuilderBase::defineAssociatedTypeWitnessTableAccessFunction(
15061512
AssociatedConformance requirement,
15071513
CanType associatedType,
15081514
ProtocolConformanceRef associatedConformance) {
@@ -2155,24 +2161,23 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
21552161
auto conf = wt->getConformance();
21562162
PrettyStackTraceConformance _st(Context, "emitting witness table for", conf);
21572163

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);
21642169
SmallVector<llvm::Constant *, 4> resilientWitnesses;
2165-
// Collect the resilient witnesses to go into the conformance descriptor.
2166-
wtableBuilder.collectResilientWitnesses(resilientWitnesses);
21672170

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();
21702177

2171-
bool isDependent = isDependentConformance(conf);
2178+
// Produce the initializer value.
2179+
auto initializer = wtableContents.finishAndCreateFuture();
21722180

2173-
llvm::GlobalVariable *global = nullptr;
2174-
unsigned tableSize;
2175-
if (!isResilientConformance(conf)) {
21762181
global = cast<llvm::GlobalVariable>(
21772182
(isDependent && conf->getDeclContext()->isGenericContext())
21782183
? getAddrOfWitnessTablePattern(cast<NormalProtocolConformance>(conf),
@@ -2181,20 +2186,36 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
21812186
global->setConstant(isConstantWitnessTable(wt));
21822187
global->setAlignment(
21832188
llvm::MaybeAlign(getWitnessTableAlignment().getValue()));
2189+
21842190
tableSize = wtableBuilder.getTableSize();
2191+
tablePrivateSize = wtableBuilder.getTablePrivateSize();
2192+
2193+
instantiationFunction = wtableBuilder.buildInstantiationFunction();
21852194
} 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();
21862206
initializer.abandon();
2207+
21872208
tableSize = 0;
2209+
tablePrivateSize = wtableBuilder.getTablePrivateSize();
21882210
}
21892211

21902212
// Collect the information that will go into the protocol conformance
21912213
// descriptor.
21922214
ConformanceDescription description(conf, wt, global, tableSize,
2193-
wtableBuilder.getTablePrivateSize(),
2194-
isDependent);
2215+
tablePrivateSize, isDependent);
21952216

21962217
// Build the instantiation function, we if need one.
2197-
description.instantiationFn = wtableBuilder.buildInstantiationFunction();
2218+
description.instantiationFn = instantiationFunction;
21982219
description.resilientWitnesses = std::move(resilientWitnesses);
21992220

22002221
// Record this conformance descriptor.

0 commit comments

Comments
 (0)