Skip to content

Commit 4062987

Browse files
committed
[IRGen] Replace examplar archetypes with canonicalized archetypes.
Rather than profiling and building exemplar archetypes, map the archetypes into the canonical generic environment for that generic signature. This doesn't provide exactly the same level of re-use as exemplars, but such re-use isn't critical and this avoids infinite recursion when working with recursive protocol constraints.
1 parent ea90fa6 commit 4062987

File tree

4 files changed

+31
-194
lines changed

4 files changed

+31
-194
lines changed

lib/IRGen/GenType.cpp

Lines changed: 30 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -943,181 +943,27 @@ const TypeInfo *TypeConverter::tryGetCompleteTypeInfo(CanType T) {
943943
return &ti;
944944
}
945945

946-
/// Profile the archetype constraints that may affect type layout into a
947-
/// folding set node ID.
948-
static void profileArchetypeConstraints(
949-
Type ty,
950-
llvm::FoldingSetNodeID &ID,
951-
llvm::DenseMap<ArchetypeType*, unsigned> &seen) {
952-
// Helper.
953-
class ProfileType : public CanTypeVisitor<ProfileType> {
954-
llvm::FoldingSetNodeID &ID;
955-
llvm::DenseMap<ArchetypeType *, unsigned> &seen;
956-
957-
public:
958-
ProfileType(llvm::FoldingSetNodeID &ID,
959-
llvm::DenseMap<ArchetypeType *, unsigned> &seen)
960-
: ID(ID), seen(seen) {}
961-
962-
#define TYPE_WITHOUT_ARCHETYPE(KIND) \
963-
void visit##KIND##Type(Can##KIND##Type type) { \
964-
llvm_unreachable("does not contain an archetype"); \
965-
}
966-
967-
TYPE_WITHOUT_ARCHETYPE(Builtin)
968-
969-
void visitNominalType(CanNominalType type) {
970-
if (type.getParent())
971-
profileArchetypeConstraints(type.getParent(), ID, seen);
972-
ID.AddPointer(type->getDecl());
973-
}
974-
975-
void visitTupleType(CanTupleType type) {
976-
ID.AddInteger(type->getNumElements());
977-
for (auto &elt : type->getElements()) {
978-
ID.AddInteger(elt.isVararg());
979-
profileArchetypeConstraints(elt.getType(), ID, seen);
980-
}
981-
}
982-
983-
void visitReferenceStorageType(CanReferenceStorageType type) {
984-
profileArchetypeConstraints(type.getReferentType(), ID, seen);
985-
}
986-
987-
void visitAnyMetatypeType(CanAnyMetatypeType type) {
988-
profileArchetypeConstraints(type.getInstanceType(), ID, seen);
989-
}
990-
991-
TYPE_WITHOUT_ARCHETYPE(Module)
992-
993-
void visitDynamicSelfType(CanDynamicSelfType type) {
994-
profileArchetypeConstraints(type.getSelfType(), ID, seen);
995-
}
996-
997-
void visitArchetypeType(CanArchetypeType type) {
998-
profileArchetypeConstraints(type, ID, seen);
999-
}
1000-
1001-
TYPE_WITHOUT_ARCHETYPE(GenericTypeParam)
1002-
1003-
void visitDependentMemberType(CanDependentMemberType type) {
1004-
ID.AddPointer(type->getAssocType());
1005-
profileArchetypeConstraints(type.getBase(), ID, seen);
1006-
}
1007-
1008-
void visitAnyFunctionType(CanAnyFunctionType type) {
1009-
ID.AddInteger(type->getExtInfo().getFuncAttrKey());
1010-
profileArchetypeConstraints(type.getInput(), ID, seen);
1011-
profileArchetypeConstraints(type.getResult(), ID, seen);
1012-
}
1013-
1014-
TYPE_WITHOUT_ARCHETYPE(SILFunction)
1015-
TYPE_WITHOUT_ARCHETYPE(SILBlockStorage)
1016-
TYPE_WITHOUT_ARCHETYPE(SILBox)
1017-
TYPE_WITHOUT_ARCHETYPE(ProtocolComposition)
1018-
1019-
void visitLValueType(CanLValueType type) {
1020-
profileArchetypeConstraints(type.getObjectType(), ID, seen);
1021-
}
1022-
1023-
void visitInOutType(CanInOutType type) {
1024-
profileArchetypeConstraints(type.getObjectType(), ID, seen);
1025-
}
1026-
1027-
TYPE_WITHOUT_ARCHETYPE(UnboundGeneric)
1028-
1029-
void visitBoundGenericType(CanBoundGenericType type) {
1030-
if (type.getParent())
1031-
profileArchetypeConstraints(type.getParent(), ID, seen);
1032-
ID.AddPointer(type->getDecl());
1033-
for (auto arg : type.getGenericArgs()) {
1034-
profileArchetypeConstraints(arg, ID, seen);
1035-
}
1036-
}
1037-
#undef TYPE_WITHOUT_ARCHETYPE
1038-
};
1039-
1040-
// End recursion if we found a concrete associated type.
1041-
auto arch = ty->getAs<ArchetypeType>();
1042-
if (!arch) {
1043-
auto concreteTy = ty->getCanonicalType();
1044-
if (!concreteTy->hasArchetype()) {
1045-
// Trivial case: if there are no archetypes, just use the canonical type
1046-
// pointer.
1047-
ID.AddBoolean(true);
1048-
ID.AddPointer(concreteTy.getPointer());
1049-
return;
1050-
}
1051-
1052-
// When there are archetypes, recurse to profile the type itself.
1053-
ID.AddInteger(1);
1054-
ID.AddInteger(static_cast<unsigned>(concreteTy->getKind()));
1055-
1056-
ProfileType(ID, seen).visit(concreteTy);
1057-
return;
1058-
}
1059-
1060-
auto found = seen.find(arch);
1061-
if (found != seen.end()) {
1062-
ID.AddInteger(found->second);
1063-
return;
1064-
}
1065-
seen.insert({arch, seen.size()});
1066-
1067-
// Is the archetype class-constrained?
1068-
ID.AddBoolean(arch->requiresClass());
1069-
1070-
// The archetype's superclass constraint.
1071-
auto superclass = arch->getSuperclass();
1072-
if (superclass) {
1073-
ProfileType(ID, seen).visit(superclass->getCanonicalType());
1074-
} else {
1075-
ID.AddPointer(nullptr);
1076-
}
1077-
1078-
// The archetype's protocol constraints.
1079-
for (auto proto : arch->getConformsTo()) {
1080-
ID.AddPointer(proto);
1081-
}
946+
ArchetypeType *TypeConverter::getExemplarArchetype(ArchetypeType *t) {
947+
// Retrieve the generic environment of the archetype.
948+
auto genericEnv = t->getGenericEnvironment();
1082949

1083-
// Skip nested types if this is an opened existential, since those
1084-
// won't resolve. Normally opened existentials cannot have nested
1085-
// types, but one case we missed compiled in Swift 3 so we support
1086-
// it here.
1087-
if (arch->getOpenedExistentialType()) {
1088-
return;
1089-
}
950+
// If there is no generic environment, the archetype is an exemplar.
951+
if (!genericEnv) return t;
1090952

1091-
// Recursively profile nested archetypes.
1092-
for (auto nested : arch->getAllNestedTypes()) {
1093-
profileArchetypeConstraints(nested.second, ID, seen);
1094-
}
1095-
}
953+
// Dig out the canonical generic environment.
954+
auto genericSig = genericEnv->getGenericSignature();
955+
auto canGenericSig = genericSig->getCanonicalSignature();
956+
auto module = IGM.getSwiftModule();
957+
auto canGenericEnv = canGenericSig.getGenericEnvironment(*module);
958+
if (canGenericEnv == genericEnv) return t;
1096959

