// RUN: %empty-directory(%t) // RUN: %{python} %utils/chex.py < %s > %t/generic_classes.sil // RUN: %target-swift-frontend %t/generic_classes.sil -emit-ir | %FileCheck %t/generic_classes.sil --check-prefix=CHECK --check-prefix=CHECK-%target-runtime -check-prefix CHECK-%target-import-type // RUN: %target-swift-frontend -Osize %t/generic_classes.sil -emit-ir | %FileCheck %t/generic_classes.sil --check-prefix=OSIZE // REQUIRES: CPU=x86_64 import Builtin import Swift // CHECK: [[ROOTGENERIC:%T15generic_classes11RootGenericC]] = type <{ %swift.refcounted, %Ts5UInt8V }> // -- offset of RootGeneric.x // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[ROOTGENERIC_NAME:@.*]] = private constant [12 x i8] c"RootGeneric\00" // CHECK-LABEL: @"$s15generic_classes11RootGenericCMn" = // -- flags: class, generic, unique, has vtable // CHECK-SAME: // -- name // CHECK-SAME: [12 x i8]* [[ROOTGENERIC_NAME]] // -- negative size in words // CHECK-SAME: i32 2, // -- positive size in words // CHECK-SAME: i32 18, // -- num immediate members // CHECK-SAME: i32 8, // -- num fields // CHECK-SAME: i32 3, // -- field offset vector offset // CHECK-SAME: i32 11, // -- template instantiation cache // CHECK-SAME: [16 x i8*]* @"$s15generic_classes11RootGenericCMI" // -- template instantiation pattern // CHECK-SAME: @"$s15generic_classes11RootGenericCMP" // -- generic parameters, requirements, key arguments, extra arguments // CHECK-SAME: i16 1, i16 0, i16 1, i16 0 // -- vtable offset // CHECK-SAME: i32 14, // -- vtable size // CHECK-SAME: i32 4 // CHECK-SAME: } // CHECK-LABEL: @"$s15generic_classes11RootGenericCMP" = internal constant // CHECK-SAME: <{ // -- template instantiation function // CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**, i8*)* @"$s15generic_classes11RootGenericCMi" // -- heap destructor // CHECK-SAME: @"$s15generic_classes11RootGenericCfD" // -- ivar destroyer // CHECK-SAME: i32 0, // -- flags // CHECK_SAME: i32 3, // -- immediate pattern size // CHECK-SAME: i16 0, // -- immediate pattern target offset // CHECK-SAME: i16 0, // -- extra data size // CHECK-SAME-native: i16 0, // CHECK-SAME-objc: i16 23, // -- class ro-data offset // CHECK-SAME-native: i16 0, // CHECK-SAME-objc: i16 5, // -- metaclass object offset // CHECK-SAME-native: i16 0, // CHECK-SAME-objc: i16 0, // -- class ro-data offset // CHECK-SAME-native: i16 0 // CHECK-SAME-objc: i16 14, // CHECK-SAME: }> // -- Check that offset vars are emitted for fixed-layout generics // // CHECK: @"$s15generic_classes22RootGenericFixedLayoutC1xs5UInt8VvpWvd" = hidden constant i64 16, align 8 // CHECK: @"$s15generic_classes22RootGenericFixedLayoutC1ySayxGvpWvd" = hidden constant i64 24, align 8 // CHECK: @"$s15generic_classes22RootGenericFixedLayoutC1zs5UInt8VvpWvd" = hidden constant i64 32, align 8 // -- fixed-layout nongeneric descriptor // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[ROOTNONGENERIC_NAME:@.*]] = private constant [15 x i8] c"RootNonGeneric\00" // CHECK: @"$s15generic_classes14RootNonGenericCMn" = hidden constant <{ {{.*}} %swift.method_descriptor }> <{ // -- flags: class, unique, has vtable // CHECK-DIRECT-SAME: // CHECK-INDIRECT-SAME: // -- name // CHECK-SAME: [15 x i8]* [[ROOTNONGENERIC_NAME]] // -- num fields // CHECK-SAME: i32 3, // -- -- field offset vector offset // CHECK-SAME: i32 10, // CHECK-SAME: }> // CHECK: @"$s15generic_classes14RootNonGenericCMf" = internal global <{ {{.*}} }> <{ // CHECK-SAME: void (%T15generic_classes14RootNonGenericC*)* @"$s15generic_classes14RootNonGenericCfD", // CHECK-DIRECT-SAME: i8** @"$sBoWV", // CHECK-INDIRECT-SAME: i8** null, // CHECK-SAME-native: i64 0, // CHECK-SAME-native: %swift.type* null, // CHECK-SAME-native: %swift.opaque* null, // CHECK-SAME-objc: i64 ptrtoint (%objc_class* @"$s15generic_classes14RootNonGenericCMm" to i64), // CHECK-SAME-objc: %objc_class* @"OBJC_CLASS_$_{{(_TtCs12_)?}}SwiftObject", // CHECK-SAME-objc: %swift.opaque* @_objc_empty_cache, // CHECK-SAME: %swift.opaque* null, // CHECK-SAME-native: i64 1, // CHECK-SAME-objc: @_DATA__TtC15generic_classes14RootNonGeneric // CHECK-SAME: i32 33, // CHECK-SAME: i16 7, // CHECK-SAME: i16 0, // CHECK-SAME: {{.*}}* @"$s15generic_classes14RootNonGenericCMn" // CHECK-SAME: }> // CHECK: @"$s15generic_classes015GenericInheritsC0CMn" = hidden constant // -- template instantiation pattern // CHECK-SAME: @"$s15generic_classes015GenericInheritsC0CMP" // CHECK: @"$s15generic_classes015GenericInheritsC0CMP" = internal constant // -- template instantiation function // CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**, i8*)* @"$s15generic_classes015GenericInheritsC0CMi" // -- pattern flags (1 == has extra data pattern) // CHECK-SAME-native: i32 0, // CHECK-SAME-objc: i32 1, // -- heap destructor // CHECK-SAME: @"$s15generic_classes015GenericInheritsC0CfD" // -- ivar destroyer // CHECK-SAME: i32 0, // -- class flags // CHECK_SAME: i32 3, // -- extra data pattern offset // CHECK-SAME-objc: i16 0, // -- extra data pattern size // CHECK-SAME-objc: i16 23, // -- class ro-data offset // CHECK-SAME-native: i16 0, // CHECK-SAME-objc: i16 5, // -- metaclass object offset // CHECK-SAME-native: i16 0, // CHECK-SAME-objc: i16 0, // -- class ro-data offset // CHECK-SAME-native: i16 0, // CHECK-SAME-objc: i16 14, // -- reserved // CHECK-SAME: i16 0 // CHECK-SAME: } // CHECK: @"$s15generic_classes018GenericInheritsNonC0CMP" 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 @$s15generic_classes11RootGenericCfD : $@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: @_TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_ #RootGeneric.bar: @_TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_ #RootGeneric.bas: @_TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_ } class RootGenericFixedLayout { var x : UInt8 var y : [T] var z : UInt8 init() } sil_vtable RootGenericFixedLayout {} sil @$s15generic_classes22RootGenericFixedLayoutCfD : $@convention(method) (RootGenericFixedLayout) -> () class RootNonGeneric { var x : UInt8 var y : Int var z : UInt8 init() } sil_vtable RootNonGeneric {} sil @$s15generic_classes14RootNonGenericCfD : $@convention(method) (RootNonGeneric) -> () class GenericInheritsGeneric : RootGeneric { var w : B func zippity() func doo() func dah() override init() } sil @$s15generic_classes015GenericInheritsC0CfD : $@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: @_TFC15generic_classes11RootGeneric3fooU__fGS0_Q__FT_T_ [inherited] #RootGeneric.bar: @_TFC15generic_classes11RootGeneric3barU__fGS0_Q__FT_T_ [inherited] #RootGeneric.bas: @_TFC15generic_classes11RootGeneric3basU__fGS0_Q__FT_T_ [inherited] #GenericInheritsGeneric.zippity: @_TFC15generic_classes22GenericInheritsGeneric7zippityU___fGS0_Q_Q0__FT_T_ #GenericInheritsGeneric.doo: @_TFC15generic_classes22GenericInheritsGeneric3dooU___fGS0_Q_Q0__FT_T_ #GenericInheritsGeneric.dah: @_TFC15generic_classes22GenericInheritsGeneric3dahU___fGS0_Q_Q0__FT_T_ } class GenericInheritsNonGeneric : RootNonGeneric { var w : UInt8 override init() } sil_vtable GenericInheritsNonGeneric {} sil @$s15generic_classes018GenericInheritsNonC0CfD : $@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 @$s15generic_classes024RecursiveGenericInheritsD0CfD : $@convention(method) (RecursiveGenericInheritsGeneric) -> () // CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc [[ROOTGENERIC]]* @RootGeneric_fragile_dependent_alloc // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s15generic_classes11RootGenericCMa"(i64 0, %swift.type* %G) // CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // 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 i16* // CHECK: [[ALIGN16:%.*]] = load i16, i16* [[T1]], align 4 // CHECK: [[ALIGN:%.*]] = zext i16 [[ALIGN16]] to i64 // CHECK: call noalias %swift.refcounted* @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{{( dllexport)?}}{{( protected)?}} swiftcc 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{{( dllexport)?}}{{( protected)?}} swiftcc 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 12 // 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{{( dllexport)?}}{{( protected)?}} swiftcc void @RootGeneric_subst_concrete_fragile_dependent_member_access_y // CHECK: [[Y_ADDR:%.*]] = getelementptr inbounds {{.*}}, {{.*}}* %1, i32 0, i32 3 // CHECK: bitcast %TSi* [[Y_ADDR]] to i8* 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{{( dllexport)?}}{{( protected)?}} swiftcc 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 13 // 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 %Ts5UInt8V* 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{{( dllexport)?}}{{( protected)?}} swiftcc i8 @RootGeneric_subst_concrete_fragile_dependent_member_access_z // CHECK: [[Z_ADDR:%.*]] = getelementptr inbounds {{.*}}, {{.*}}* %0, i32 0, i32 4 // CHECK: [[T0:%.*]] = getelementptr inbounds %Ts5UInt8V, %Ts5UInt8V* [[Z_ADDR]], i32 0, i32 0 // CHECK: load i8, i8* [[T0]], align 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_borrow %p : $*UInt8 %q = ref_element_addr %c : $RootGeneric, #RootGeneric.y %y = load_borrow %q : $*Int32 %r = ref_element_addr %c : $RootGeneric, #RootGeneric.z %z = load_borrow %r : $*UInt8 %t = tuple (%x : $UInt8, %y : $Int32, %z : $UInt8) return %t : $(UInt8, Int32, UInt8) } */ // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal %swift.type* @"$s15generic_classes11RootGenericCMi"(%swift.type_descriptor* %0, i8** %1, i8* %2) {{.*}} { // CHECK: [[METADATA:%.*]] = call{{( tail)?}} %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8* %2) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal swiftcc %swift.metadata_response @"$s15generic_classes11RootGenericCMr" // CHECK-SAME: (%swift.type* [[METADATA:%.*]], i8* %0, i8** %1) {{.*}} { // -- initialize the dependent field offsets // CHECK: call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* [[METADATA]], i64 0, i64 3, i8*** {{%.*}}, i64* {{%.*}}) // CHECK: } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal %swift.type* @"$s15generic_classes22RootGenericFixedLayoutCMi"(%swift.type_descriptor* %0, i8** %1, i8* %2) {{.*}} { // CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8* %2) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal swiftcc %swift.metadata_response @"$s15generic_classes22RootGenericFixedLayoutCMr" // CHECK-SAME: (%swift.type* [[METADATA:%.*]], i8* %0, i8** %1) {{.*}} { // CHECK: call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* [[METADATA]], i64 0, i64 3, i8*** {{%.*}}, i64* {{%.*}}) // CHECK: } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal %swift.type* @"$s15generic_classes015GenericInheritsC0CMi"(%swift.type_descriptor* %0, i8** %1, i8* %2) {{.*}} { // 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 class. // CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8* %2) // CHECK-NEXT: ret %swift.type* [[METADATA]] // CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$s15generic_classes015GenericInheritsC0CMr" // CHECK-SAME: (%swift.type* [[METADATA:%.*]], i8* %0, i8** %1) {{.*}} { // Initialize our own dependent field offsets. // CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64* // CHECK: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 20 // CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 // CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %B) // CHECK: [[B_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK: [[B_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1 // CHECK: [[B_OK:%.*]] = icmp ule i64 [[B_STATUS]], 63 // CHECK: br i1 [[B_OK]], // CHECK: [[T0:%.*]] = bitcast %swift.type* [[B_CHECKED]] 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 8 // CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0 // CHECK: store i8** [[T0]], i8*** [[T1]], align 8 // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[FIELDS_ADDR]], i64* [[OFFSETS]]) // CHECK-NEXT: [[INITDEP_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK-NEXT: [[INITDEP_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1 // CHECK-NEXT: [[INITDEP_PRESENT:%.*]] = icmp eq %swift.type* [[INITDEP_METADATA]], null // CHECK-NEXT: br i1 [[INITDEP_PRESENT]], // CHECK: [[DEP:%.*]] = phi %swift.type* [ [[B_CHECKED]], {{.*}} ], [ [[INITDEP_METADATA]], {{.*}} ], [ null, {{.*}} ] // CHECK: [[DEP_REQ:%.*]] = phi i64 [ 63, {{.*}} ], [ [[INITDEP_STATUS]], {{.*}} ], [ 0, {{.*}} ] // CHECK: [[T0:%.*]] = insertvalue %swift.metadata_response undef, %swift.type* [[DEP]], 0 // CHECK: [[T1:%.*]] = insertvalue %swift.metadata_response [[T0]], i64 [[DEP_REQ]], 1 // CHECK: ret %swift.metadata_response [[T1]] // CHECK: } // OSIZE: define hidden swiftcc %swift.metadata_response @"$s15generic_classes11RootGenericCMa"(i64 %0, %swift.type* {{.*}}) [[ATTRS:#[0-9]+]] { // OSIZE: [[ATTRS]] = {{{.*}}noinline