Skip to content

Commit 0273167

Browse files
committed
Use the known type parameters to determine static offsets to stored
properties of classes with generic layouts. Previously we were falling back on accessing them via the field offset vector even when we knew everything about the type. As a minor benefit, this allows RemoteAST to also determine offsets for members of classes with generic layout. Half of the test changes are IR type-name uniquing; I'm going to explore mangling these with the full type where possible.
1 parent 929c78e commit 0273167

File tree

11 files changed

+154
-172
lines changed

11 files changed

+154
-172
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 129 additions & 111 deletions
Large diffs are not rendered by default.

lib/IRGen/GenType.cpp

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,30 +1173,6 @@ TypeCacheEntry TypeConverter::getTypeEntry(CanType canonicalTy) {
11731173
return convertedTI;
11741174
}
11751175

1176-
/// A convenience for grabbing the TypeInfo for a class declaration.
1177-
const TypeInfo &TypeConverter::getTypeInfo(ClassDecl *theClass) {
1178-
// This type doesn't really matter except for serving as a key.
1179-
CanType theType
1180-
= getExemplarType(theClass->getDeclaredType()->getCanonicalType());
1181-
1182-
// If we have generic parameters, use the bound-generics conversion
1183-
// routine. This does an extra level of caching based on the common
1184-
// class decl.
1185-
TypeCacheEntry entry;
1186-
if (theClass->getGenericParams()) {
1187-
entry = convertAnyNominalType(theType, theClass);
1188-
1189-
// Otherwise, just look up the declared type.
1190-
} else {
1191-
assert(isa<ClassType>(theType));
1192-
entry = getTypeEntry(theType);
1193-
}
1194-
1195-
// This will always yield a TypeInfo because forward-declarations
1196-
// are unnecessary when converting class types.
1197-
return *entry.get<const TypeInfo*>();
1198-
}
1199-
12001176
/// Return a TypeInfo the represents opaque storage for a loadable POD value
12011177
/// with the given storage size.
12021178
///
@@ -1495,10 +1471,15 @@ namespace {
14951471
return false;
14961472
}
14971473

1498-
// Classes do not need unique implementations.
1499-
bool visitClassType(CanClassType type) { return false; }
1474+
// Conservatively assume classes need unique implementations.
1475+
bool visitClassType(CanClassType type) {
1476+
return visitClassDecl(type->getDecl());
1477+
}
15001478
bool visitBoundGenericClassType(CanBoundGenericClassType type) {
1501-
return false;
1479+
return visitClassDecl(type->getDecl());
1480+
}
1481+
bool visitClassDecl(ClassDecl *theClass) {
1482+
return true;
15021483
}
15031484