1097-
void ExemplarArchetype::Profile(llvm::FoldingSetNodeID &ID) const {
1098-
llvm::DenseMap<ArchetypeType*, unsigned> seen;
1099-
profileArchetypeConstraints(Archetype, ID, seen);
1100-
}
1101-
1102-
ArchetypeType *TypeConverter::getExemplarArchetype(ArchetypeType *t) {
1103-
// Check the folding set to see whether we already have an exemplar matching
1104-
// this archetype.
1105-
llvm::FoldingSetNodeID ID;
1106-
llvm::DenseMap<ArchetypeType*, unsigned> seen;
1107-
profileArchetypeConstraints(t, ID, seen);
1108-
void *insertPos;
1109-
ExemplarArchetype *existing
1110-
= Types.ExemplarArchetypes.FindNodeOrInsertPos(ID, insertPos);
1111-
if (existing) {
1112-
return existing->Archetype;
1113-
}
1114-
1115-
// Otherwise, use this archetype as the exemplar for future similar
1116-
// archetypes.
1117-
Types.ExemplarArchetypeStorage.push_back(new ExemplarArchetype(t));
1118-
Types.ExemplarArchetypes.InsertNode(&Types.ExemplarArchetypeStorage.back(),
1119-
insertPos);
1120-
return t;
960+
// Map the archetype out of its own generic environment and into the
961+
// canonical generic environment.
962+
auto interfaceType = genericEnv->mapTypeOutOfContext(t);
963+
auto exemplar = canGenericEnv->mapTypeIntoContext(module, interfaceType)
964+
->castTo<ArchetypeType>();
965+
assert(isExemplarArchetype(exemplar));
966+
return exemplar;
1121967
}
1122968

