Skip to content

Commit 57ceb50

Browse files
Merge pull request swiftlang#63733 from nate-chandler/variadic-generics/irgen/open_pack_element_requirements
[IRGen] Bound all requirements of open_pack_element.
2 parents dbd7258 + 8eb3058 commit 57ceb50

File tree

6 files changed

+303
-37
lines changed

6 files changed

+303
-37
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
200200
void forEachPackElementArchetype(
201201
llvm::function_ref<void(ElementArchetypeType*)> function) const;
202202

203+
void forEachPackElementGenericTypeParam(
204+
llvm::function_ref<void(GenericTypeParamType *)> function) const;
205+
203206
using PackElementBindingCallback =
204207
llvm::function_ref<void(ElementArchetypeType *elementType,
205208
PackType *packSubstitution)>;

lib/AST/GenericEnvironment.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,12 @@ void GenericEnvironment::forEachPackElementArchetype(
141141
}
142142
}
143143

144-
void GenericEnvironment::forEachPackElementBinding(
145-
PackElementBindingCallback function) const {
144+
void GenericEnvironment::forEachPackElementGenericTypeParam(
145+
llvm::function_ref<void(GenericTypeParamType *)> function) const {
146146
auto sig = getGenericSignature();
147147
auto shapeClass = getOpenedElementShapeClass();
148148
auto packElements = sig.getInnermostGenericParams();
149149
auto packElementDepth = packElements.front()->getDepth();
150-
auto elementIt = packElements.begin();
151150

152151
// Each parameter pack in the outer generic parameters has
153152
// a corresponding pack element parameter at the innermost
@@ -164,13 +163,23 @@ void GenericEnvironment::forEachPackElementBinding(
164163
if (!sig->haveSameShape(genericParam, shapeClass->mapTypeOutOfContext()))
165164
continue;
166165

166+
function(genericParam);
167+
}
168+
}
169+
170+
void GenericEnvironment::forEachPackElementBinding(
171+
PackElementBindingCallback function) const {
172+
auto sig = getGenericSignature();
173+
auto packElements = sig.getInnermostGenericParams();
174+
auto elementIt = packElements.begin();
175+
forEachPackElementGenericTypeParam([&](auto *genericParam) {
167176
assert(elementIt != packElements.end());
168177
auto *elementArchetype =
169178
mapTypeIntoContext(*elementIt++)->castTo<ElementArchetypeType>();
170-
auto *packSubstitution =
171-
maybeApplyOuterContextSubstitutions(genericParam)->castTo<PackType>();
179+
auto *packSubstitution = maybeApplyOuterContextSubstitutions(genericParam)
180+
->template castTo<PackType>();
172181
function(elementArchetype, packSubstitution);
173-
}
182+
});
174183

175184
assert(elementIt == packElements.end());
176185
}

lib/IRGen/GenPack.cpp

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,13 @@ static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF,
262262
}
263263