15041485
// Reference storage types propagate the decision.
@@ -1522,8 +1503,8 @@ namespace {
15221503

15231504
static bool isIRTypeDependent(IRGenModule &IGM, NominalTypeDecl *decl) {
15241505
assert(!isa<ProtocolDecl>(decl));
1525-
if (isa<ClassDecl>(decl)) {
1526-
return false;
1506+
if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
1507+
return IsIRTypeDependent(IGM).visitClassDecl(classDecl);
15271508
} else if (auto structDecl = dyn_cast<StructDecl>(decl)) {
15281509
return IsIRTypeDependent(IGM).visitStructDecl(structDecl);
15291510
} else {
@@ -1587,12 +1568,8 @@ TypeCacheEntry TypeConverter::convertAnyNominalType(CanType type,
15871568
case DeclKind::Protocol:
15881569
llvm_unreachable("protocol types don't take generic parameters");
15891570

1590-
case DeclKind::Class: {
1591-
auto result = convertClassType(cast<ClassDecl>(decl));
1592-
assert(!Cache.count(key));
1593-
Cache.insert(std::make_pair(key, result));
1594-
return result;
1595-
}
1571+
case DeclKind::Class:
1572+
llvm_unreachable("classes are always considered dependent for now");
15961573

15971574
case DeclKind::Enum: {
15981575
auto type = CanType(decl->getDeclaredTypeInContext());

lib/IRGen/GenType.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ class TypeConverter {
145145
TypeCacheEntry getTypeEntry(CanType type);
146146
const TypeInfo &getCompleteTypeInfo(CanType type);
147147
const TypeInfo *tryGetCompleteTypeInfo(CanType type);
148-
const TypeInfo &getTypeInfo(ClassDecl *D);
149148
const LoadableTypeInfo &getNativeObjectTypeInfo();
150149
const LoadableTypeInfo &getUnknownObjectTypeInfo();
151150
const LoadableTypeInfo &getBridgeObjectTypeInfo();

lib/IRGen/StructLayout.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,9 +418,6 @@ struct ClassLayout {
418418
ArrayRef<VarDecl*> InheritedStoredProperties;
419419
/// Lazily-initialized array of all field access methods.
420420
ArrayRef<FieldAccess> AllFieldAccesses;
421-
/// Lazily-initialized metadata access method. See the comment in
422-
/// ClassLayoutBuilder.
423-
FieldAccess MetadataAccess;
424421
/// Does the class metadata require dynamic initialization.
425422
bool MetadataRequiresDynamicInitialization;
426423

test/IRGen/class.sil

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,5 @@ entry(%x : $ClassConstrainedGenericField<ClassConstraintConformance>):
165165
}
166166
// CHECK-LABEL: define{{( protected)?}} %C5class26ClassConstraintConformance* @fixed_class_generic_field(%C5class28ClassConstrainedGenericField*)
167167
// CHECK: [[FIELD_ADDR_GENERIC:%.*]] = getelementptr inbounds %C5class28ClassConstrainedGenericField, %C5class28ClassConstrainedGenericField* %0, i32 0, i32 1
168-
// CHECK: [[FIELD_ADDR_CONCRETE:%.*]] = bitcast %objc_object** [[FIELD_ADDR_GENERIC]] to %C5class26ClassConstraintConformance**
169-
// CHECK: load %C5class26ClassConstraintConformance*, %C5class26ClassConstraintConformance** [[FIELD_ADDR_CONCRETE]]
168+
// CHECK: load %C5class26ClassConstraintConformance*, %C5class26ClassConstraintConformance** [[FIELD_ADDR_GENERIC]]
170169

test/IRGen/fulfillment.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ bb0(%0 : $B<T, U>):
4747
return %3 : $()
4848
}
4949

50-
// CHECK-LABEL: define hidden void @test_23121786(%C11fulfillment1A*, %C11fulfillment1A*)
50+
// CHECK-LABEL: define hidden void @test_23121786(%C11fulfillment1A*, %C11fulfillment1A{{.*}}*)
5151
sil hidden @test_23121786 : $@convention(thin) <T> (@owned A<A<T>>, @owned A<T>) -> () {
5252
bb0(%0 : $A<A<T>>, %1 : $A<T>):
5353
%2 = tuple ()

test/IRGen/generic_classes.sil

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,8 @@ entry(%z : $*F, %c : $RootGeneric<F>):
248248
}
249249

250250
// CHECK-LABEL: define{{( protected)?}} void @RootGeneric_subst_concrete_fragile_dependent_member_access_y
251-
// CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64*
252-
// CHECK: [[Y_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 16
253-
// CHECK: [[Y_OFFSET:%.*]] = load i64, i64* [[Y_OFFSET_ADDR]], align 8
254-
// CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8*
255-
// CHECK: [[Y_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Y_OFFSET]]
256-
// CHECK: bitcast i8* [[Y_ADDR]] to %Si*
251+
// CHECK: [[Y_ADDR:%.*]] = getelementptr inbounds {{.*}}, {{.*}}* %1, i32 0, i32 3
252+
// CHECK: bitcast %Si* [[Y_ADDR]] to i8*
257253
sil @RootGeneric_subst_concrete_fragile_dependent_member_access_y : $(RootGeneric<Int>) -> @out Int {
258254
entry(%z : $*Int, %c : $RootGeneric<Int>):
259255
%p = ref_element_addr %c : $RootGeneric<Int>, #RootGeneric.y
@@ -278,12 +274,9 @@ entry(%c : $RootGeneric<F>):
278274
}
279275

280276
// CHECK-LABEL: define{{( protected)?}} i8 @RootGeneric_subst_concrete_fragile_dependent_member_access_z
281-
// CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64*
282-
// CHECK: [[Z_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 17
283-
// CHECK: [[Z_OFFSET:%.*]] = load i64, i64* [[Z_OFFSET_ADDR]], align 8
284-
// CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8*
285-
// CHECK: [[Z_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Z_OFFSET]]
286-
// CHECK: bitcast i8* [[Z_ADDR]] to %Vs5UInt8*
277+
// CHECK: [[Z_ADDR:%.*]] = getelementptr inbounds {{.*}}, {{.*}}* %0, i32 0, i32 4
278+
// CHECK: [[T0:%.*]] = getelementptr inbounds %Vs5UInt8, %Vs5UInt8* [[Z_ADDR]], i32 0, i32 0
279+
// CHECK: load i8, i8* [[T0]], align
287280
sil @RootGeneric_subst_concrete_fragile_dependent_member_access_z : $RootGeneric<Int> -> UInt8 {
288281
entry(%c : $RootGeneric<Int>):
289282
%p = ref_element_addr %c : $RootGeneric<Int>, #RootGeneric.z

test/IRGen/partial_apply_forwarder.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public class C : P {}
66
public class D<T : P> {}
77
class E {}
88

9-
// CHECK-LABEL: define internal %C23partial_apply_forwarder1D* @_TPA_unspecialized_uncurried(%swift.refcounted*
9+
// CHECK-LABEL: define internal %C23partial_apply_forwarder1D{{.*}}* @_TPA_unspecialized_uncurried(%swift.refcounted*
1010
// CHECK: [[TYPE:%.*]] = call %swift.type* @_TMaC23partial_apply_forwarder1C()
1111
// CHECK: [[CAST:%.*]] = bitcast %swift.refcounted* %0 to %C23partial_apply_forwarder1E*
1212
// CHECK: [[CALL:%.*]] = call %C23partial_apply_forwarder1D* @unspecialized_uncurried(%swift.type* [[TYPE]], i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_TWPC23partial_apply_forwarder1CS_1PS_, i32 0, i32 0), %C23partial_apply_forwarder1E* [[CAST]])

test/IRGen/sil_witness_methods.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ entry:
141141
// CHECK: [[LAYOUT:%.*]] = bitcast %swift.refcounted* [[CONTEXT]] to <{ %swift.refcounted, i8* }>*
142142
// CHECK: [[WTABLE:%.*]] = getelementptr inbounds <{ %swift.refcounted, i8* }>, <{ %swift.refcounted, i8* }>* [[LAYOUT]], i32 0, i32 1
143143
// CHECK: store i8* null, i8** [[WTABLE]]
144-
// CHECK: [[RESULT:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (%swift.type* (%C19sil_witness_methods3Bar**, %swift.refcounted*)* @_TPA_generic_type_concrete_method_witness to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CONTEXT]], 1
144+
// CHECK: [[RESULT:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (%swift.type* (%C19sil_witness_methods3Bar{{.*}}**, %swift.refcounted*)* @_TPA_generic_type_concrete_method_witness to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CONTEXT]], 1
145145
// CHECK: ret { i8*, %swift.refcounted* } [[RESULT]]
146146

147147
sil @partial_apply_concrete_witness : $() -> @callee_owned (@in Bar<Foo, Foo, Foo>) -> @thick Bar<Foo, Foo, Foo>.Type {

test/IRGen/subclass.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class G<T> : A {
5757
// Ensure that downcasts to generic types instantiate generic metadata instead
5858
// of trying to reference global metadata. <rdar://problem/14265663>
5959

60-
// CHECK: define hidden %C8subclass1G* @_TF8subclass9a_to_gintF{{.*}}(%C8subclass1A*) {{.*}} {
60+
// CHECK: define hidden %C8subclass1G{{.*}}* @_TF8subclass9a_to_gintF{{.*}}(%C8subclass1A*) {{.*}} {
6161
func a_to_gint(a: A) -> G<Int> {
6262
// CHECK: call %swift.type* @_TMaGC8subclass1GSi_()
6363
// CHECK: call i8* @swift_dynamicCastClassUnconditional

0 commit comments

Comments
 (0)