1123969
/// Fold archetypes to unique exemplars. Any archetype with the same
@@ -1858,9 +1704,18 @@ CanType TypeConverter::getTypeThatLoweredTo(llvm::Type *t) const {
18581704
}
18591705

18601706
bool TypeConverter::isExemplarArchetype(ArchetypeType *arch) const {
1861-
for (auto &ea : Types.ExemplarArchetypeStorage)
1862-
if (ea.Archetype == arch) return true;
1863-
return false;
1707+
auto genericEnv = arch->getGenericEnvironment();
1708+
if (!genericEnv) return true;
1709+
1710+
// Dig out the canonical generic environment.
1711+
auto genericSig = genericEnv->getGenericSignature();
1712+
auto canGenericSig = genericSig->getCanonicalSignature();
1713+
auto module = IGM.getSwiftModule();
1714+
auto canGenericEnv = canGenericSig.getGenericEnvironment(*module);
1715+
1716+
// If this archetype is in the canonical generic environment, it's an
1717+
// exemplar archetype.
1718+
return canGenericEnv == genericEnv;
18641719
}
18651720
#endif
18661721

lib/IRGen/GenType.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,6 @@ namespace irgen {
6161
/// Either a type or a forward-declaration.
6262
typedef llvm::PointerUnion<const TypeInfo*, llvm::Type*> TypeCacheEntry;
6363

64-
/// A unique archetype arbitrarily chosen as an exemplar for all archetypes with
65-
/// the same constraints.
66-
class ExemplarArchetype : public llvm::FoldingSetNode,
67-
public llvm::ilist_node<ExemplarArchetype> {
68-
public:
69-
ArchetypeType * const Archetype;
70-
71-
ExemplarArchetype() : Archetype(nullptr) {}
72-
ExemplarArchetype(ArchetypeType *t) : Archetype(t) {}
73-
74-
void Profile(llvm::FoldingSetNodeID &ID) const;
75-
};
76-
7764
/// The helper class for generating types.
7865
class TypeConverter {
7966
public:
@@ -195,9 +182,6 @@ class TypeConverter {
195182
llvm::DenseMap<TypeBase*, TypeCacheEntry> DependentCache;
196183
llvm::DenseMap<TypeBase*, TypeCacheEntry> &getCacheFor(TypeBase *t);
197184

198-
llvm::ilist<ExemplarArchetype> ExemplarArchetypeStorage;
199-
llvm::FoldingSet<ExemplarArchetype> ExemplarArchetypes;
200-
201185
friend TypeCacheEntry TypeConverter::getTypeEntry(CanType T);
202186
friend TypeCacheEntry TypeConverter::convertAnyNominalType(CanType Type,
203187
NominalTypeDecl *D);

test/DebugInfo/generic_arg2.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests %s -emit-ir -g -o - | %FileCheck %s
22

33
// CHECK: define hidden void @_T012generic_arg25ClassC3foo{{.*}}, %swift.type* %U
4-
// CHECK: [[Y:%.*]] = getelementptr inbounds %C12generic_arg25Class, %C12generic_arg25Class* %2, i32 0, i32 0, i32 0
5-
// store %swift.opaque* %[[Y]], %swift.opaque** %[[Y_SHADOW:.*]], align
64
// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %y.addr, metadata ![[U:.*]], metadata !{{[0-9]+}})
75
// Make sure there is no conflicting dbg.value for this variable.x
86
// CHECK-NOT: dbg.value{{.*}}metadata ![[U]]

test/IRGen/sil_witness_methods.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ entry(%z : $*Z, %x : $*Foo):
8585
return %m : $@thick Foo.Type
8686
}
8787

88-
// CHECK-LABEL: define{{( protected)?}} %swift.type* @generic_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %C19sil_witness_methods3Bar** noalias nocapture dereferenceable({{.*}}), %swift.type* %Self, i8** %SelfWitnessTable)
88+
// CHECK-LABEL: define{{( protected)?}} %swift.type* @generic_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %C19sil_witness_methods3Bar{{(.1)?}}** noalias nocapture dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable)
8989
sil @generic_type_generic_method_witness : $@convention(witness_method) <T, U, V, Z> (@in Z, @in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type {
9090
entry(%z : $*Z, %x : $*Bar<T, U, V>):
9191
%t = metatype $@thick T.Type

0 commit comments

Comments
 (0)