@@ -982,7 +982,6 @@ class irgen::ConformanceInfo {
982
982
public:
983
983
virtual ~ConformanceInfo () {}
984
984
virtual llvm::Value *getTable (IRGenFunction &IGF,
985
- CanType conformingType,
986
985
llvm::Value **conformingMetadataCache) const = 0;
987
986
// / Try to get this table as a constant pointer. This might just
988
987
// / not be supportable at all.
@@ -991,7 +990,7 @@ class irgen::ConformanceInfo {
991
990
};
992
991
993
992
static llvm::Value *
994
- emitConditionalConformancesBuffer (IRGenFunction &IGF, CanType conformingType,
993
+ emitConditionalConformancesBuffer (IRGenFunction &IGF,
995
994
const ProtocolConformance *conformance) {
996
995
// Pointers to the witness tables, in the right order, which will be included
997
996
// in the buffer that gets passed to the witness table accessor.
@@ -1000,30 +999,6 @@ emitConditionalConformancesBuffer(IRGenFunction &IGF, CanType conformingType,
1000
999
auto subMap = conformance->getSubstitutions (IGF.IGM .getSwiftModule ());
1001
1000
auto rootConformance = conformance->getRootNormalConformance ();
1002
1001
1003
- // Find the generic environment into which the witness table should be
1004
- // mapped.
1005
- // FIXME: Passing conformingType down for just this purpose feels like a
1006
- // hack.
1007
- if (conformingType->hasArchetype () &&
1008
- conformance->getType ()->hasTypeParameter ()) {
1009
- GenericEnvironment *conformingTypeEnv = nullptr ;
1010
- conformingType.findIf ([&](Type type) {
1011
- if (auto archetype = type->getAs <ArchetypeType>()) {
1012
- conformingTypeEnv = archetype->getGenericEnvironment ();
1013
- return conformingTypeEnv != nullptr ;
1014
- }
1015
-
1016
- return false ;
1017
- });
1018
-
1019
- if (conformingTypeEnv) {
1020
- subMap = subMap.subst ([&](SubstitutableType *dependentType) {
1021
- return conformingTypeEnv->mapTypeIntoContext (Type (dependentType));
1022
- },
1023
- LookUpConformanceInModule (IGF.getSwiftModule ()));
1024
- }
1025
- }
1026
-
1027
1002
SILWitnessTable::enumerateWitnessTableConditionalConformances (
1028
1003
rootConformance, [&](unsigned , CanType type, ProtocolDecl *proto) {
1029
1004
auto substType = type.subst (subMap)->getCanonicalType ();
@@ -1056,7 +1031,7 @@ emitConditionalConformancesBuffer(IRGenFunction &IGF, CanType conformingType,
1056
1031
1057
1032
static llvm::Value *emitWitnessTableAccessorCall (
1058
1033
IRGenFunction &IGF, const ProtocolConformance *conformance,
1059
- CanType conformingType, llvm::Value **srcMetadataCache) {
1034
+ llvm::Value **srcMetadataCache) {
1060
1035
auto accessor = IGF.IGM .getAddrOfWitnessTableAccessFunction (
1061
1036
conformance->getRootNormalConformance (), NotForDefinition);
1062
1037
@@ -1066,11 +1041,12 @@ static llvm::Value *emitWitnessTableAccessorCall(
1066
1041
if (conformance->witnessTableAccessorRequiresArguments ()) {
1067
1042
// Emit the source metadata if we haven't yet.
1068
1043
if (!*srcMetadataCache) {
1069
- *srcMetadataCache = IGF.emitTypeMetadataRef (conformingType);
1044
+ *srcMetadataCache = IGF.emitTypeMetadataRef (
1045
+ conformance->getType ()->getCanonicalType ());
1070
1046
}
1071
1047
1072
1048
auto conditionalTables =
1073
- emitConditionalConformancesBuffer (IGF, conformingType, conformance);
1049
+ emitConditionalConformancesBuffer (IGF, conformance);
1074
1050
1075
1051
call = IGF.Builder .CreateCall (accessor,
1076
1052
{*srcMetadataCache, conditionalTables});
@@ -1090,9 +1066,10 @@ static llvm::Value *emitWitnessTableAccessorCall(
1090
1066
// / given type.
1091
1067
static llvm::Function *
1092
1068
getWitnessTableLazyAccessFunction (IRGenModule &IGM,
1093
- const ProtocolConformance *conformance,
1094
- CanType conformingType) {
1069
+ const ProtocolConformance *conformance) {
1070
+ auto conformingType = conformance-> getType ()-> getCanonicalType ();
1095
1071
assert (!conformingType->hasArchetype ());
1072
+
1096
1073
auto rootConformance = conformance->getRootNormalConformance ();
1097
1074
llvm::Function *accessor = IGM.getAddrOfWitnessTableLazyAccessFunction (
1098
1075
rootConformance, conformingType, ForDefinition);
@@ -1112,13 +1089,23 @@ getWitnessTableLazyAccessFunction(IRGenModule &IGM,
1112
1089
emitLazyCacheAccessFunction (IGM, accessor, cacheVariable,
1113
1090
[&](IRGenFunction &IGF) -> llvm::Value* {
1114
1091
llvm::Value *conformingMetadataCache = nullptr ;
1115
- return emitWitnessTableAccessorCall (IGF, conformance, conformingType,
1092
+ return emitWitnessTableAccessorCall (IGF, conformance,
1116
1093
&conformingMetadataCache);
1117
1094
});
1118
1095
1119
1096
return accessor;
1120
1097
}
1121
1098
1099
+ static ProtocolConformance &mapConformanceIntoContext (IRGenModule &IGM,
1100
+ const ProtocolConformance &conf,
1101
+ DeclContext *dc) {
1102
+ return *conf.subst (dc->mapTypeIntoContext (conf.getType ()),
1103
+ [&](SubstitutableType *t) -> Type {
1104
+ return dc->mapTypeIntoContext (t);
1105
+ },
1106
+ LookUpConformanceInModule (IGM.getSwiftModule ()));
1107
+ }
1108
+
1122
1109
namespace {
1123
1110
1124
1111
// / Conformance info for a witness table that can be directly generated.
@@ -1130,7 +1117,7 @@ class DirectConformanceInfo : public ConformanceInfo {
1130
1117
DirectConformanceInfo (const ProtocolConformance *C)
1131
1118
: RootConformance(C->getRootNormalConformance ()) {}
1132
1119
1133
- llvm::Value *getTable (IRGenFunction &IGF, CanType conformingType,
1120
+ llvm::Value *getTable (IRGenFunction &IGF,
1134
1121
llvm::Value **conformingMetadataCache) const override {
1135
1122
return IGF.IGM .getAddrOfWitnessTable (RootConformance);
1136
1123
}
@@ -1150,17 +1137,17 @@ class AccessorConformanceInfo : public ConformanceInfo {
1150
1137
public:
1151
1138
AccessorConformanceInfo (const ProtocolConformance *C) : Conformance(C) {}
1152
1139
1153
- llvm::Value *getTable (IRGenFunction &IGF, CanType type,
1140
+ llvm::Value *getTable (IRGenFunction &IGF,
1154
1141
llvm::Value **typeMetadataCache) const override {
1155
1142
// If we're looking up a dependent type, we can't cache the result.
1156
- if (type ->hasArchetype ()) {
1157
- return emitWitnessTableAccessorCall (IGF, Conformance, type,
1143
+ if (Conformance-> getType () ->hasArchetype ()) {
1144
+ return emitWitnessTableAccessorCall (IGF, Conformance,
1158
1145
typeMetadataCache);
1159
1146
}
1160
1147
1161
1148
// Otherwise, call a lazy-cache function.
1162
1149
auto accessor =
1163
- getWitnessTableLazyAccessFunction (IGF.IGM , Conformance, type );
1150
+ getWitnessTableLazyAccessFunction (IGF.IGM , Conformance);
1164
1151
llvm::CallInst *call = IGF.Builder .CreateCall (accessor, {});
1165
1152
call->setCallingConv (IGF.IGM .DefaultCC );
1166
1153
call->setDoesNotAccessMemory ();
@@ -1182,6 +1169,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
1182
1169
unsigned TableSize = ~0U ; // will get overwritten unconditionally
1183
1170
CanType ConcreteType;
1184
1171
const NormalProtocolConformance &Conformance;
1172
+ const ProtocolConformance &ConformanceInContext;
1185
1173
ArrayRef<SILWitnessTable::Entry> SILEntries;
1186
1174
ArrayRef<SILWitnessTable::ConditionalConformance>
1187
1175
SILConditionalConformances;
@@ -1207,6 +1195,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
1207
1195
->getCanonicalType())
1208
1196
->getCanonicalType()),
1209
1197
Conformance(*SILWT->getConformance ()),
1198
+ ConformanceInContext(mapConformanceIntoContext(IGM,
1199
+ Conformance,
1200
+ Conformance.getDeclContext())),
1210
1201
SILEntries(SILWT->getEntries ()),
1211
1202
SILConditionalConformances(SILWT->getConditionalConformances ()),
1212
1203
PI(IGM.getProtocolInfo(SILWT->getConformance ()->getProtocol())) {
@@ -1254,8 +1245,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
1254
1245
1255
1246
// Look for a protocol type info.
1256
1247
const ProtocolInfo &basePI = IGM.getProtocolInfo (baseProto);
1257
- const ProtocolConformance *astConf
1258
- = Conformance.getInheritedConformance (baseProto);
1248
+ auto *astConf = ConformanceInContext.getInheritedConformance (baseProto);
1249
+ assert (astConf->getType ()->isEqual (ConcreteType));
1250
+
1259
1251
const ConformanceInfo &conf =
1260
1252
basePI.getConformance (IGM, baseProto, astConf);
1261
1253
@@ -1328,15 +1320,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
1328
1320
1329
1321
SILEntries = SILEntries.slice (1 );
1330
1322
1331
- auto interfaceAssociate =
1332
- Conformance.getTypeWitness (requirement.getAssociation (), nullptr );
1333
-
1334
- // This type will be expressed in terms of the archetypes
1335
- // of the conforming context.
1336
- assert (!interfaceAssociate->hasArchetype ());
1337
- auto associate = Conformance.getDeclContext ()->mapTypeIntoContext (interfaceAssociate)
1338
- ->getCanonicalType ();
1339
-
1323
+ auto associate =
1324
+ ConformanceInContext.getTypeWitness (
1325
+ requirement.getAssociation (), nullptr )->getCanonicalType ();
1340
1326
1341
1327
llvm::Constant *metadataAccessFunction =
1342
1328
getAssociatedTypeMetadataAccessFunction (requirement, associate);
@@ -1346,17 +1332,14 @@ class AccessorConformanceInfo : public ConformanceInfo {
1346
1332
void addAssociatedConformance (AssociatedConformance requirement) {
1347
1333
// FIXME: Add static witness tables for type conformances.
1348
1334
1349
- auto interfaceAssociate =
1350
- Conformance.getAssociatedType (requirement.getAssociation ());
1351
- assert (!interfaceAssociate->hasArchetype ());
1352
-
1353
1335
auto associate =
1354
- Conformance. getDeclContext ()-> mapTypeIntoContext (interfaceAssociate)
1355
- ->getCanonicalType ();
1336
+ ConformanceInContext. getAssociatedType (
1337
+ requirement. getAssociation ()) ->getCanonicalType ();
1356
1338
1357
1339
ProtocolConformanceRef associatedConformance =
1358
- Conformance.getAssociatedConformance (requirement.getAssociation (),
1359
- requirement.getAssociatedRequirement ());
1340
+ ConformanceInContext.getAssociatedConformance (
1341
+ requirement.getAssociation (),
1342
+ requirement.getAssociatedRequirement ());
1360
1343
1361
1344
#ifndef NDEBUG
1362
1345
auto &entry = SILEntries.front ();
@@ -1544,9 +1527,10 @@ getAssociatedTypeMetadataAccessFunction(AssociatedType requirement,
1544
1527
// / the conformance is being requested; it may ignore this (perhaps
1545
1528
// / implicitly by taking no arguments).
1546
1529
static llvm::Constant *
1547
- getOrCreateWitnessTableAccessFunction (IRGenModule &IGM, CanType type,
1530
+ getOrCreateWitnessTableAccessFunction (IRGenModule &IGM,
1548
1531
ProtocolConformance *conformance) {
1549
- assert (!type->hasArchetype () && " cannot do this for dependent type" );
1532
+ assert (!conformance->getType ()->hasArchetype () &&
1533
+ " cannot do this for dependent type" );
1550
1534
1551
1535
// We always emit an access function for conformances, and in principle
1552
1536
// it is always possible to just use that here directly. However,
@@ -1558,7 +1542,7 @@ getOrCreateWitnessTableAccessFunction(IRGenModule &IGM, CanType type,
1558
1542
// function.
1559
1543
auto rootConformance = conformance->getRootNormalConformance ();
1560
1544
if (rootConformance->witnessTableAccessorRequiresArguments ()) {
1561
- return getWitnessTableLazyAccessFunction (IGM, conformance, type );
1545
+ return getWitnessTableLazyAccessFunction (IGM, conformance);
1562
1546
} else {
1563
1547
return IGM.getAddrOfWitnessTableAccessFunction (rootConformance,
1564
1548
NotForDefinition);
@@ -1583,7 +1567,7 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
1583
1567
if (!associatedType->hasArchetype ()) {
1584
1568
assert (associatedConformance.isConcrete () &&
1585
1569
" no concrete conformance for non-dependent type" );
1586
- return getOrCreateWitnessTableAccessFunction (IGM, associatedType,
1570
+ return getOrCreateWitnessTableAccessFunction (IGM,
1587
1571
associatedConformance.getConcrete ());
1588
1572
}
1589
1573
@@ -1630,6 +1614,8 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
1630
1614
1631
1615
const ConformanceInfo *conformanceI = nullptr ;
1632
1616
if (associatedConformance.isConcrete ()) {
1617
+ assert (associatedType->isEqual (associatedConformance.getConcrete ()->getType ()));
1618
+
1633
1619
const ProtocolInfo &protocolI = IGM.getProtocolInfo (associatedProtocol);
1634
1620
conformanceI =
1635
1621
&protocolI.getConformance (IGM, associatedProtocol,
@@ -1681,7 +1667,7 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
1681
1667
// Otherwise, we need a cache entry.
1682
1668
emitReturnOfCheckedLoadFromCache (IGF, destTable, self,
1683
1669
[&]() -> llvm::Value* {
1684
- return conformanceI->getTable (IGF, associatedType, &associatedTypeMetadata);
1670
+ return conformanceI->getTable (IGF, &associatedTypeMetadata);
1685
1671
});
1686
1672
1687
1673
return accessor;
@@ -1896,7 +1882,7 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
1896
1882
for (auto &base : SpecializedBaseConformances) {
1897
1883
// Ask the ConformanceInfo to emit the wtable.
1898
1884
llvm::Value *baseWTable =
1899
- base.second ->getTable (IGF, ConcreteType, &metadata);
1885
+ base.second ->getTable (IGF, &metadata);
1900
1886
baseWTable = IGF.Builder .CreateBitCast (baseWTable, IGM.Int8PtrTy );
1901
1887
1902
1888
// Store that to the appropriate slot in the new witness table.
@@ -2590,7 +2576,7 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
2590
2576
auto &protoI = IGF.IGM .getProtocolInfo (proto);
2591
2577
auto &conformanceI =
2592
2578
protoI.getConformance (IGF.IGM , proto, concreteConformance);
2593
- wtable = conformanceI.getTable (IGF, srcType, srcMetadataCache);
2579
+ wtable = conformanceI.getTable (IGF, srcMetadataCache);
2594
2580
2595
2581
IGF.setScopedLocalTypeData (
2596
2582
srcType,
0 commit comments