Skip to content

Commit 857489c

Browse files
committed
When a generic type has dependent IR and thus requires each
specialization to be separately lowered in IRGen, use the mangling of the specialized type as the name of the llvm::StructType instead of the base, unspecialized type. This tends to produce fewer collisions between IR type names. LLVM does unique the names on its own, so that's not strictly necessary, but it's still a good idea because it makes the test output more reliable and somewhat easier to read (modulo the impact of bigger type names). Collisions will still occur if the type is specialized at an archetype, since in this case we will fall back on the unspecialized type.
1 parent 8f820de commit 857489c

15 files changed

+41
-32
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,8 +1846,8 @@ llvm::Constant *irgen::emitObjCProtocolData(IRGenModule &IGM,
18461846
}
18471847

18481848
const TypeInfo *
1849-
TypeConverter::convertClassType(ClassDecl *D) {
1850-
llvm::StructType *ST = IGM.createNominalType(D);
1849+
TypeConverter::convertClassType(CanType type, ClassDecl *D) {
1850+
llvm::StructType *ST = IGM.createNominalType(type);
18511851
llvm::PointerType *irType = ST->getPointerTo();
18521852
ReferenceCounting refcount = ::getReferenceCountingForClass(IGM, D);
18531853

lib/IRGen/GenEnum.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5446,7 +5446,7 @@ const TypeInfo *TypeConverter::convertEnumType(TypeBase *key, CanType type,
54465446
if (IGM.isResilient(theEnum, ResilienceExpansion::Maximal))
54475447
storageType = cast<llvm::StructType>(IGM.OpaquePtrTy->getElementType());
54485448
else
5449-
storageType = IGM.createNominalType(theEnum);
5449+
storageType = IGM.createNominalType(type);
54505450

54515451
// Create a forward declaration for that type.
54525452
addForwardDecl(key, storageType);

lib/IRGen/GenExistential.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,8 +1298,7 @@ static const TypeInfo *createErrorExistentialTypeInfo(IRGenModule &IGM,
12981298
refcounting);
12991299
}
13001300

1301-
static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM,
1302-
TypeBase *T,
1301+
static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM, CanType T,
13031302
ArrayRef<ProtocolDecl*> protocols) {
13041303
SmallVector<llvm::Type*, 5> fields;
13051304
SmallVector<ProtocolEntry, 4> entries;
@@ -1318,11 +1317,11 @@ static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM,
13181317
}
13191318

13201319
llvm::StructType *type;
1321-
if (auto *protoT = T->getAs<ProtocolType>())
1322-
type = IGM.createNominalType(protoT->getDecl());
1323-
else if (auto *compT = T->getAs<ProtocolCompositionType>())
1320+
if (isa<ProtocolType>(T))
1321+
type = IGM.createNominalType(T);
1322+
else if (auto compT = dyn_cast<ProtocolCompositionType>(T))
13241323
// Protocol composition types are not nominal, but we name them anyway.
1325-
type = IGM.createNominalType(compT);
1324+
type = IGM.createNominalType(compT.getPointer());
13261325
else
13271326
llvm_unreachable("unknown existential type kind");
13281327

@@ -1415,7 +1414,7 @@ static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM,
14151414

14161415
const TypeInfo *TypeConverter::convertProtocolType(ProtocolType *T) {
14171416
// Protocol types are nominal.
1418-
return createExistentialTypeInfo(IGM, T, T->getDecl());
1417+
return createExistentialTypeInfo(IGM, CanType(T), T->getDecl());
14191418
}
14201419

14211420
const TypeInfo *
@@ -1424,7 +1423,7 @@ TypeConverter::convertProtocolCompositionType(ProtocolCompositionType *T) {
14241423
SmallVector<ProtocolDecl*, 4> protocols;
14251424
T->getAnyExistentialTypeProtocols(protocols);
14261425

1427-
return createExistentialTypeInfo(IGM, T, protocols);
1426+
return createExistentialTypeInfo(IGM, CanType(T), protocols);
14281427
}
14291428

14301429
const TypeInfo *

lib/IRGen/GenStruct.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ const TypeInfo *TypeConverter::convertStructType(TypeBase *key, CanType type,
842842
return &getResilientStructTypeInfo();
843843

844844
// Create the struct type.
845-
auto ty = IGM.createNominalType(D);
845+
auto ty = IGM.createNominalType(type);
846846

847847
// Register a forward declaration before we look at any of the child types.
848848
addForwardDecl(key, ty);

lib/IRGen/GenType.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,7 @@ TypeCacheEntry TypeConverter::convertAnyNominalType(CanType type,
15331533
llvm_unreachable("protocol types shouldn't be handled here");
15341534

15351535
case DeclKind::Class:
1536-
return convertClassType(cast<ClassDecl>(decl));
1536+
return convertClassType(type, cast<ClassDecl>(decl));
15371537
case DeclKind::Enum:
15381538
return convertEnumType(type.getPointer(), type, cast<EnumDecl>(decl));
15391539
case DeclKind::Struct:
@@ -1618,9 +1618,17 @@ TypeConverter::getMetatypeTypeInfo(MetatypeRepresentation representation) {
16181618
}
16191619

16201620
/// createNominalType - Create a new nominal type.
1621-
llvm::StructType *IRGenModule::createNominalType(TypeDecl *decl) {
1621+
llvm::StructType *IRGenModule::createNominalType(CanType type) {
1622+
assert(type.getNominalOrBoundGenericNominal());
1623+
1624+
// We share type infos for different instantiations of a generic type
1625+
// when the archetypes have the same exemplars. Mangling the archetypes
1626+
// in this case can be very misleading, so we just mangle the base name.
1627+
if (type->hasArchetype())
1628+
type = type.getNominalOrBoundGenericNominal()->getDeclaredType()
1629+
->getCanonicalType();
1630+
16221631
llvm::SmallString<32> typeName;
1623-
auto type = decl->getDeclaredType()->getCanonicalType();
16241632
LinkEntity::forTypeMangling(type).mangle(typeName);
16251633
return llvm::StructType::create(getLLVMContext(), typeName.str());
16261634
}

lib/IRGen/GenType.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class TypeConverter {
117117
TypeCacheEntry convertType(CanType T);
118118
TypeCacheEntry convertAnyNominalType(CanType T, NominalTypeDecl *D);
119119
const TypeInfo *convertTupleType(TupleType *T);
120-
const TypeInfo *convertClassType(ClassDecl *D);
120+
const TypeInfo *convertClassType(CanType type, ClassDecl *D);
121121
const TypeInfo *convertEnumType(TypeBase *key, CanType type, EnumDecl *D);
122122
const TypeInfo *convertStructType(TypeBase *key, CanType type, StructDecl *D);
123123
const TypeInfo *convertFunctionType(SILFunctionType *T);

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ class IRGenModule {
564564
llvm::PointerType *getStoragePointerTypeForUnlowered(Type T);
565565
llvm::PointerType *getStoragePointerTypeForLowered(CanType T);
566566
llvm::PointerType *getStoragePointerType(SILType T);
567-
llvm::StructType *createNominalType(TypeDecl *D);
567+
llvm::StructType *createNominalType(CanType type);
568568
llvm::StructType *createNominalType(ProtocolCompositionType *T);
569569
void getSchema(SILType T, ExplosionSchema &schema);
570570
ExplosionSchema getSchema(SILType T);

test/IRGen/class.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ entry(%x : $ClassConstrainedGenericField<ClassConstraintConformance>):
163163
%b = load %a : $*ClassConstraintConformance
164164
return %b : $ClassConstraintConformance
165165
}
166-
// CHECK-LABEL: define{{( protected)?}} %C5class26ClassConstraintConformance* @fixed_class_generic_field(%C5class28ClassConstrainedGenericField*)
167-
// CHECK: [[FIELD_ADDR_GENERIC:%.*]] = getelementptr inbounds %C5class28ClassConstrainedGenericField, %C5class28ClassConstrainedGenericField* %0, i32 0, i32 1
166+
// CHECK-LABEL: define{{( protected)?}} %C5class26ClassConstraintConformance* @fixed_class_generic_field(%GC5class28ClassConstrainedGenericFieldCS_26ClassConstraintConformance_*)
167+
// CHECK: [[FIELD_ADDR_GENERIC:%.*]] = getelementptr inbounds %GC5class28ClassConstrainedGenericFieldCS_26ClassConstraintConformance_, %GC5class28ClassConstrainedGenericFieldCS_26ClassConstraintConformance_* %0, i32 0, i32 1
168168
// CHECK: load %C5class26ClassConstraintConformance*, %C5class26ClassConstraintConformance** [[FIELD_ADDR_GENERIC]]
169169

test/IRGen/enum.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ import Swift
8989
// -- Dynamic enums. The type layout is opaque; we dynamically bitcast to
9090
// the element type.
9191
// CHECK: %O4enum20DynamicSinglePayload = type <{}>
92-
// CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%O4enum20DynamicSinglePayload\.[0-9]+]] = type <{ [1 x i8] }>
92+
// CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%GO4enum20DynamicSinglePayloadT__]] = type <{ [1 x i8] }>
9393

9494
// -- Address-only multi-payload enums. We can't use spare bits.
9595
// CHECK-64: %O4enum32MultiPayloadAddressOnlySpareBits = type <{ [16 x i8], [1 x i8] }>
@@ -2495,7 +2495,7 @@ struct StructWithWeakVar {
24952495
weak var delegate: delegateProtocol?
24962496
}
24972497

2498-
// CHECK-64-LABEL: define{{( protected)?}} void @weak_optional(%Sq{{.*}}* noalias nocapture dereferenceable({{.*}}))
2498+
// CHECK-64-LABEL: define{{( protected)?}} void @weak_optional(%GSqV4enum17StructWithWeakVar_* noalias nocapture dereferenceable({{.*}}))
24992499
sil @weak_optional : $@convention(thin) (@in StructWithWeakVar?) -> () {
25002500
entry(%x : $*StructWithWeakVar?):
25012501
// CHECK-64: icmp eq [[WORD]] {{%.*}}, 0

test/IRGen/enum_spare_bits.sil

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ enum Archetype<T: AnyObject> {
4848
case A(T), B(C)
4949
}
5050
// can't use spare bits—archetype may be bound to tagged pointer type
51-
// CHECK-32: [[ARCHETYPE:%O15enum_spare_bits9Archetype.*]] = type <{ [4 x i8], [1 x i8] }>
52-
// CHECK-64: [[ARCHETYPE:%O15enum_spare_bits9Archetype.*]] = type <{ [8 x i8], [1 x i8] }>
51+
// CHECK-32: [[ARCHETYPE:%GO15enum_spare_bits9ArchetypeCS_1C_]] = type <{ [4 x i8], [1 x i8] }>
52+
// CHECK-32: [[ARCHETYPE_OBJC:%GO15enum_spare_bits9ArchetypeCSo8NSObject_]] = type <{ [4 x i8], [1 x i8] }>
53+
// CHECK-64: [[ARCHETYPE:%GO15enum_spare_bits9ArchetypeCS_1C_]] = type <{ [8 x i8], [1 x i8] }>
54+
// CHECK-64: [[ARCHETYPE_OBJC:%GO15enum_spare_bits9ArchetypeCSo8NSObject_]] = type <{ [8 x i8], [1 x i8] }>
5355

5456
sil_global @swiftClass: $SwiftClass
5557
sil_global @objcClass: $ObjCClass
@@ -59,7 +61,7 @@ sil_global @archetypeBoundToSwift: $Archetype<C>
5961
sil_global @archetypeBoundToObjC: $Archetype<NSObject>
6062

6163
// CHECK: @archetypeBoundToSwift = {{(protected )?}}global [[ARCHETYPE]]
62-
// CHECK: @archetypeBoundToObjC = {{(protected )?}}global [[ARCHETYPE]]
64+
// CHECK: @archetypeBoundToObjC = {{(protected )?}}global [[ARCHETYPE_OBJC]]
6365

6466
sil @instantiate_globals : $() -> () {
6567
entry:

0 commit comments

Comments
 (0)