| // RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s |
| |
| // REQUIRES: CPU=x86_64 |
| // REQUIRES: objc_interop |
| |
| import Builtin |
| import Swift |
| |
| // CHECK-DAG: [[REF:%swift.refcounted]] = type |
| // CHECK-DAG: [[TYPE:%swift.type]] = type |
| // CHECK-DAG: [[OBJCCLASS:%objc_class]] = type |
| // CHECK-DAG: [[OPAQUE:%swift.opaque]] = type opaque |
| // CHECK-DAG: [[C_CLASS:%T5class1CC]] = type |
| // CHECK-DAG: [[OBJCOBJ:%objc_object]] = type |
| |
| class C {} |
| sil_vtable C {} |
| |
| // <rdar://14812566>: include _Tt prefix here |
| // CHECK: [[C_NAME:@.*]] = private unnamed_addr constant [13 x i8] c"_TtC5class1C\00" |
| |
| // CHECK: @_DATA__TtC5class1C = private constant {{.*}} { |
| // \ CHECK: i32 128, |
| // \ CHECK: i32 16, |
| // \ CHECK: i32 16, |
| // \ CHECK: i32 0, |
| // \ CHECK: i8* null, |
| // \ CHECK: i8* getelementptr inbounds ([13 x i8], [13 x i8]* [[C_NAME]], i64 0, i64 0), |
| // \ CHECK: i8* null, |
| // \ CHECK: i8* null, |
| // \ CHECK: i8* null, |
| // \ CHECK: i8* null, |
| // \ CHECK: i8* null |
| // \ CHECK: } |
| |
| // CHECK: @"$S5class1CCMf" = internal global <{ {{.*}} }> <{ |
| // \ CHECK: void ([[C_CLASS]]*)* @"$S5class1CCfD", |
| // \ CHECK: i8** @"$SBoWV", |
| // \ CHECK: i64 ptrtoint ([[OBJCCLASS]]* @"$S5class1CCMm" to i64), |
| // \ CHECK: [[OBJCCLASS]]* @"OBJC_CLASS_$__TtCs12_SwiftObject", |
| // \ CHECK: [[OPAQUE]]* @_objc_empty_cache, |
| // \ CHECK: [[OPAQUE]]* null, |
| // \ CHECK: i64 add (i64 ptrtoint ({{.*}}* @_DATA__TtC5class1C to i64), i64 1) |
| // \ CHECK: }> |
| |
| // Destroying destructor |
| // CHECK: define{{( protected)?}} swiftcc [[REF]]* @"$S5class1CCfd"([[C_CLASS]]* swiftself) {{.*}} { |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[OBJ_PTR:%[a-zA-Z0-9]+]] = bitcast [[C_CLASS]]* %0 to [[REF]]* |
| // CHECK-NEXT: ret [[REF]]* [[OBJ_PTR]] |
| sil @$S5class1CCfd : $@convention(method) (@owned C) -> @owned Builtin.NativeObject { |
| bb0(%0 : $C): |
| %1 = unchecked_ref_cast %0 : $C to $Builtin.NativeObject // user: %2 |
| return %1 : $Builtin.NativeObject // id: %2 |
| } |
| |
| // Deallocating destructor |
| // CHECK: define{{( protected)?}} swiftcc void @"$S5class1CCfD"([[C_CLASS]]* swiftself) |
| sil @$S5class1CCfD : $@convention(method) (@owned C) -> () { |
| bb0(%0 : $C): |
| // CHECK-NEXT: entry |
| // CHECK-NEXT: [[SELF:%[a-zA-Z0-9]+]] = call swiftcc [[REF]]* @"$S5class1CCfd"([[C_CLASS]]* swiftself %0) |
| // CHECK-NEXT: [[SELF_OBJ:%[a-zA-Z0-9]+]] = bitcast [[REF]]* [[SELF]] to [[C_CLASS]]* |
| %1 = function_ref @$S5class1CCfd : $@convention(method) (@owned C) -> @owned Builtin.NativeObject // user: %2 |
| %2 = apply %1(%0) : $@convention(method) (@owned C) -> @owned Builtin.NativeObject // user: %3 |
| %3 = unchecked_ref_cast %2 : $Builtin.NativeObject to $C // user: %4 |
| // CHECK-NEXT: [[SELF:%[a-zA-Z0-9]+]] = bitcast [[C_CLASS]]* [[SELF_OBJ]] to [[REF]]* |
| // CHECK-NEXT: call void @swift_deallocClassInstance([[REF]]* [[SELF]], i64 16, i64 7) |
| dealloc_ref %3 : $C // id: %4 |
| // CHECK-NEXT: ret void |
| %5 = tuple () // user: %6 |
| return %5 : $() // id: %6 |
| } |
| |
| // CHECK: define{{( protected)?}} swiftcc [[REF]]* @unchecked_ref_cast_cast([[C_CLASS]]*) |
| // CHECK: bitcast [[C_CLASS]]* {{%.*}} to [[REF]]* |
| sil @unchecked_ref_cast_cast : $@convention(thin) C -> Builtin.NativeObject { |
| entry(%c : $C): |
| %r = unchecked_ref_cast %c : $C to $Builtin.NativeObject |
| return %r : $Builtin.NativeObject |
| } |
| |
| // CHECK: define{{( protected)?}} swiftcc [[OBJCOBJ]]* @ref_to_objc_pointer_cast([[C_CLASS]]*) |
| // CHECK: bitcast [[C_CLASS]]* %0 to [[OBJCOBJ]]* |
| sil @ref_to_objc_pointer_cast : $@convention(thin) C -> Builtin.UnknownObject { |
| entry(%c : $C): |
| %r = unchecked_ref_cast %c : $C to $Builtin.UnknownObject |
| return %r : $Builtin.UnknownObject |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc %T5class1CC* @alloc_ref_dynamic(%swift.type*) |
| sil @alloc_ref_dynamic : $@convention(thin) (@thick C.Type) -> @owned C { |
| bb0(%0 : $@thick C.Type): |
| // CHECK: [[META_PTR:%[0-9]+]] = bitcast %swift.type* %0 to i8* |
| // CHECK: [[T0:%.*]] = getelementptr inbounds i8, i8* [[META_PTR]], 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* [[META_PTR]], 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: [[RESULT:%[0-9]+]] = call noalias %swift.refcounted* @swift_allocObject(%swift.type* %0, i64 [[SIZE]], i64 [[ALIGN]]) |
| %1 = alloc_ref_dynamic %0 : $@thick C.Type, $C |
| return %1 : $C |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc %T5class1CC* @autorelease(%T5class1CC*) {{.*}} { |
| // CHECK: %1 = bitcast %T5class1CC* %0 to %objc_object* |
| // CHECK: call %objc_object* @objc_autorelease(%objc_object* %1) |
| // CHECK: ret %T5class1CC* %0 |
| sil @autorelease : $@convention(thin) (@owned C) -> C { |
| entry(%c : $C): |
| autorelease_value %c : $C |
| return %c : $C |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc i64 @autorelease_optional(i64) {{.*}} { |
| // CHECK: %1 = inttoptr i64 %0 to %objc_object* |
| // CHECK: call %objc_object* @objc_autorelease(%objc_object* %1) |
| // CHECK: ret i64 %0 |
| sil @autorelease_optional : $@convention(thin) (@owned C?) -> C? { |
| entry(%c : $C?): |
| autorelease_value %c : $C? |
| return %c : $C? |
| } |
| |
| // rdar://problem/19514920 |
| |
| class NonRequiredBase {} |
| class RequiredBase: NonRequiredBase { |
| required override init() |
| } |
| |
| sil public_external @init_NonRequiredBase : $@convention(method) (@owned NonRequiredBase) -> @owned NonRequiredBase |
| sil public_external @alloc_RequiredBase : $@convention(method) (@thick RequiredBase.Type) -> @owned RequiredBase |
| sil public_external @init_RequiredBase : $@convention(method) (@owned RequiredBase) -> @owned RequiredBase |
| |
| sil_vtable NonRequiredBase { |
| #NonRequiredBase.init!initializer.1: @init_NonRequiredBase |
| } |
| |
| sil_vtable RequiredBase { |
| #NonRequiredBase.init!initializer.1: @init_RequiredBase |
| #RequiredBase.init!allocator.1: @alloc_RequiredBase |
| } |
| |
| // rdar://problem/19902523 |
| |
| protocol ClassConstraint: class {} |
| class ClassConstraintConformance: ClassConstraint {} |
| sil_vtable ClassConstraintConformance {} |
| |
| class ClassConstrainedGenericField<T: ClassConstraint> { |
| var field: T |
| init() |
| } |
| sil_vtable ClassConstrainedGenericField {} |
| |
| sil @fixed_class_generic_field : $@convention(thin) (@owned ClassConstrainedGenericField<ClassConstraintConformance>) -> @owned ClassConstraintConformance { |
| entry(%x : $ClassConstrainedGenericField<ClassConstraintConformance>): |
| %a = ref_element_addr %x : $ClassConstrainedGenericField<ClassConstraintConformance>, #ClassConstrainedGenericField.field |
| %b = load %a : $*ClassConstraintConformance |
| return %b : $ClassConstraintConformance |
| } |
| // CHECK-LABEL: define{{( protected)?}} swiftcc %T5class26ClassConstraintConformanceC* @fixed_class_generic_field(%T5class28ClassConstrainedGenericFieldCyAA0B21ConstraintConformanceCG*) |
| // CHECK: [[FIELD_ADDR_GENERIC:%.*]] = getelementptr inbounds %T5class28ClassConstrainedGenericFieldCyAA0B21ConstraintConformanceCG, %T5class28ClassConstrainedGenericFieldCyAA0B21ConstraintConformanceCG* %0, i32 0, i32 1 |
| // CHECK: load %T5class26ClassConstraintConformanceC*, %T5class26ClassConstraintConformanceC** [[FIELD_ADDR_GENERIC]] |
| |