Skip to content

Commit 6378efe

Browse files
committed
[IRGen] Bound all reqs of open_pack_element.
Previously, only the element archetypes that corresponded to the relevant pack generic parameters were bound, and the wtables that were bound for them were based on looking up what they conform to. Here, the requirements of the generic signature are used to find which archetypes must be bound to metadata and which conformances must be bound to wtables.
1 parent 502bbd0 commit 6378efe

File tree

4 files changed

+269
-11
lines changed

4 files changed

+269
-11
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,71 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
915915
return metadataPhi;
916916
}
917917

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

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

test/IRGen/run_variadic_generics.sil

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ sil public_external @printGenericTypeAndWord : $@convention(thin) <T> (@thick T.
2323
protocol P {
2424
static func static_member_fn()
2525
}
26+
protocol PA {
27+
associatedtype A
28+
}
2629

2730
struct A : P {
2831
static func static_member_fn()
@@ -49,6 +52,13 @@ struct G : P {
4952
struct GenFwdP<T : P> : P {
5053
static func static_member_fn()
5154
}
55+
struct GenAssocPA<T> : PA {
56+
typealias A = T
57+
}
58+
59+
sil_witness_table <T : P> GenAssocPA<T>: PA module main {
60+
associated_type A : T
61+
}
5262

5363
sil private @A_static_member_fn : $@convention(witness_method: P) (@thick A.Type) -> () {
5464
bb0(%0 : $@thick A.Type):
@@ -385,6 +395,143 @@ bb0(%argc : $Int32, %argv : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<
385395
apply %wrap_in_GenFwdP<Pack{A, B, C, D, E, F}>(%5) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
386396

387397

398+
/// Expect the following:
399+
/// GenAssocPA<GenFwdP<INNER>> // from extract_associatedtype_with_conformance's call to printGenericType
400+
/// GenFwdP<INNER> // from GenFwdP_static_member_fn's call to printGenericType
401+
/// INNER // from INNER::static_member_fn's call to printGenericTypeAndWord
402+
/// INNER.INDEX // from INNER::static_member_fn's call to printGenericTypeAndWord
403+
%extract_associatedtype_with_conformance = function_ref @extract_associatedtype_with_conformance : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
404+
// U_1 -> {A, B, C, D, E, F}
405+
// --0---> ^
406+
// CHECK: GenAssocPA<GenFwdP<A>>
407+
// CHECK: GenFwdP<A>
408+
// CHECK: A
409+
// CHECK: 0
410+
apply %extract_associatedtype_with_conformance<Pack{A, B, C, D, E, F}>(%0) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
411+
// U_1 -> {A, B, C, D, E, F}
412+
// ----1----> ^
413+
// CHECK: GenAssocPA<GenFwdP<B>>
414+
// CHECK: GenFwdP<B>
415+
// CHECK: B
416+
// CHECK: 1
417+
apply %extract_associatedtype_with_conformance<Pack{A, B, C, D, E, F}>(%1) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
418+
// U_1 -> {A, B, C, D, E, F}
419+
// -----2------> ^
420+
// CHECK: GenAssocPA<GenFwdP<C>>
421+
// CHECK: GenFwdP<C>
422+
// CHECK: C
423+
// CHECK: 2
424+
apply %extract_associatedtype_with_conformance<Pack{A, B, C, D, E, F}>(%2) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
425+
// U_1 -> {A, B, C, D, E, F}
426+
// -------3-------> ^
427+
// CHECK: GenAssocPA<GenFwdP<D>>
428+
// CHECK: GenFwdP<D>
429+
// CHECK: D
430+
// CHECK: 3
431+
apply %extract_associatedtype_with_conformance<Pack{A, B, C, D, E, F}>(%3) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
432+
// U_1 -> {A, B, C, D, E, F}
433+
// --------4---------> ^
434+
// CHECK: GenAssocPA<GenFwdP<E>>
435+
// CHECK: GenFwdP<E>
436+
// CHECK: E
437+
// CHECK: 4
438+
apply %extract_associatedtype_with_conformance<Pack{A, B, C, D, E, F}>(%4) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
439+
// U_1 -> {A, B, C, D, E, F}
440+
// ----------5----------> ^
441+
// CHECK: GenAssocPA<GenFwdP<F>>
442+
// CHECK: GenFwdP<F>
443+
// CHECK: F
444+
// CHECK: 5
445+
apply %extract_associatedtype_with_conformance<Pack{A, B, C, D, E, F}>(%5) : $@convention(thin) <T_1... : P> (Builtin.Word) -> ()
446+
447+
448+
/// Expect the following:
449+
/// GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<INNER>>>> // from extract_associatedtype_with_conformance2's call to printGenericType
450+
/// GenFwdP<INNER> // from GenFwdP_static_member_fn's call to printGenericType
451+
/// INNER // from INNER::static_member_fn's call to printGenericTypeAndWord
452+
/// INNER.INDEX // from INNER::static_member_fn's call to printGenericTypeAndWord
453+
/// It occurs for both U_1 and U_2.
454+
%extract_associatedtype_with_conformance2 = function_ref @extract_associatedtype_with_conformance2 : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
455+
// U_1 -> {A, B, C, A, B, C}
456+
// --0---> ^
457+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<A>>>>
458+
// CHECK: GenFwdP<A>
459+
// CHECK: A
460+
// CHECK: 0
461+
// U_2 -> {E, F, G, E, F, G}
462+
// --0---> ^
463+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<E>>>>
464+
// CHECK: GenFwdP<E>
465+
// CHECK: E
466+
// CHECK: 4
467+
apply %extract_associatedtype_with_conformance2<Pack{A, B, C}, D, Pack{E, F, G}>(%0) : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
468+
// U_1 -> {A, B, C, A, B, C}
469+
// ----1----> ^
470+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<B>>>>
471+
// CHECK: GenFwdP<B>
472+
// CHECK: B
473+
// CHECK: 1
474+
// U_2 -> {E, F, G, E, F, G}
475+
// ----1----> ^
476+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<F>>>>
477+
// CHECK: GenFwdP<F>
478+
// CHECK: F
479+
// CHECK: 5
480+
apply %extract_associatedtype_with_conformance2<Pack{A, B, C}, D, Pack{E, F, G}>(%1) : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
481+
// U_1 -> {A, B, C, A, B, C}
482+
// -----2------> ^
483+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<C>>>>
484+
// CHECK: GenFwdP<C>
485+
// CHECK: C
486+
// CHECK: 2
487+
// U_2 -> {E, F, G, E, F, G}
488+
// -----2------> ^
489+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<G>>>>
490+
// CHECK: GenFwdP<G>
491+
// CHECK: G
492+
// CHECK: 6
493+
apply %extract_associatedtype_with_conformance2<Pack{A, B, C}, D, Pack{E, F, G}>(%2) : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
494+
// U_1 -> {A, B, C, A, B, C}
495+
// -------3-------> ^
496+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<A>>>>
497+
// CHECK: GenFwdP<A>
498+
// CHECK: A
499+
// CHECK: 0
500+
// U_2 -> {E, F, G, E, F, G}
501+
// -------3-------> ^
502+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<E>>>>
503+
// CHECK: GenFwdP<E>
504+
// CHECK: E
505+
// CHECK: 4
506+
apply %extract_associatedtype_with_conformance2<Pack{A, B, C}, D, Pack{E, F, G}>(%3) : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
507+
// U_1 -> {A, B, C, A, B, C}
508+
// --------4---------> ^
509+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<B>>>>
510+
// CHECK: GenFwdP<B>
511+
// CHECK: B
512+
// CHECK: 1
513+
// U_2 -> {E, F, G, E, F, G}
514+
// --------4---------> ^
515+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<F>>>>
516+
// CHECK: GenFwdP<F>
517+
// CHECK: F
518+
// CHECK: 5
519+
apply %extract_associatedtype_with_conformance2<Pack{A, B, C}, D, Pack{E, F, G}>(%4) : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
520+
// U_1 -> {A, B, C, A, B, C}
521+
// ----------5----------> ^
522+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<C>>>>
523+
// CHECK: GenFwdP<C>
524+
// CHECK: C
525+
// CHECK: 2
526+
// U_2 -> {E, F, G, E, F, G}
527+
// ----------5----------> ^
528+
// CHECK: GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<G>>>>
529+
// CHECK: GenFwdP<G>
530+
// CHECK: G
531+
// CHECK: 6
532+
apply %extract_associatedtype_with_conformance2<Pack{A, B, C}, D, Pack{E, F, G}>(%5) : $@convention(thin) <T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> ()
533+
534+
388535
%outb = integer_literal $Builtin.Int32, 0
389536
%out = struct $Int32 (%outb : $Builtin.Int32)
390537
return %out : $Int32
@@ -471,3 +618,54 @@ entry(%intIndex : $Builtin.Word):
471618
%t = tuple ()
472619
return %t : $()
473620
}
621+
622+
sil @unwrap_from_PA : $<T_1... : PA where each T_1.A : P> (Builtin.Word) -> () {
623+
entry(%intIndex : $Builtin.Word):
624+
%direct_access_from_parameter_with_conformance = function_ref @direct_access_from_parameter_with_conformance : $@convention(thin) <T_1...: P> (Builtin.Word) -> ()
625+
apply %direct_access_from_parameter_with_conformance<Pack{repeat GenFwdP<each T_1.A>}>(%intIndex) : $@convention(thin) <T_1...: P> (Builtin.Word) -> ()
626+
%t = tuple ()
627+
return %t : $()
628+
}
629+
630+
sil @extract_associatedtype_with_conformance : $<T_1... : P> (Builtin.Word) -> () {
631+
entry(%intIndex : $Builtin.Word):
632+
%innerIndex = dynamic_pack_index %intIndex of $Pack{repeat each T_1}
633+
%token = open_pack_element %innerIndex of <U_1... : PA where each U_1.A : P> at <Pack{repeat GenAssocPA<GenFwdP<each T_1>>}>, shape $U_1, uuid "01234567-89AB-CDEF-0123-000000000005"
634+
%metatype_1 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1).Type
635+
%printGenericType = function_ref @printGenericType : $@convention(thin) <T> (@thick T.Type) -> ()
636+
apply %printGenericType<(@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1)>(%metatype_1) : $@convention(thin) <T> (@thick T.Type) -> ()
637+
%static_member_fn = witness_method $(@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1).A, #P.static_member_fn : <Self where Self : P> (Self.Type) -> () -> () : $@convention(witness_method: P) <T where T : P> (@thick T.Type) -> ()
638+
%metatype_2 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1).A.Type
639+
apply %static_member_fn<(@pack_element("01234567-89AB-CDEF-0123-000000000005") U_1).A>(%metatype_2) : $@convention(witness_method: P) <T where T : P> (@thick T.Type) -> ()
640+
%t = tuple ()
641+
return %t : $()
642+
}
643+
644+
// Nested associatedtypes.
645+
sil @extract_associatedtype_with_conformance2 : $<T_1... : P, Tee : P, T_2... : P where (repeat (each T_1, each T_2)) : Any> (Builtin.Word) -> () {
646+
entry(%intIndex : $Builtin.Word):
647+
%innerIndex = dynamic_pack_index %intIndex of $Pack{repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>, repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>}
648+
%token = open_pack_element %innerIndex
649+
of <U_1... : PA, Ewe : PA, U_2... : PA where each U_1.A : PA, each U_1.A.A : PA, each U_1.A.A.A : P, Ewe.A : PA, Ewe.A.A : PA, Ewe.A.A.A : P, each U_2.A : PA, each U_2.A.A : PA, each U_2.A.A.A : P, (repeat (each U_1, each U_2)): Any>
650+
at <
651+
Pack{repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>, repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_1>>>>},
652+
GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<Tee>>>>,
653+
Pack{repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_2>>>>, repeat GenAssocPA<GenAssocPA<GenAssocPA<GenFwdP<each T_2>>>>}>
654+
, shape $U_1
655+
, uuid "01234567-89AB-CDEF-0123-000000000004"
656+
%metatype_1 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1).Type
657+
%printGenericType = function_ref @printGenericType : $@convention(thin) <T> (@thick T.Type) -> ()
658+
apply %printGenericType<(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1)>(%metatype_1) : $@convention(thin) <T> (@thick T.Type) -> ()
659+
%static_member_fn_1 = witness_method $(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1).A.A.A, #P.static_member_fn : <Self where Self : P> (Self.Type) -> () -> () : $@convention(witness_method: P) <T where T : P> (@thick T.Type) -> ()
660+
%metatype_12 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1).A.A.A.Type
661+
apply %static_member_fn_1<(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1).A.A.A>(%metatype_12) : $@convention(witness_method: P) <T where T : P> (@thick T.Type) -> ()
662+
663+
%metatype_2 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000004") U_2).Type
664+
apply %printGenericType<(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_2)>(%metatype_2) : $@convention(thin) <T> (@thick T.Type) -> ()
665+
%static_member_fn_2 = witness_method $(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_2).A.A.A, #P.static_member_fn : <Self where Self : P> (Self.Type) -> () -> () : $@convention(witness_method: P) <T where T : P> (@thick T.Type) -> ()
666+
%metatype_22 = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000004") U_2).A.A.A.Type
667+
apply %static_member_fn_2<(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_2).A.A.A>(%metatype_22) : $@convention(witness_method: P) <T where T : P> (@thick T.Type) -> ()
668+
669+
%t = tuple ()
670+
return %t : $()
671+
}

0 commit comments

Comments
 (0)