Skip to content

Commit e3e107b

Browse files
committed
Teach IRGen how to derive associated type data for non-primary archetypes.
NFC for now because we're aggressively fulfilling associated type data.
1 parent c5408c8 commit e3e107b

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

benchmark/PerfTestSuite

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 0d8ae60c9fc58dcd51d78f60e7ced02b1d1e2730

lib/IRGen/GenArchetype.cpp

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,23 @@ using namespace irgen;
5252

5353
static llvm::Value *emitArchetypeTypeMetadataRef(IRGenFunction &IGF,
5454
CanArchetypeType archetype) {
55-
return IGF.getLocalTypeData(archetype, LocalTypeDataKind::forTypeMetadata());
55+
// Check for an existing cache entry.
56+
auto localDataKind = LocalTypeDataKind::forTypeMetadata();
57+
auto metadata = IGF.tryGetLocalTypeData(archetype, localDataKind);
58+
59+
// If that's not present, this must be an associated type.
60+
if (!metadata) {
61+
assert(!archetype->isPrimary() &&
62+
"type metadata for primary archetype was not bound in context");
63+
64+
CanArchetypeType parent(archetype->getParent());
65+
metadata = emitAssociatedTypeMetadataRef(IGF, parent,
66+
archetype->getAssocType());
67+
68+
IGF.setScopedLocalTypeData(archetype, localDataKind, metadata);
69+
}
70+
71+
return metadata;
5672
}
5773

5874
namespace {
@@ -88,8 +104,30 @@ class ArchetypeTypeInfoBase {
88104
unsigned which) const {
89105
assert(which < getNumStoredProtocols());
90106
auto protocol = archetype->getConformsTo()[which];
91-
return IGF.getLocalTypeData(archetype,
92-
LocalTypeDataKind::forAbstractProtocolWitnessTable(protocol));
107+
auto localDataKind =
108+
LocalTypeDataKind::forAbstractProtocolWitnessTable(protocol);
109+
110+
// Check for an existing cache entry.
111+
auto wtable = IGF.tryGetLocalTypeData(archetype, localDataKind);
112+
113+
// If that's not present, this must be an associated type; drill
114+
// down from the parent.
115+
if (!wtable) {
116+
assert(!archetype->isPrimary() &&
117+
"witness table for primary archetype was not bound in context");
118+
119+
// To do this, we need the metadata for the associated type.
120+
auto associatedMetadata = emitArchetypeTypeMetadataRef(IGF, archetype);
121+
122+
CanArchetypeType parent(archetype->getParent());
123+
wtable = emitAssociatedTypeWitnessTableRef(IGF, parent,
124+
archetype->getAssocType(),
125+
associatedMetadata,
126+
protocol);
127+
IGF.setScopedLocalTypeData(archetype, localDataKind, wtable);
128+
}
129+
130+
return wtable;
93131
}
94132
};
95133

@@ -174,10 +212,19 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF,
174212
assert(Lowering::TypeConverter::protocolRequiresWitnessTable(proto) &&
175213
"looking up witness table for protocol that doesn't have one");
176214

215+
// Check immediately for an existing cache entry.
216+
auto wtable = IGF.tryGetLocalTypeData(archetype,
217+
LocalTypeDataKind::forAbstractProtocolWitnessTable(proto));
218+
if (wtable) return wtable;
219+
220+
// Otherwise, find the best path from one of the protocols directly
221+
// conformed to by the protocol, then get that conformance.
222+
// TODO: this isn't necessarily optimal if the direct conformance isn't
223+
// concretely available; we really ought to be comparing the full paths
224+
// to this conformance from concrete sources.
177225
auto &archTI = getArchetypeInfo(IGF, archetype,
178226
IGF.getTypeInfoForLowered(archetype));
179-
auto wtable = emitImpliedWitnessTableRef(IGF, archTI.getStoredProtocols(),
180-
proto,
227+
wtable = emitImpliedWitnessTableRef(IGF, archTI.getStoredProtocols(), proto,
181228
[&](unsigned originIndex) -> llvm::Value* {
182229
return archTI.getWitnessTable(IGF, archetype, originIndex);
183230
});

0 commit comments

Comments
 (0)