Skip to content

Commit c90a77d

Browse files
committed
IRGen: Use SubstitutionMap instead of ArrayRef<Substitution> in a few places
The crazy indexing logic is gone.
1 parent cf4043b commit c90a77d

File tree

9 files changed

+44
-105
lines changed

9 files changed

+44
-105
lines changed

lib/IRGen/Fulfillment.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ bool FulfillmentMap::searchBoundGenericTypeMetadata(IRGenModule &IGM,
242242

243243
GenericTypeRequirements requirements(IGM, type->getDecl());
244244
requirements.enumerateFulfillments(
245-
IGM, type->gatherAllSubstitutions(IGM.getSwiftModule(), nullptr),
245+
IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), type->getDecl()),
246246
[&](unsigned reqtIndex, CanType arg,
247247
Optional<ProtocolConformanceRef> conf) {
248248
// Skip uninteresting type arguments.

lib/IRGen/GenFunc.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,8 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
848848
&& "should have substitutions iff original function is generic");
849849
WitnessMetadata witnessMetadata;
850850
if (hasPolymorphicParameters(origType)) {
851-
emitPolymorphicArguments(subIGF, origType, substType, subs,
851+
auto subMap = origType->getGenericSignature()->getSubstitutionMap(subs);
852+
emitPolymorphicArguments(subIGF, origType, substType, subMap,
852853
&witnessMetadata, polyArgs);
853854
}
854855

@@ -1169,8 +1170,11 @@ void irgen::emitFunctionPartialApplication(IRGenFunction &IGF,
11691170
SmallVector<ParameterConvention, 4> argConventions;
11701171

11711172
// Reserve space for polymorphic bindings.
1173+
SubstitutionMap subMap;
1174+
if (auto genericSig = origType->getGenericSignature())
1175+
subMap = genericSig->getSubstitutionMap(subs);
11721176
auto bindings = NecessaryBindings::forFunctionInvocations(IGF.IGM,
1173-
origType, substType, subs);
1177+
origType, substType, subMap);
11741178
if (!bindings.empty()) {
11751179
hasSingleSwiftRefcountedContext = No;
11761180
auto bindingsSize = bindings.getBufferSize(IGF.IGM);

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ namespace {
208208
}
209209

210210
auto subs =
211-
type->gatherAllSubstitutions(IGF.IGM.getSwiftModule(), nullptr);
211+
type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl);
212212
requirements.enumerateFulfillments(IGF.IGM, subs,
213213
[&](unsigned reqtIndex, CanType type,
214214
Optional<ProtocolConformanceRef> conf) {

lib/IRGen/GenProto.cpp

Lines changed: 24 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -623,49 +623,6 @@ void irgen::setProtocolWitnessTableName(IRGenModule &IGM, llvm::Value *wtable,
623623
wtable->setName(name);
624624
}
625625

626-
/// Return the index of the given dependent type in the list of all
627-
/// dependent types.
628-
///
629-
/// This will be its index in the list of substitutions.
630-
static unsigned getDependentTypeIndex(CanGenericSignature generics,
631-
ModuleDecl &M, CanType type) {
632-
assert(type->isTypeParameter());
633-
634-
// Make a pass over all the dependent types.
635-
unsigned index = 0;
636-
for (auto depTy : generics->getAllDependentTypes()) {
637-
if (depTy->isEqual(type))
638-
return index;
639-
index++;
640-
}
641-
642-
llvm_unreachable("didn't find dependent type in all-dependent-types list");
643-
}
644-
645-
/// Return the index of the given protocol conformance in the list of all
646-
/// protocol conformances for the given dependent type in the given signature.
647-
///
648-
/// This will be its index in the list of protocol conformances on the
649-
/// dependent type's substitution.
650-
static unsigned
651-
getProtocolConformanceIndex(CanGenericSignature generics, ModuleDecl &M,
652-
CanType type, ProtocolDecl *protocol) {
653-
assert(type->isTypeParameter());
654-
655-
// Make a pass over all the dependent types.
656-
unsigned index = 0;
657-
for (auto reqt : generics->getRequirements()) {
658-
if (reqt.getKind() == RequirementKind::Conformance &&
659-
reqt.getFirstType()->isEqual(type)) {
660-
if (reqt.getSecondType()->getAnyNominal() == protocol)
661-
return index;
662-
index++;
663-
}
664-
}
665-
666-
llvm_unreachable("didn't find dependent type in all-dependent-types list");
667-
}
668-
669626
namespace {
670627
/// A concrete witness table, together with its known layout.
671628
class WitnessTable {
@@ -2037,15 +1994,12 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF,
20371994
auto &requirement = requirements.getRequirements()[reqtIndex];
20381995

20391996
auto module = IGF.getSwiftModule();
2040-
auto generics = generic->getDecl()->getGenericSignatureOfContext()
2041-
->getCanonicalSignature();
2042-
2043-
auto argIndex =
2044-
getDependentTypeIndex(generics, *module, requirement.TypeParameter);
2045-
Substitution sub = generic->gatherAllSubstitutions(module, nullptr)[argIndex];
1997+
auto subs = generic->getContextSubstitutionMap(module,
1998+
generic->getDecl());
1999+
auto sub = requirement.TypeParameter.subst(subs)->getCanonicalType();
20462000

20472001
// In either case, we need to change the type.
2048-
sourceKey.Type = sub.getReplacement()->getCanonicalType();
2002+
sourceKey.Type = sub;
20492003

20502004
// If this is a type argument, we've fully updated sourceKey.
20512005
if (component.getKind() == Component::Kind::NominalTypeArgument) {
@@ -2060,10 +2014,8 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF,
20602014
// conformance kind.
20612015
} else {
20622016
assert(requirement.Protocol && "index mismatch!");
2063-
auto confIndex = getProtocolConformanceIndex(generics, *module,
2064-
requirement.TypeParameter,
2065-
requirement.Protocol);
2066-
auto conformance = sub.getConformances()[confIndex];
2017+
auto conformance = *subs.lookupConformance(requirement.TypeParameter,
2018+
requirement.Protocol);
20672019
assert(conformance.getRequirement() == requirement.Protocol);
20682020
sourceKey.Kind = LocalTypeDataKind::forProtocolWitnessTable(conformance);
20692021

@@ -2339,7 +2291,7 @@ void irgen::emitWitnessTableRefs(IRGenFunction &IGF,
23392291
}
23402292

23412293
static CanType getSubstSelfType(CanSILFunctionType origFnType,
2342-
ArrayRef<Substitution> subs) {
2294+
const SubstitutionMap &subs) {
23432295
// Grab the apparent 'self' type. If there isn't a 'self' type,
23442296
// we're not going to try to access this anyway.
23452297
assert(!origFnType->getParameters().empty());
@@ -2366,8 +2318,7 @@ static CanType getSubstSelfType(CanSILFunctionType origFnType,
23662318
// SIL function type to make that work, which could be managed by having a
23672319
// "substituted generic signature" concept.
23682320
if (!subs.empty()) {
2369-
auto subMap = origFnType->getGenericSignature()->getSubstitutionMap(subs);
2370-
inputType = inputType.subst(subMap)->getCanonicalType();
2321+
inputType = inputType.subst(subs)->getCanonicalType();
23712322
}
23722323

23732324
return inputType;
@@ -2381,11 +2332,11 @@ namespace {
23812332
CanSILFunctionType polyFn)
23822333
: PolymorphicConvention(IGF.IGM, polyFn), IGF(IGF) {}
23832334

2384-
void emit(CanSILFunctionType substFnType, ArrayRef<Substitution> subs,
2335+
void emit(CanSILFunctionType substFnType, const SubstitutionMap &subs,
23852336
WitnessMetadata *witnessMetadata, Explosion &out);
23862337

23872338
private:
2388-
void emitEarlySources(ArrayRef<Substitution> subs, Explosion &out) {
2339+
void emitEarlySources(const SubstitutionMap &subs, Explosion &out) {
23892340
for (auto &source : getSources()) {
23902341
switch (source.getKind()) {
23912342
// Already accounted for in the parameters.
@@ -2415,15 +2366,15 @@ namespace {
24152366
void irgen::emitPolymorphicArguments(IRGenFunction &IGF,
24162367
CanSILFunctionType origFnType,
24172368
CanSILFunctionType substFnType,
2418-
ArrayRef<Substitution> subs,
2369+
const SubstitutionMap &subs,
24192370
WitnessMetadata *witnessMetadata,
24202371
Explosion &out) {
24212372
EmitPolymorphicArguments(IGF, origFnType).emit(substFnType, subs,
24222373
witnessMetadata, out);
24232374
}
24242375

24252376
void EmitPolymorphicArguments::emit(CanSILFunctionType substFnType,
2426-
ArrayRef<Substitution> subs,
2377+
const SubstitutionMap &subs,
24272378
WitnessMetadata *witnessMetadata,
24282379
Explosion &out) {
24292380
// Add all the early sources.
@@ -2469,7 +2420,7 @@ NecessaryBindings
24692420
NecessaryBindings::forFunctionInvocations(IRGenModule &IGM,
24702421
CanSILFunctionType origType,
24712422
CanSILFunctionType substType,
2472-
ArrayRef<Substitution> subs) {
2423+
const SubstitutionMap &subs) {
24732424
NecessaryBindings bindings;
24742425

24752426
// Bail out early if we don't have polymorphic parameters.
@@ -2482,21 +2433,11 @@ NecessaryBindings::forFunctionInvocations(IRGenModule &IGM,
24822433
// - unfulfilled requirements
24832434
convention.enumerateUnfulfilledRequirements(
24842435
[&](GenericRequirement requirement) {
2485-
auto depTyIndex =
2486-
getDependentTypeIndex(origType->getGenericSignature(),
2487-
*IGM.getSwiftModule(),
2488-
requirement.TypeParameter);
2489-
2490-
auto &sub = subs[depTyIndex];
2491-
CanType type = sub.getReplacement()->getCanonicalType();
2436+
CanType type = requirement.TypeParameter.subst(subs)->getCanonicalType();
24922437

24932438
if (requirement.Protocol) {
2494-
auto confIndex =
2495-
getProtocolConformanceIndex(origType->getGenericSignature(),
2496-
*IGM.getSwiftModule(),
2497-
requirement.TypeParameter,
2498-
requirement.Protocol);
2499-
auto conf = sub.getConformances()[confIndex];
2439+
auto conf = *subs.lookupConformance(requirement.TypeParameter,
2440+
requirement.Protocol);
25002441
bindings.addProtocolConformance(type, conf);
25012442
} else {
25022443
bindings.addTypeMetadata(type);
@@ -2583,23 +2524,16 @@ GenericTypeRequirements::GenericTypeRequirements(IRGenModule &IGM,
25832524

25842525
void
25852526
GenericTypeRequirements::enumerateFulfillments(IRGenModule &IGM,
2586-
ArrayRef<Substitution> subs,
2527+
const SubstitutionMap &subs,
25872528
FulfillmentCallback callback) {
25882529
if (empty()) return;
25892530

2590-
auto signature =
2591-
TheDecl->getGenericSignatureOfContext()->getCanonicalSignature();
25922531
for (auto reqtIndex : indices(getRequirements())) {
25932532
auto &reqt = getRequirements()[reqtIndex];
2594-
auto typeIndex = getDependentTypeIndex(signature, *IGM.getSwiftModule(),
2595-
reqt.TypeParameter);
2596-
auto &sub = subs[typeIndex];
2597-
CanType type = sub.getReplacement()->getCanonicalType();
2533+
CanType type = reqt.TypeParameter.subst(subs)->getCanonicalType();
25982534
if (reqt.Protocol) {
2599-
auto confIndex =
2600-
getProtocolConformanceIndex(signature, *IGM.getSwiftModule(),
2601-
reqt.TypeParameter, reqt.Protocol);
2602-
auto conformance = sub.getConformances()[confIndex];
2535+
auto conformance = *subs.lookupConformance(reqt.TypeParameter,
2536+
reqt.Protocol);
26032537
callback(reqtIndex, type, conformance);
26042538
} else {
26052539
callback(reqtIndex, type, None);
@@ -2608,7 +2542,7 @@ GenericTypeRequirements::enumerateFulfillments(IRGenModule &IGM,
26082542
}
26092543

26102544
void GenericTypeRequirements::emitInitOfBuffer(IRGenFunction &IGF,
2611-
ArrayRef<Substitution> subs,
2545+
const SubstitutionMap &subs,
26122546
Address buffer) {
26132547
if (Requirements.empty()) return;
26142548

@@ -2652,20 +2586,17 @@ irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
26522586
CanGenericSignature generics,
26532587
ModuleDecl &module,
26542588
GenericRequirement requirement,
2655-
ArrayRef<Substitution> subs) {
2589+
const SubstitutionMap &subs) {
26562590
CanType depTy = requirement.TypeParameter;
2657-
auto typeIndex = getDependentTypeIndex(generics, module, depTy);
2658-
const Substitution &sub = subs[typeIndex];
2659-
CanType argType = sub.getReplacement()->getCanonicalType();
2591+
CanType argType = depTy.subst(subs)->getCanonicalType();
26602592

26612593
if (!requirement.Protocol) {
26622594
auto argMetadata = IGF.emitTypeMetadataRef(argType);
26632595
return argMetadata;
26642596
}
26652597

26662598
auto proto = requirement.Protocol;
2667-
auto protoIndex = getProtocolConformanceIndex(generics, module, depTy, proto);
2668-
auto conformance = sub.getConformances()[protoIndex];
2599+
auto conformance = *subs.lookupConformance(depTy, proto);
26692600
assert(conformance.getRequirement() == proto);
26702601
llvm::Value *metadata = nullptr;
26712602
auto wtable = emitWitnessTableRef(IGF, argType, &metadata, conformance);

lib/IRGen/GenProto.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ namespace irgen {
136136
void emitPolymorphicArguments(IRGenFunction &IGF,
137137
CanSILFunctionType origType,
138138
CanSILFunctionType substType,
139-
ArrayRef<Substitution> subs,
139+
const SubstitutionMap &subs,
140140
WitnessMetadata *witnessMetadata,
141141
Explosion &args);
142142

lib/IRGen/GenericRequirement.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class CanGenericSignature;
3333
class ModuleDecl;
3434
class NominalTypeDecl;
3535
class ProtocolDecl;
36-
class Substitution;
36+
class SubstitutionMap;
3737

3838
namespace irgen {
3939
class Address;
@@ -54,7 +54,7 @@ emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
5454
CanGenericSignature signature,
5555
ModuleDecl &module,
5656
GenericRequirement requirement,
57-
ArrayRef<Substitution> subs);
57+
const SubstitutionMap &subs);
5858

5959
using EmitGenericRequirementFn =
6060
llvm::function_ref<llvm::Value*(GenericRequirement reqt)>;
@@ -141,10 +141,10 @@ class GenericTypeRequirements {
141141
llvm::function_ref<void(unsigned requirementIndex,
142142
CanType type,
143143
Optional<ProtocolConformanceRef> conf)>;
144-
void enumerateFulfillments(IRGenModule &IGM, ArrayRef<Substitution> subs,
144+
void enumerateFulfillments(IRGenModule &IGM, const SubstitutionMap &subs,
145145
FulfillmentCallback callback);
146146

147-
void emitInitOfBuffer(IRGenFunction &IGF, ArrayRef<Substitution> subs,
147+
void emitInitOfBuffer(IRGenFunction &IGF, const SubstitutionMap &subs,
148148
Address buffer);
149149

150150
void bindFromBuffer(IRGenFunction &IGF, Address buffer,

lib/IRGen/IRGenSIL.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2075,8 +2075,11 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {
20752075

20762076
// Pass the generic arguments.
20772077
if (hasPolymorphicParameters(origCalleeType)) {
2078+
SubstitutionMap subMap;
2079+
if (auto genericSig = origCalleeType->getGenericSignature())
2080+
subMap = genericSig->getSubstitutionMap(site.getSubstitutions());
20782081
emitPolymorphicArguments(*this, origCalleeType, substCalleeType,
2079-
site.getSubstitutions(), &witnessMetadata, llArgs);
2082+
subMap, &witnessMetadata, llArgs);
20802083
}
20812084

20822085
// Add all those arguments.

lib/IRGen/MetadataLayout.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ template <class Impl> class MetadataLayout {
6666
if (requirements.empty()) return;
6767

6868
auto subs = type->castTo<BoundGenericType>()
69-
->gatherAllSubstitutions(IGM.getSwiftModule(), nullptr);
69+
->getContextSubstitutionMap(IGM.getSwiftModule(),
70+
typeDecl);
7071
requirements.enumerateFulfillments(IGM, subs,
7172
[&](unsigned reqtIndex, CanType argType,
7273
Optional<ProtocolConformanceRef> conf) {

lib/IRGen/NecessaryBindings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class NecessaryBindings {
4949
static NecessaryBindings forFunctionInvocations(IRGenModule &IGM,
5050
CanSILFunctionType origType,
5151
CanSILFunctionType substType,
52-
ArrayRef<Substitution> subs);
52+
const SubstitutionMap &subs);
5353

5454
/// Add whatever information is necessary to reconstruct type metadata
5555
/// for the given type.

0 commit comments

Comments
 (0)