264264
struct OpenedElementContext {
265-
GenericEnvironment *packEnvironment;
266-
CanGenericSignature packSignature;
267-
268-
GenericEnvironment *elementEnvironment;
269-
CanGenericSignature elementSignature;
265+
GenericEnvironment *environment;
266+
CanGenericSignature signature;
270267

271268
static OpenedElementContext
272269
createForPackExpansion(IRGenFunction &IGF, CanPackExpansionType expansionTy) {
273270
// Get the outer generic signature and environment.
274-
auto *genericEnv = cast<PackArchetypeType>(expansionTy.getCountType())
271+
auto *genericEnv = cast<ArchetypeType>(expansionTy.getCountType())
275272
->getGenericEnvironment();
276273
auto subMap = genericEnv->getForwardingSubstitutionMap();
277274

@@ -282,15 +279,15 @@ struct OpenedElementContext {
282279
auto *elementEnv = GenericEnvironment::forOpenedElement(
283280
elementSig, UUID::fromTime(), expansionTy.getCountType(), subMap);
284281

285-
return {genericEnv, genericSig, elementEnv, elementSig};
282+
return {elementEnv, elementSig};
286283
}
287284
};
288285

289286
static void bindElementSignatureRequirementsAtIndex(
290287
IRGenFunction &IGF, OpenedElementContext const &context, llvm::Value *index,
291288
DynamicMetadataRequest request) {
292289
enumerateGenericSignatureRequirements(
293-
context.elementSignature, [&](GenericRequirement requirement) {
290+
context.signature, [&](GenericRequirement requirement) {
294291
switch (requirement.getKind()) {
295292
case GenericRequirement::Kind::Shape:
296293
case GenericRequirement::Kind::Metadata:
@@ -299,12 +296,12 @@ static void bindElementSignatureRequirementsAtIndex(
299296
case GenericRequirement::Kind::MetadataPack: {
300297
auto ty = requirement.getTypeParameter();
301298
auto patternPackArchetype = cast<PackArchetypeType>(
302-
context.packEnvironment->mapTypeIntoContext(ty)
299+
context.environment->maybeApplyOuterContextSubstitutions(ty)
303300
->getCanonicalType());
304301
auto response =
305302
IGF.emitTypeMetadataRef(patternPackArchetype, request);
306303
auto elementArchetype =
307-
context.elementEnvironment
304+
context.environment
308305
->mapPackTypeIntoElementContext(
309306
patternPackArchetype->getInterfaceType())
310307
->getCanonicalType();
@@ -319,20 +316,20 @@ static void bindElementSignatureRequirementsAtIndex(
319316
auto ty = requirement.getTypeParameter();
320317
auto proto = requirement.getProtocol();
321318
auto patternPackArchetype = cast<PackArchetypeType>(
322-
context.packEnvironment->mapTypeIntoContext(ty)
319+
context.environment->maybeApplyOuterContextSubstitutions(ty)
323320
->getCanonicalType());
324321
auto elementArchetype =
325-
context.elementEnvironment
322+
context.environment
326323
->mapPackTypeIntoElementContext(
327324
patternPackArchetype->getInterfaceType())
328325
->getCanonicalType();
329326
llvm::Value *_metadata = nullptr;
330327
auto packConformance =
331-
context.packSignature->lookupConformance(ty, proto);
328+
context.signature->lookupConformance(ty, proto);
332329
auto *wtablePack = emitWitnessTableRef(IGF, patternPackArchetype,
333330
&_metadata, packConformance);
334331
auto elementConformance =
335-
context.elementSignature->lookupConformance(ty, proto);
332+
context.signature->lookupConformance(ty, proto);
336333
auto *wtable = bindWitnessTableAtIndex(
337334
IGF, elementArchetype, elementConformance, wtablePack, index);
338335
assert(wtable);
@@ -350,7 +347,7 @@ static llvm::Value *emitPackExpansionElementMetadata(
350347

351348
// Replace pack archetypes with element archetypes in the pattern type.
352349
auto instantiatedPatternTy =
353-
context.elementEnvironment
350+
context.environment
354351
->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext())
355352
->getCanonicalType();
356353

@@ -526,11 +523,11 @@ static llvm::Value *emitPackExpansionElementWitnessTable(
526523

527524
// Replace pack archetypes with element archetypes in the pattern type.
528525
auto instantiatedPatternTy =
529-
context.elementEnvironment
526+
context.environment
530527
->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext())
531528
->getCanonicalType();
532529
auto instantiatedConformance =
533-
context.elementEnvironment->getGenericSignature()->lookupConformance(
530+
context.environment->getGenericSignature()->lookupConformance(
534531
instantiatedPatternTy, conformance.getRequirement());
535532

536533
// Emit the element witness table.
@@ -646,7 +643,7 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
646643
ArrayRef<ProtocolDecl *> protocols, llvm::Value *index,
647644
DynamicMetadataRequest request,
648645
llvm::SmallVectorImpl<llvm::Value *> &wtables) {
649-
// If the packs have already been materialized, just gep into it.
646+
// If the packs have already been materialized, just gep into them.
650647
auto materializedMetadataPack =
651648
tryGetLocalPackTypeMetadata(IGF, packType, request);
652649
llvm::SmallVector<llvm::Value *> materializedWtablePacks;
@@ -692,9 +689,8 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
692689
auto response = IGF.emitTypeMetadataRef(ty, request);
693690
auto *metadata = response.getMetadata();
694691
for (auto protocol : protocols) {
695-
llvm::Value *_metadata = nullptr;
696692
auto *wtable =
697-
emitWitnessTableRef(IGF, ty, /*srcMetadataCache=*/&_metadata,
693+
emitWitnessTableRef(IGF, ty, /*srcMetadataCache=*/&metadata,
698694
ProtocolConformanceRef(protocol));
699695
wtables.push_back(wtable);
700696
}
@@ -918,6 +914,71 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
918914
return metadataPhi;
919915
}
920916

917+
void irgen::bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
918+
GenericEnvironment *environment,
919+
llvm::Value *index) {
920+
assert(environment->getKind() == GenericEnvironment::Kind::OpenedElement);
921+
922+
// Record the generic type parameters of interest.
923+
llvm::SmallPtrSet<CanType, 2> openablePackParams;
924+
environment->forEachPackElementGenericTypeParam([&](auto *genericParam) {
925+
openablePackParams.insert(genericParam->getCanonicalType());
926+
});
927+
928+
// Find the archetypes and conformances which must be bound.
929+
llvm::SmallSetVector<CanType, 2> types;
930+
llvm::DenseMap<CanType, llvm::SmallVector<ProtocolDecl *, 2>>
931+
protocolsForType;
932+
auto isDerivedFromPackElementGenericTypeParam = [&](CanType ty) -> bool {
933+
// Is this type itself an openable pack parameter OR a dependent type of
934+
// one?
935+
return openablePackParams.contains(
936+
ty->getRootGenericParam()->getCanonicalType());
937+
};
938+
enumerateGenericSignatureRequirements(
939+
environment->getGenericSignature().getCanonicalSignature(),
940+
[&](GenericRequirement requirement) {
941+
switch (requirement.getKind()) {
942+
case GenericRequirement::Kind::MetadataPack: {
943+
auto ty = requirement.getTypeParameter();
944+
if (!isDerivedFromPackElementGenericTypeParam(ty))
945+
return;
946+
types.insert(ty);
947+
protocolsForType.insert({ty, {}});
948+
break;
949+
}
950+
case GenericRequirement::Kind::WitnessTablePack: {
951+
auto ty = requirement.getTypeParameter();
952+
if (!isDerivedFromPackElementGenericTypeParam(ty))
953+
return;
954+
types.insert(ty);
955+
auto iterator = protocolsForType.insert({ty, {}}).first;
956+
iterator->getSecond().push_back(requirement.getProtocol());
957+
break;
958+
}
959+
case GenericRequirement::Kind::Shape:
960+
case GenericRequirement::Kind::Metadata:
961+
case GenericRequirement::Kind::WitnessTable:
962+
break;
963+
}
964+
});
965+
966+
// For each archetype to be bound, find the corresponding conformances and
967+
// bind the metadata and wtables.
968+
for (auto ty : types) {
969+
auto protocols = protocolsForType.find(ty)->getSecond();
970+
auto archetype = cast<ElementArchetypeType>(
971+
environment->mapPackTypeIntoElementContext(ty)->getCanonicalType());
972+
auto pack =
973+
cast<PackType>(environment->maybeApplyOuterContextSubstitutions(ty)
974+
->getCanonicalType());
975+
llvm::SmallVector<llvm::Value *, 2> wtables;
976+
auto *metadata = emitTypeMetadataPackElementRef(
977+
IGF, pack, protocols, index, MetadataState::Complete, wtables);
978+
IGF.bindArchetype(archetype, metadata, MetadataState::Complete, wtables);
979+
}
980+
}
981+
921982
void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF,
922983
StackAddress pack,
923984
Optional<unsigned> elementCount) {

lib/IRGen/GenPack.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ emitTypeMetadataPackRef(IRGenFunction &IGF,
5353
CanPackType packType,
5454
DynamicMetadataRequest request);
5555

56+
void bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
57+
GenericEnvironment *env,
58+
llvm::Value *index);
59+
5660
llvm::Value *
5761
emitTypeMetadataPackElementRef(IRGenFunction &IGF, CanPackType packType,
5862
ArrayRef<ProtocolDecl *> protocols,

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6902,17 +6902,8 @@ void IRGenSILFunction::visitScalarPackIndexInst(ScalarPackIndexInst *i) {
69026902
void IRGenSILFunction::visitOpenPackElementInst(swift::OpenPackElementInst *i) {
69036903
llvm::Value *index = getLoweredSingletonExplosion(i->getIndexOperand());
69046904

6905-
i->getOpenedGenericEnvironment()->forEachPackElementBinding(
6906-
[&](auto *archetype, auto *pack) {
6907-
auto protocols = archetype->getConformsTo();
6908-
llvm::SmallVector<llvm::Value *, 2> wtables;
6909-
auto *metadata = emitTypeMetadataPackElementRef(
6910-
*this, CanPackType(pack), protocols, index, MetadataState::Complete,
6911-
wtables);
6912-
bindArchetype(CanElementArchetypeType(archetype), metadata,
6913-
MetadataState::Complete, wtables);
6914-
});
6915-
6905+
auto *env = i->getOpenedGenericEnvironment();
6906+
bindOpenedElementArchetypesAtIndex(*this, env, index);
69166907
// The result is just used for type dependencies.
69176908
}
69186909

0 commit comments

Comments
 (0)