Skip to content

Commit 5795bdf

Browse files
authored
Merge pull request #15200 from slavapestov/conditional-buffer-cleanup
IRGen: Clean up FIXME in emitConditionalConformancesBuffer()
2 parents b010833 + 10eb178 commit 5795bdf

File tree

1 file changed

+49
-63
lines changed

1 file changed

+49
-63
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 49 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,6 @@ class irgen::ConformanceInfo {
982982
public:
983983
virtual ~ConformanceInfo() {}
984984
virtual llvm::Value *getTable(IRGenFunction &IGF,
985-
CanType conformingType,
986985
llvm::Value **conformingMetadataCache) const = 0;
987986
/// Try to get this table as a constant pointer. This might just
988987
/// not be supportable at all.
@@ -991,7 +990,7 @@ class irgen::ConformanceInfo {
991990
};
992991

993992
static llvm::Value *
994-
emitConditionalConformancesBuffer(IRGenFunction &IGF, CanType conformingType,
993+
emitConditionalConformancesBuffer(IRGenFunction &IGF,
995994
const ProtocolConformance *conformance) {
996995
// Pointers to the witness tables, in the right order, which will be included
997996
// in the buffer that gets passed to the witness table accessor.
@@ -1000,30 +999,6 @@ emitConditionalConformancesBuffer(IRGenFunction &IGF, CanType conformingType,
1000999
auto subMap = conformance->getSubstitutions(IGF.IGM.getSwiftModule());
10011000
auto rootConformance = conformance->getRootNormalConformance();
10021001

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-
10271002
SILWitnessTable::enumerateWitnessTableConditionalConformances(
10281003
rootConformance, [&](unsigned, CanType type, ProtocolDecl *proto) {
10291004
auto substType = type.subst(subMap)->getCanonicalType();
@@ -1056,7 +1031,7 @@ emitConditionalConformancesBuffer(IRGenFunction &IGF, CanType conformingType,
10561031

10571032
static llvm::Value *emitWitnessTableAccessorCall(
10581033
IRGenFunction &IGF, const ProtocolConformance *conformance,
1059-
CanType conformingType, llvm::Value **srcMetadataCache) {
1034+
llvm::Value **srcMetadataCache) {
10601035
auto accessor = IGF.IGM.getAddrOfWitnessTableAccessFunction(
10611036
conformance->getRootNormalConformance(), NotForDefinition);
10621037

@@ -1066,11 +1041,12 @@ static llvm::Value *emitWitnessTableAccessorCall(
10661041
if (conformance->witnessTableAccessorRequiresArguments()) {
10671042
// Emit the source metadata if we haven't yet.
10681043
if (!*srcMetadataCache) {
1069-
*srcMetadataCache = IGF.emitTypeMetadataRef(conformingType);
1044+
*srcMetadataCache = IGF.emitTypeMetadataRef(
1045+
conformance->getType()->getCanonicalType());
10701046
}
10711047

10721048
auto conditionalTables =
1073-
emitConditionalConformancesBuffer(IGF, conformingType, conformance);
1049+
emitConditionalConformancesBuffer(IGF, conformance);
10741050

10751051
call = IGF.Builder.CreateCall(accessor,
10761052
{*srcMetadataCache, conditionalTables});
@@ -1090,9 +1066,10 @@ static llvm::Value *emitWitnessTableAccessorCall(
10901066
/// given type.
10911067
static llvm::Function *
10921068
getWitnessTableLazyAccessFunction(IRGenModule &IGM,
1093-
const ProtocolConformance *conformance,
1094-
CanType conformingType) {
1069+
const ProtocolConformance *conformance) {
1070+
auto conformingType = conformance->getType()->getCanonicalType();
10951071
assert(!conformingType->hasArchetype());
1072+
10961073
auto rootConformance = conformance->getRootNormalConformance();
10971074
llvm::Function *accessor = IGM.getAddrOfWitnessTableLazyAccessFunction(
10981075
rootConformance, conformingType, ForDefinition);
@@ -1112,13 +1089,23 @@ getWitnessTableLazyAccessFunction(IRGenModule &IGM,
11121089
emitLazyCacheAccessFunction(IGM, accessor, cacheVariable,
11131090
[&](IRGenFunction &IGF) -> llvm::Value* {
11141091
llvm::Value *conformingMetadataCache = nullptr;
1115-
return emitWitnessTableAccessorCall(IGF, conformance, conformingType,
1092+
return emitWitnessTableAccessorCall(IGF, conformance,
11161093
&conformingMetadataCache);
11171094
});
11181095

11191096
return accessor;
11201097
}
11211098

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+
11221109
namespace {
11231110

11241111
/// Conformance info for a witness table that can be directly generated.
@@ -1130,7 +1117,7 @@ class DirectConformanceInfo : public ConformanceInfo {
11301117
DirectConformanceInfo(const ProtocolConformance *C)
11311118
: RootConformance(C->getRootNormalConformance()) {}
11321119

1133-
llvm::Value *getTable(IRGenFunction &IGF, CanType conformingType,
1120+
llvm::Value *getTable(IRGenFunction &IGF,
11341121
llvm::Value **conformingMetadataCache) const override {
11351122
return IGF.IGM.getAddrOfWitnessTable(RootConformance);
11361123
}
@@ -1150,17 +1137,17 @@ class AccessorConformanceInfo : public ConformanceInfo {
11501137
public:
11511138
AccessorConformanceInfo(const ProtocolConformance *C) : Conformance(C) {}
11521139

1153-
llvm::Value *getTable(IRGenFunction &IGF, CanType type,
1140+
llvm::Value *getTable(IRGenFunction &IGF,
11541141
llvm::Value **typeMetadataCache) const override {
11551142
// 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,
11581145
typeMetadataCache);
11591146
}
11601147

11611148
// Otherwise, call a lazy-cache function.
11621149
auto accessor =
1163-
getWitnessTableLazyAccessFunction(IGF.IGM, Conformance, type);
1150+
getWitnessTableLazyAccessFunction(IGF.IGM, Conformance);
11641151
llvm::CallInst *call = IGF.Builder.CreateCall(accessor, {});
11651152
call->setCallingConv(IGF.IGM.DefaultCC);
11661153
call->setDoesNotAccessMemory();
@@ -1182,6 +1169,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
11821169
unsigned TableSize = ~0U; // will get overwritten unconditionally
11831170
CanType ConcreteType;
11841171
const NormalProtocolConformance &Conformance;
1172+
const ProtocolConformance &ConformanceInContext;
11851173
ArrayRef<SILWitnessTable::Entry> SILEntries;
11861174
ArrayRef<SILWitnessTable::ConditionalConformance>
11871175
SILConditionalConformances;
@@ -1207,6 +1195,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
12071195
->getCanonicalType())
12081196
->getCanonicalType()),
12091197
Conformance(*SILWT->getConformance()),
1198+
ConformanceInContext(mapConformanceIntoContext(IGM,
1199+
Conformance,
1200+
Conformance.getDeclContext())),
12101201
SILEntries(SILWT->getEntries()),
12111202
SILConditionalConformances(SILWT->getConditionalConformances()),
12121203
PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol())) {
@@ -1254,8 +1245,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
12541245

12551246
// Look for a protocol type info.
12561247
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+
12591251
const ConformanceInfo &conf =
12601252
basePI.getConformance(IGM, baseProto, astConf);
12611253

@@ -1328,15 +1320,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
13281320

13291321
SILEntries = SILEntries.slice(1);
13301322

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

13411327
llvm::Constant *metadataAccessFunction =
13421328
getAssociatedTypeMetadataAccessFunction(requirement, associate);
@@ -1346,17 +1332,14 @@ class AccessorConformanceInfo : public ConformanceInfo {
13461332
void addAssociatedConformance(AssociatedConformance requirement) {
13471333
// FIXME: Add static witness tables for type conformances.
13481334

1349-
auto interfaceAssociate =
1350-
Conformance.getAssociatedType(requirement.getAssociation());
1351-
assert(!interfaceAssociate->hasArchetype());
1352-
13531335
auto associate =
1354-
Conformance.getDeclContext()->mapTypeIntoContext(interfaceAssociate)
1355-
->getCanonicalType();
1336+
ConformanceInContext.getAssociatedType(
1337+
requirement.getAssociation())->getCanonicalType();
13561338

13571339
ProtocolConformanceRef associatedConformance =
1358-
Conformance.getAssociatedConformance(requirement.getAssociation(),
1359-
requirement.getAssociatedRequirement());
1340+
ConformanceInContext.getAssociatedConformance(
1341+
requirement.getAssociation(),
1342+
requirement.getAssociatedRequirement());
13601343

13611344
#ifndef NDEBUG
13621345
auto &entry = SILEntries.front();
@@ -1544,9 +1527,10 @@ getAssociatedTypeMetadataAccessFunction(AssociatedType requirement,
15441527
/// the conformance is being requested; it may ignore this (perhaps
15451528
/// implicitly by taking no arguments).
15461529
static llvm::Constant *
1547-
getOrCreateWitnessTableAccessFunction(IRGenModule &IGM, CanType type,
1530+
getOrCreateWitnessTableAccessFunction(IRGenModule &IGM,
15481531
ProtocolConformance *conformance) {
1549-
assert(!type->hasArchetype() && "cannot do this for dependent type");
1532+
assert(!conformance->getType()->hasArchetype() &&
1533+
"cannot do this for dependent type");
15501534

15511535
// We always emit an access function for conformances, and in principle
15521536
// it is always possible to just use that here directly. However,
@@ -1558,7 +1542,7 @@ getOrCreateWitnessTableAccessFunction(IRGenModule &IGM, CanType type,
15581542
// function.
15591543
auto rootConformance = conformance->getRootNormalConformance();
15601544
if (rootConformance->witnessTableAccessorRequiresArguments()) {
1561-
return getWitnessTableLazyAccessFunction(IGM, conformance, type);
1545+
return getWitnessTableLazyAccessFunction(IGM, conformance);
15621546
} else {
15631547
return IGM.getAddrOfWitnessTableAccessFunction(rootConformance,
15641548
NotForDefinition);
@@ -1583,7 +1567,7 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
15831567
if (!associatedType->hasArchetype()) {
15841568
assert(associatedConformance.isConcrete() &&
15851569
"no concrete conformance for non-dependent type");
1586-
return getOrCreateWitnessTableAccessFunction(IGM, associatedType,
1570+
return getOrCreateWitnessTableAccessFunction(IGM,
15871571
associatedConformance.getConcrete());
15881572
}
15891573

@@ -1630,6 +1614,8 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
16301614

16311615
const ConformanceInfo *conformanceI = nullptr;
16321616
if (associatedConformance.isConcrete()) {
1617+
assert(associatedType->isEqual(associatedConformance.getConcrete()->getType()));
1618+
16331619
const ProtocolInfo &protocolI = IGM.getProtocolInfo(associatedProtocol);
16341620
conformanceI =
16351621
&protocolI.getConformance(IGM, associatedProtocol,
@@ -1681,7 +1667,7 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
16811667
// Otherwise, we need a cache entry.
16821668
emitReturnOfCheckedLoadFromCache(IGF, destTable, self,
16831669
[&]() -> llvm::Value* {
1684-
return conformanceI->getTable(IGF, associatedType, &associatedTypeMetadata);
1670+
return conformanceI->getTable(IGF, &associatedTypeMetadata);
16851671
});
16861672

16871673
return accessor;
@@ -1896,7 +1882,7 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
18961882
for (auto &base : SpecializedBaseConformances) {
18971883
// Ask the ConformanceInfo to emit the wtable.
18981884
llvm::Value *baseWTable =
1899-
base.second->getTable(IGF, ConcreteType, &metadata);
1885+
base.second->getTable(IGF, &metadata);
19001886
baseWTable = IGF.Builder.CreateBitCast(baseWTable, IGM.Int8PtrTy);
19011887

19021888
// Store that to the appropriate slot in the new witness table.
@@ -2590,7 +2576,7 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
25902576
auto &protoI = IGF.IGM.getProtocolInfo(proto);
25912577
auto &conformanceI =
25922578
protoI.getConformance(IGF.IGM, proto, concreteConformance);
2593-
wtable = conformanceI.getTable(IGF, srcType, srcMetadataCache);
2579+
wtable = conformanceI.getTable(IGF, srcMetadataCache);
25942580

25952581
IGF.setScopedLocalTypeData(
25962582
srcType,

0 commit comments

Comments
 (0)