mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Don't emit placeholders for field offsets and vtable entries, since they were always null. Instead, calculate the final size of class metadata at runtime using the size of the superclass metadata and the number of immediate members, and only copy this prefix from the template to the instantiated metadata, zero-filling the rest. For this to work with non-generic resilient classes and non-generic subclasses of generic classes, we need a new runtime entry point to relocate non-generic class metadata, calculating its size at runtime using the same strategy.
151 lines
5.3 KiB
Swift
151 lines
5.3 KiB
Swift
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK
|
|
|
|
// REQUIRES: CPU=x86_64
|
|
|
|
public class Base {
|
|
public func m1() {}
|
|
public func m2() {}
|
|
}
|
|
|
|
public class Derived<T> : Base {
|
|
public override func m2() {}
|
|
public func m3() {}
|
|
}
|
|
|
|
public class Concrete : Derived<Int> {
|
|
public override func m3() {}
|
|
public func m4() {}
|
|
}
|
|
|
|
|
|
//// Nominal type descriptor for 'Base' does not have any method descriptors.
|
|
|
|
// CHECK-LABEL: @_T014generic_vtable4BaseCMn = {{(protected )?}}constant
|
|
// -- nesting depth
|
|
// CHECK-SAME: i16 1,
|
|
// -- flags: has vtable
|
|
// CHECK-SAME: i16 4,
|
|
// -- generic parameters at depth 0
|
|
// CHECK-SAME: i32 0,
|
|
// -- vtable offset
|
|
// CHECK-SAME: i32 10,
|
|
// -- vtable size
|
|
// CHECK-SAME: i32 3
|
|
// -- no method descriptors -- class is fully concrete
|
|
// CHECK-SAME: section "{{.*}}", align 8
|
|
|
|
//// Type metadata for 'Base' has a static vtable.
|
|
|
|
// CHECK-LABEL: @_T014generic_vtable4BaseCMf = internal global
|
|
// -- vtable entry for 'm1()'
|
|
// CHECK-SAME: void (%T14generic_vtable4BaseC*)* @_T014generic_vtable4BaseC2m1yyF
|
|
// -- vtable entry for 'm2()'
|
|
// CHECK-SAME: void (%T14generic_vtable4BaseC*)* @_T014generic_vtable4BaseC2m2yyF
|
|
// -- vtable entry for 'init()'
|
|
// CHECK-SAME: %T14generic_vtable4BaseC* (%T14generic_vtable4BaseC*)* @_T014generic_vtable4BaseCACycfc
|
|
// --
|
|
// CHECK-SAME: , align 8
|
|
|
|
|
|
//// Nominal type descriptor for 'Derived' has method descriptors.
|
|
|
|
// CHECK-LABEL: @_T014generic_vtable7DerivedCMn = {{(protected )?}}constant
|
|
// -- nesting depth
|
|
// CHECK-SAME: i16 1,
|
|
// -- flags: has vtable
|
|
// CHECK-SAME: i16 4,
|
|
// -- generic parameters at depth 0
|
|
// CHECK-SAME: i32 1,
|
|
// -- vtable offset
|
|
// CHECK-SAME: i32 14,
|
|
// -- vtable size
|
|
// CHECK-SAME: i32 1,
|
|
// -- vtable entry for m3()
|
|
// CHECK-SAME: void (%T14generic_vtable7DerivedC*)* @_T014generic_vtable7DerivedC2m3yyF
|
|
// --
|
|
// CHECK-SAME: section "{{.*}}", align 8
|
|
|
|
//// Type metadata pattern for 'Derived' has an empty vtable, filled in at
|
|
//// instantiation time.
|
|
|
|
// CHECK-LABEL: @_T014generic_vtable7DerivedCMP = internal global <{{.*}}> <{
|
|
// -- nominal type descriptor
|
|
// CHECK-SAME: @_T014generic_vtable7DerivedCMn,
|
|
// -- ivar destroyer
|
|
// CHECK-SAME: i8* null
|
|
// --
|
|
// CHECK-SAME: }>, align 8
|
|
|
|
|
|
//// Nominal type descriptor for 'Concrete' has method descriptors.
|
|
|
|
// CHECK-LABEL: @_T014generic_vtable8ConcreteCMn = {{(protected )?}}constant
|
|
// -- nesting depth
|
|
// CHECK-SAME: i16 1,
|
|
// -- flags: has vtable
|
|
// CHECK-SAME: i16 4,
|
|
// -- generic parameters at depth 0
|
|
// CHECK-SAME: i32 0,
|
|
// -- vtable offset
|
|
// CHECK-SAME: i32 15,
|
|
// -- vtable size
|
|
// CHECK-SAME: i32 1,
|
|
// -- vtable entry for m4()
|
|
// CHECK-SAME: void (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteC2m4yyF
|
|
// --
|
|
// CHECK-SAME: section "{{.*}}", align 8
|
|
|
|
//// Type metadata for 'Concrete' does not have any vtable entries; the vtable is
|
|
//// filled in at initialization time.
|
|
|
|
// CHECK-LABEL: @_T014generic_vtable8ConcreteCMf = internal global <{{.*}}> <{
|
|
// -- nominal type descriptor
|
|
// CHECK-SAME: @_T014generic_vtable8ConcreteCMn,
|
|
// -- ivar destroyer
|
|
// CHECK-SAME: i8* null
|
|
// --
|
|
// CHECK-SAME: }>, align 8
|
|
|
|
|
|
//// Metadata initialization function for 'Derived' copies superclass vtable
|
|
//// and installs overrides for 'm2()' and 'init()'.
|
|
|
|
// CHECK-LABEL: define private %swift.type* @create_generic_metadata_Derived(%swift.type_pattern*, i8**)
|
|
|
|
// - 2 immediate members:
|
|
// - type metadata for generic parameter T,
|
|
// - and vtable entry for 'm3()'
|
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, {{.*}}, i64 2)
|
|
|
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
|
|
|
|
// -- method override for 'm2()'
|
|
// CHECK: [[WORDS:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
|
// CHECK: [[VTABLE0:%.*]] = getelementptr inbounds i8*, i8** [[WORDS]], i32 11
|
|
// CHECK: store i8* bitcast (void (%T14generic_vtable7DerivedC*)* @_T014generic_vtable7DerivedC2m2yyF to i8*), i8** [[VTABLE0]], align 8
|
|
|
|
// -- method override for 'init()'
|
|
// CHECK: [[VTABLE1:%.*]] = getelementptr inbounds i8*, i8** [[WORDS]], i32 12
|
|
// CHECK: store i8* bitcast (%T14generic_vtable7DerivedC* (%T14generic_vtable7DerivedC*)* @_T014generic_vtable7DerivedCACyxGycfc to i8*), i8** [[VTABLE1]], align 8
|
|
|
|
// CHECK: ret %swift.type* [[METADATA]]
|
|
|
|
|
|
//// Metadata initialization function for 'Concrete' copies superclass vtable
|
|
//// and installs overrides for 'init()' and 'm3()'.
|
|
|
|
// CHECK-LABEL: define private void @initialize_metadata_Concrete(i8*)
|
|
// CHECK: [[SUPERCLASS:%.*]] = call %swift.type* @_T014generic_vtable7DerivedCySiGMa()
|
|
// CHECK: store %swift.type* [[SUPERCLASS]], %swift.type** getelementptr inbounds {{.*}} @_T014generic_vtable8ConcreteCMf
|
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, i64 96, i64 1)
|
|
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
|
|
|
|
// -- method override for 'init()'
|
|
// CHECK: store i8* bitcast (%T14generic_vtable8ConcreteC* (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteCACycfc to i8*), i8**
|
|
|
|
// -- method override for 'm3()'
|
|
// CHECK: store i8* bitcast (void (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteC2m3yyF to i8*), i8**
|
|
|
|
// CHECK: store atomic %swift.type* [[METADATA]], %swift.type** @_T014generic_vtable8ConcreteCML release, align 8
|
|
// CHECK: ret void
|