// RUN: %target-swift-frontend %s -emit-ir | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime // REQUIRES: CPU=x86_64 import Builtin import Swift // CHECK: [[ROOTGENERIC:%C15generic_classes11RootGeneric]] = type <{ %swift.refcounted, %Vs5UInt8 }> // -- offset of RootGeneric.x // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[ROOTGENERIC_NAME:@.*]] = private constant [32 x i8] c"C15generic_classes11RootGeneric\00" // CHECK: [[ROOTGENERIC_FIELDS:@.*]] = private constant [7 x i8] c"x\00y\00z\00\00" // CHECK: @_TMnC15generic_classes11RootGeneric = {{(protected )?}}constant <{ {{.*}} i32 }> <{ // -- name // CHECK: [32 x i8]* [[ROOTGENERIC_NAME]] // -- num fields // CHECK: i32 3, // -- field offset vector offset // CHECK: i32 15, // -- field names // CHECK: [7 x i8]* [[ROOTGENERIC_FIELDS]] // -- generic metadata pattern // CHECK: @_TMPC15generic_classes11RootGeneric // -- generic parameter vector offset // CHECK: i32 10, // -- generic parameter count, primary count, witness table counts // CHECK: i32 1, i32 1, i32 0 // CHECK: } // CHECK: @_TMPC15generic_classes11RootGeneric = {{(protected )?}}global // -- template fill function // CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_RootGeneric // -- nominal type descriptor // CHECK: @_TMnC15generic_classes11RootGeneric // -- vtable // CHECK: @_TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_, // CHECK: @_TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_, // CHECK: @_TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_, // -- field offset placeholders // CHECK: i64 16, i64 0, i64 0 // CHECK: }> // -- Check that offset vars are emitted for fixed-layout generics // // CHECK: @_TWvdvC15generic_classes22RootGenericFixedLayout1xVs5UInt8 = {{(protected )?}}constant i64 16, align 8 // CHECK: @_TWvdvC15generic_classes22RootGenericFixedLayout1yGSax_ = {{(protected )?}}constant i64 24, align 8 // CHECK: @_TWvdvC15generic_classes22RootGenericFixedLayout1zVs5UInt8 = {{(protected )?}}constant i64 32, align 8 // -- fixed-layout nongeneric descriptor // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[ROOTNONGENERIC_NAME:@.*]] = private constant [35 x i8] c"C15generic_classes14RootNonGeneric\00" // CHECK: @_TMnC15generic_classes14RootNonGeneric = {{(protected )?}}constant <{ {{.*}} i32 }> <{ // -- name // CHECK: [35 x i8]* [[ROOTNONGENERIC_NAME]] // -- num fields // CHECK: i32 3, // -- -- field offset vector offset // CHECK: i32 11, // -- field names // CHECK: [7 x i8]* [[ROOTGENERIC_FIELDS]] // -- no generic metadata pattern, kind 0 // CHECK: i32 0, // -- 0 = no generic parameter vector // CHECK: i32 0, // -- number of generic params, primary params // CHECK: i32 0, i32 0 // CHECK: }> // CHECK: @_TMfC15generic_classes14RootNonGeneric = internal global <{ {{.*}} }> <{ // CHECK: void (%C15generic_classes14RootNonGeneric*)* @_TFC15generic_classes14RootNonGenericD, // CHECK: i8** @_TWVBo, // CHECK-native: i64 0, // CHECK-native: %swift.type* null, // CHECK-native: %swift.opaque* null, // CHECK-objc: i64 ptrtoint (%objc_class* @_TMmC15generic_classes14RootNonGeneric to i64), // CHECK-objc: %objc_class* @"OBJC_CLASS_$_SwiftObject", // CHECK-objc: %swift.opaque* @_objc_empty_cache, // CHECK: %swift.opaque* null, // CHECK-native: i64 1, // CHECK-objc: @_DATA__TtC15generic_classes14RootNonGeneric // CHECK: i32 33, // CHECK: i16 7, // CHECK: i16 0, // CHECK: {{.*}}* @_TMnC15generic_classes14RootNonGeneric // CHECK: }> // CHECK: @_TMPC15generic_classes22GenericInheritsGeneric = {{(protected )?}}global // -- template fill function // CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_GenericInheritsGeneric // -- RootGeneric vtable // CHECK: @_TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_, // CHECK: @_TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_, // CHECK: @_TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_, // -- RootGeneric field offset placeholders // CHECK: i64 16, i64 0, i64 0 // -- GenericInheritsGeneric vtable // CHECK: @_TFC15generic_classes22GenericInheritsGeneric7zippityU___fGS0_Q_Q0__FT_T_, // CHECK: @_TFC15generic_classes22GenericInheritsGeneric3dooU___fGS0_Q_Q0__FT_T_, // CHECK: @_TFC15generic_classes22GenericInheritsGeneric3dahU___fGS0_Q_Q0__FT_T_, // -- GenericInheritsGeneric field offset placeholder // CHECK: i64 0 // CHECK: } // CHECK: @_TMPC15generic_classes25GenericInheritsNonGeneric class RootGeneric { var x : UInt8 init() // Test that declaration order doesn't cause the field offset vector to end // up interleaved with the vtable. func foo() var y : T func bar() var z : UInt8 func bas() } sil @_TFC15generic_classes11RootGenericD : $@convention(method) (RootGeneric) -> () sil @_TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_ : $@convention(method) (@guaranteed RootGeneric) -> () sil @_TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_ : $@convention(method) (@guaranteed RootGeneric) -> () sil @_TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_ : $@convention(method) (@guaranteed RootGeneric) -> () sil_vtable RootGeneric { #RootGeneric.foo!1: _TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_ #RootGeneric.bar!1: _TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_ #RootGeneric.bas!1: _TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_ } class RootGenericFixedLayout { var x : UInt8 var y : [T] var z : UInt8 init() } sil_vtable RootGenericFixedLayout {} sil @_TFC15generic_classes22RootGenericFixedLayoutD : $@convention(method) (RootGenericFixedLayout) -> () class RootNonGeneric { var x : UInt8 var y : Int var z : UInt8 init() } sil_vtable RootNonGeneric {} sil @_TFC15generic_classes14RootNonGenericD : $@convention(method) (RootNonGeneric) -> () class GenericInheritsGeneric : RootGeneric { var w : B func zippity() func doo() func dah() override init() } sil @_TFC15generic_classes22GenericInheritsGenericD : $@convention(method) (GenericInheritsGeneric) -> () sil @_TFC15generic_classes22GenericInheritsGeneric7zippityU___fGS0_Q_Q0__FT_T_ : $@convention(method) (@guaranteed GenericInheritsGeneric) -> () sil @_TFC15generic_classes22GenericInheritsGeneric3dooU___fGS0_Q_Q0__FT_T_ : $@convention(method) (@guaranteed GenericInheritsGeneric) -> () sil @_TFC15generic_classes22GenericInheritsGeneric3dahU___fGS0_Q_Q0__FT_T_ : $@convention(method) (@guaranteed GenericInheritsGeneric) -> () sil_vtable GenericInheritsGeneric { #RootGeneric.foo!1: _TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_ #RootGeneric.bar!1: _TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_ #RootGeneric.bas!1: _TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_ #GenericInheritsGeneric.zippity!1: _TFC15generic_classes22GenericInheritsGeneric7zippityU___fGS0_Q_Q0__FT_T_ #GenericInheritsGeneric.doo!1: _TFC15generic_classes22GenericInheritsGeneric3dooU___fGS0_Q_Q0__FT_T_ #GenericInheritsGeneric.dah!1: _TFC15generic_classes22GenericInheritsGeneric3dahU___fGS0_Q_Q0__FT_T_ } class GenericInheritsNonGeneric : RootNonGeneric { var w : UInt8 override init() } sil_vtable GenericInheritsNonGeneric {} sil @_TFC15generic_classes25GenericInheritsNonGenericD : $@convention(method) (GenericInheritsNonGeneric) -> () // rdar://18067671 class RecursiveGenericInheritsGeneric : RootGeneric { var w : B var r : RecursiveGenericInheritsGeneric? func zippity() func doo() func dah() override init() } sil_vtable RecursiveGenericInheritsGeneric {} sil @_TFC15generic_classes31RecursiveGenericInheritsGenericD : $@convention(method) (RecursiveGenericInheritsGeneric) -> () // CHECK: define{{( protected)?}} [[ROOTGENERIC]]* @RootGeneric_fragile_dependent_alloc // CHECK: [[METADATA:%.*]] = call %swift.type* @_TMaC15generic_classes11RootGeneric // CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8* // CHECK: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 48 // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i32* // CHECK: [[SIZE32:%.*]] = load i32, i32* [[T1]], align 8 // CHECK: [[SIZE:%.*]] = zext i32 [[SIZE32]] to i64 // CHECK: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 52 // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i32* // CHECK: [[ALIGN32:%.*]] = load i32, i32* [[T1]], align 4 // CHECK: [[ALIGN:%.*]] = zext i32 [[ALIGN32]] to i64 // CHECK: call noalias %swift.refcounted* @rt_swift_allocObject(%swift.type* [[METADATA]], i64 [[SIZE]], i64 [[ALIGN]]) sil @RootGeneric_fragile_dependent_alloc : $ () -> RootGeneric { entry: %x = alloc_ref $RootGeneric return %x : $RootGeneric } // RootGeneric.x has fixed layout // CHECK: define{{( protected)?}} i8 @RootGeneric_concrete_fragile_dependent_member_access_x // CHECK: getelementptr inbounds [[ROOTGENERIC]], [[ROOTGENERIC]]* %0, i32 0, i32 1 sil @RootGeneric_concrete_fragile_dependent_member_access_x : $ RootGeneric -> UInt8 { entry(%c : $RootGeneric): %p = ref_element_addr %c : $RootGeneric, #RootGeneric.x %x = load %p : $*UInt8 return %x : $UInt8 } // RootGeneric.y has dependent layout; load the offset from the metadata // CHECK-LABEL: define{{( protected)?}} void @RootGeneric_concrete_fragile_dependent_member_access_y // CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[Y_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 16 // CHECK: [[Y_OFFSET:%.*]] = load i64, i64* [[Y_OFFSET_ADDR]], align 8 // CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8* // CHECK: [[Y_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Y_OFFSET]] // CHECK: bitcast i8* [[Y_ADDR]] to %swift.opaque* sil @RootGeneric_concrete_fragile_dependent_member_access_y : $ (RootGeneric) -> @out F { entry(%z : $*F, %c : $RootGeneric): %p = ref_element_addr %c : $RootGeneric, #RootGeneric.y copy_addr %p to [initialization] %z : $*F %t = tuple () return %t : $() } // CHECK-LABEL: define{{( protected)?}} void @RootGeneric_subst_concrete_fragile_dependent_member_access_y // CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[Y_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 16 // CHECK: [[Y_OFFSET:%.*]] = load i64, i64* [[Y_OFFSET_ADDR]], align 8 // CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8* // CHECK: [[Y_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Y_OFFSET]] // CHECK: bitcast i8* [[Y_ADDR]] to %Si* sil @RootGeneric_subst_concrete_fragile_dependent_member_access_y : $(RootGeneric) -> @out Int { entry(%z : $*Int, %c : $RootGeneric): %p = ref_element_addr %c : $RootGeneric, #RootGeneric.y copy_addr %p to [initialization] %z : $*Int %t = tuple () return %t : $() } // RootGeneric.z has dependent layout; load the offset from the metadata // CHECK-LABEL: define{{( protected)?}} i8 @RootGeneric_concrete_fragile_dependent_member_access_z // CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[Z_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 17 // CHECK: [[Z_OFFSET:%.*]] = load i64, i64* [[Z_OFFSET_ADDR]], align 8 // CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8* // CHECK: [[Z_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Z_OFFSET]] // CHECK: bitcast i8* [[Z_ADDR]] to %Vs5UInt8* sil @RootGeneric_concrete_fragile_dependent_member_access_z : $ RootGeneric -> UInt8 { entry(%c : $RootGeneric): %p = ref_element_addr %c : $RootGeneric, #RootGeneric.z %z = load %p : $*UInt8 return %z : $UInt8 } // CHECK-LABEL: define{{( protected)?}} i8 @RootGeneric_subst_concrete_fragile_dependent_member_access_z // CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64* // CHECK: [[Z_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 17 // CHECK: [[Z_OFFSET:%.*]] = load i64, i64* [[Z_OFFSET_ADDR]], align 8 // CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8* // CHECK: [[Z_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Z_OFFSET]] // CHECK: bitcast i8* [[Z_ADDR]] to %Vs5UInt8* sil @RootGeneric_subst_concrete_fragile_dependent_member_access_z : $RootGeneric -> UInt8 { entry(%c : $RootGeneric): %p = ref_element_addr %c : $RootGeneric, #RootGeneric.z %z = load %p : $*UInt8 return %z : $UInt8 } /* TODO: Instantiate types for fragile generic instances so we can do * fixed-layout access sil @RootGeneric_concrete_fragile_fixed_member_access : $RootGeneric -> (UInt8, Int32, UInt8) { entry(%c : $RootGeneric): %p = ref_element_addr %c : $RootGeneric, #RootGeneric.x %x = load %p : $*UInt8 %q = ref_element_addr %c : $RootGeneric, #RootGeneric.y %y = load %q : $*Int32 %r = ref_element_addr %c : $RootGeneric, #RootGeneric.z %z = load %r : $*UInt8 %t = tuple (%x : $UInt8, %y : $Int32, %z : $UInt8) return %t : $(UInt8, Int32, UInt8) } */ // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_RootGeneric(%swift.type_pattern*, i8**) {{.*}} { // -- initialize the dependent field offsets // CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i64* {{%.*}}, i64* {{%.*}}) // CHECK: } // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_RootGenericFixedLayout(%swift.type_pattern*, i8**) {{.*}} { // CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i64* {{%.*}}, i64* {{%.*}}) // CHECK: } // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_GenericInheritsGeneric(%swift.type_pattern*, i8**) {{.*}} { // Bind the generic parameters. // CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type** // CHECK: %A = load %swift.type*, %swift.type** [[T0]] // CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1 // CHECK: %B = load %swift.type*, %swift.type** [[T1]] // Construct the superclass. // CHECK: [[SUPER:%.*]] = call %swift.type* @_TMaC15generic_classes11RootGeneric(%swift.type* %A) // CHECK: [[T0:%.*]] = bitcast %swift.type* [[SUPER]] to %objc_class* // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[T0]]) // CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8** // Put the generic arguments in their correct positions. // CHECK: [[T0:%.*]] = bitcast %swift.type* %A to i8* // CHECK: [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 18 // CHECK: store i8* [[T0]], i8** [[A_ADDR]], align 8 // CHECK: [[T0:%.*]] = bitcast %swift.type* %B to i8* // CHECK: [[B_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 19 // CHECK: store i8* [[T0]], i8** [[B_ADDR]], align 8 // Set up the isa. // CHECK-objc: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8** // CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 0 // CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to %objc_class** // CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 25 // CHECK-objc: [[METACLASS:%.*]] = bitcast i8** [[T0]] to %objc_class* // CHECK-objc: store %objc_class* [[METACLASS]], %objc_class** [[T1]], align 8 // Set up the instance rodata pointer. // CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4 // CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to i64* // CHECK-objc: [[RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 30 // CHECK-objc: [[T2:%.*]] = ptrtoint i8** [[RODATA]] to i64 // CHECK-objc: [[T3:%.*]] = or i64 [[T2]], 1 // CHECK-objc: store i64 [[T3]], i64* [[T1]], align 8 // Set up the class rodata pointer. // CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 29 // CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to i64* // CHECK-objc: [[META_RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 39 // CHECK-objc: [[T2:%.*]] = ptrtoint i8** [[META_RODATA]] to i64 // CHECK-objc: store i64 [[T2]], i64* [[T1]], align 8 // Initialize our own dependent field offsets. // CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64* // CHECK: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i32 23 // CHECK: [[T0:%.*]] = bitcast %swift.type* %B to i8*** // CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1 // CHECK: [[VWT:%.*]] = load i8**, i8*** [[T1]], align 8 // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 17 // CHECK: [[T1:%.*]] = load i8*, i8** [[T0]], align 8 // CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to i64 // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 18 // CHECK: [[T1:%.*]] = load i8*, i8** [[T0]], align 8 // CHECK: [[T2:%.*]] = ptrtoint i8* [[T1]] to i64 // CHECK: [[ALIGN:%.*]] = and i64 [[T2]], 65535 // CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[TYPES:%.*]], i32 0, i32 0 // CHECK: store i64 [[SIZE]], i64* [[SIZE_ADDR]], align 8 // CHECK: [[ALIGN_ADDR:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[TYPES]], i32 0, i32 1 // CHECK: store i64 [[ALIGN]], i64* [[ALIGN_ADDR]], align 8 // CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 1, i64* [[SIZE_ADDR]], i64* [[OFFSETS]]) // CHECK: ret %swift.type* [[METADATA]] // CHECK: }