| // RUN: rm -rf %t && mkdir -p %t |
| // RUN: %build-irgen-test-overlays |
| // RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) %s -emit-ir -assume-parsing-unqualified-ownership-sil -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize |
| |
| // REQUIRES: CPU=x86_64 |
| // REQUIRES: objc_interop |
| |
| import Builtin |
| import Swift |
| import Foundation |
| import gizmo |
| |
| @objc class ObjCClass : BaseClassForMethodFamilies { |
| func method(x: Int) {} |
| func method2(r: NSRect) {} |
| |
| override func fakeInitFamily() -> ObjCClass { return self } |
| } |
| sil_vtable ObjCClass {} |
| sil @_T018partial_apply_objc9ObjCClassCfD : $@convention(method) (ObjCClass) -> () |
| |
| sil @_T018partial_apply_objc9ObjCClassCACycACmcfc : $@convention(method) (ObjCClass) -> ObjCClass { |
| bb0(%0 : $ObjCClass): |
| return %0 : $ObjCClass |
| } |
| |
| sil @_T018partial_apply_objc9ObjCClassCACycfcTo : $@convention(objc_method) (ObjCClass) -> ObjCClass { |
| bb0(%0 : $ObjCClass): |
| // function_ref ObjectiveC.ObjCClass.constructor (ObjectiveC.ObjCClass.Type)() -> ObjectiveC.ObjCClass |
| %1 = function_ref @_T018partial_apply_objc9ObjCClassCACycACmcfc : $@convention(method) (ObjCClass) -> ObjCClass // user: %2 |
| %2 = apply %1(%0) : $@convention(method) (ObjCClass) -> ObjCClass // user: %3 |
| return %2 : $ObjCClass |
| } |
| |
| sil @_T018partial_apply_objc9ObjCClassC6methodySi1x_tFTo : $@convention(objc_method) (Int, ObjCClass) -> () { |
| bb0(%0 : $Int, %1 : $ObjCClass): |
| %v = tuple() |
| return %v : $() |
| } |
| sil @_T018partial_apply_objc9ObjCClassC7method2ySC6NSRectV1r_tFTo : $@convention(objc_method) (NSRect, ObjCClass) -> () { |
| bb0(%0 : $NSRect, %1 : $ObjCClass): |
| %v = tuple() |
| return %v : $() |
| } |
| |
| sil @_T018partial_apply_objc9ObjCClassC14fakeInitFamilyACyFTo : $@convention(objc_method) (@owned ObjCClass) -> @owned ObjCClass { |
| bb0(%0 : $ObjCClass): |
| return %0 : $ObjCClass |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @indirect_partial_apply(i8*, %swift.refcounted*, i64) {{.*}} { |
| // CHECK: entry: |
| // CHECK: [[OBJ:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) |
| // CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* [[OBJ]] to [[DATA_TYPE:<{ %swift.refcounted, i64, %swift.refcounted\*, i8\* }>]]* |
| // CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1 |
| // CHECK: store i64 %2, i64* [[X_ADDR]], align 8 |
| // CHECK: [[CONTEXT_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 2 |
| // CHECK: store %swift.refcounted* %1, %swift.refcounted** [[CONTEXT_ADDR]], align 8 |
| // CHECK: [[FN_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 3 |
| // CHECK: store i8* %0, i8** [[FN_ADDR]], align 8 |
| // CHECK: [[RET:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%swift.refcounted*)* [[INDIRECT_PARTIAL_APPLY_STUB:@_T0TA[A-Za-z0-9_]*]] to i8*), %swift.refcounted* undef }, %swift.refcounted* [[OBJ]], 1 |
| // CHECK: ret { i8*, %swift.refcounted* } [[RET]] |
| // CHECK: } |
| // CHECK: define internal swiftcc void [[INDIRECT_PARTIAL_APPLY_STUB]](%swift.refcounted* swiftself) {{.*}} { |
| // CHECK: entry: |
| // CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* %0 to [[DATA_TYPE]] |
| // CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* %1, i32 0, i32 1 |
| // CHECK: [[X:%.*]] = load i64, i64* [[X_ADDR]], align 8 |
| // CHECK: [[CONTEXT_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 2 |
| // CHECK: [[CONTEXT:%.*]] = load %swift.refcounted*, %swift.refcounted** [[CONTEXT_ADDR]], align 8 |
| // CHECK: [[FN_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 3 |
| // CHECK: [[FN_PTR:%.*]] = load i8*, i8** [[FN_ADDR]], align 8 |
| // CHECK: [[FN:%.*]] = bitcast i8* [[FN_PTR]] to void (i64, %swift.refcounted*)* |
| // CHECK: tail call swiftcc void [[FN]](i64 [[X]], %swift.refcounted* swiftself [[CONTEXT]]) |
| // CHECK: ret void |
| // CHECK: } |
| |
| sil @indirect_partial_apply : $@convention(thin) (@callee_owned (Builtin.Word) -> (), Builtin.Word) -> @callee_owned () -> () { |
| entry(%f : $@callee_owned (Builtin.Word) -> (), %x : $Builtin.Word): |
| %p = partial_apply %f(%x) : $@callee_owned (Builtin.Word) -> () |
| return %p : $@callee_owned () -> () |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @objc_partial_apply(%T18partial_apply_objc9ObjCClassC*) {{.*}} { |
| // CHECK: entry: |
| // CHECK: [[OBJ:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.2, i32 0, i32 2), i64 24, i64 7) |
| // CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* [[OBJ]] to [[DATA_TYPE:<{ %swift.refcounted, %T18partial_apply_objc9ObjCClassC\* }>]]* |
| // CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1 |
| // CHECK: store %T18partial_apply_objc9ObjCClassC* %0, %T18partial_apply_objc9ObjCClassC** [[X_ADDR]], align 8 |
| // CHECK: [[RET:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (i64, %swift.refcounted*)* [[OBJC_PARTIAL_APPLY_STUB:@_T0Ta[A-Za-z0-9_]*]] to i8*), %swift.refcounted* undef }, %swift.refcounted* [[OBJ]], 1 |
| // CHECK: ret { i8*, %swift.refcounted* } [[RET]] |
| // CHECK: } |
| // CHECK: define internal swiftcc void [[OBJC_PARTIAL_APPLY_STUB]](i64, %swift.refcounted* swiftself) {{.*}} { |
| // CHECK: entry: |
| // CHECK-NOT: swift_retain |
| // CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* %1 to [[DATA_TYPE]]* |
| // CHECK-NOT: swift_retain |
| // CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1 |
| // CHECK-NOT: swift_retain |
| // CHECK: [[SELF:%.*]] = load %T18partial_apply_objc9ObjCClassC*, %T18partial_apply_objc9ObjCClassC** [[X_ADDR]], align 8 |
| // CHECK-NOT: swift_retain |
| // CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(methodWithX:)", align 8 |
| // CHECK: [[I8PTRSELF:%.*]] = bitcast %T18partial_apply_objc9ObjCClassC* [[SELF]] to [[OPAQUE0:%.*]]* |
| // CHECK-NOT: swift_retain |
| // CHECK: call void bitcast (void ()* @objc_msgSend to void ([[OPAQUE2:%.*]]*, i8*, i64)*)([[OPAQUE2]]* [[I8PTRSELF]], i8* [[CMD]], i64 %0) |
| // CHECK: ret void |
| // CHECK: } |
| |
| sil @objc_partial_apply : $@convention(thin) ObjCClass -> @callee_owned Int -> () { |
| entry(%c : $ObjCClass): |
| %m = class_method [volatile] %c : $ObjCClass, #ObjCClass.method!1.foreign : (ObjCClass) -> (Int) -> (), $@convention(objc_method) (Int, ObjCClass) -> () |
| %p = partial_apply %m(%c) : $@convention(objc_method) (Int, ObjCClass) -> () |
| return %p : $@callee_owned Int -> () |
| } |
| |
| // CHECK-LABEL: define{{.*}} { i8*, %swift.refcounted* } @objc_partial_apply_indirect_sil_argument(%T18partial_apply_objc9ObjCClassC*) {{.*}} |
| // CHECK: [[CTX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject |
| // CHECK: [[CTX_ADDR:%.*]] = bitcast %swift.refcounted* [[CTX]] to [[CTXTYPE:<{ %swift.refcounted, %T18partial_apply_objc9ObjCClassC\* }>]]* |
| // CHECK: [[SELF_ADDR:%.*]] = getelementptr inbounds [[CTXTYPE]], [[CTXTYPE]]* [[CTX_ADDR]], i32 0, i32 1 |
| // CHECK: store %T18partial_apply_objc9ObjCClassC* %0, %T18partial_apply_objc9ObjCClassC** [[SELF_ADDR]] |
| // CHECK: [[CLOSURE:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (double, double, double, double, %swift.refcounted*)* [[OBJC_PARTIAL_APPLY_STUB2:@_T0Ta[A-Za-z0-9_.]*]] to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CTX]], 1 |
| // CHECK: ret { i8*, %swift.refcounted* } [[CLOSURE]] |
| // CHECK:} |
| // CHECK: define internal swiftcc void [[OBJC_PARTIAL_APPLY_STUB2]](double, double, double, double, %swift.refcounted* |
| // CHECK: [[TMP:%.*]] = alloca %TSC6NSRectV |
| // CHECK: [[ORIGIN:%.*]] = getelementptr inbounds %TSC6NSRectV, %TSC6NSRectV* [[TMP]] |
| // CHECK: [[ORIGINX:%.*]] = getelementptr inbounds %TSC7NSPointV, %TSC7NSPointV* [[ORIGIN]] |
| // CHECK: [[ORIGINXVAL:%*]] = getelementptr inbounds %TSd, %TSd* [[ORIGINX]] |
| // CHECK: store double %0, double* [[ORIGINXVAL]] |
| sil @objc_partial_apply_indirect_sil_argument : $@convention(thin) ObjCClass -> @callee_owned NSRect -> () { |
| entry(%c : $ObjCClass): |
| %m = class_method [volatile] %c : $ObjCClass, #ObjCClass.method2!1.foreign : (ObjCClass) -> (NSRect) -> (), $@convention(objc_method) (NSRect, ObjCClass) -> () |
| %p = partial_apply %m(%c) : $@convention(objc_method) (NSRect, ObjCClass) -> () |
| return %p : $@callee_owned NSRect -> () |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @objc_partial_apply_consumes_self(%T18partial_apply_objc9ObjCClassC*) {{.*}} { |
| // CHECK: bitcast %swift.refcounted* {{%.*}} to [[DATA_TYPE:<{ %swift.refcounted, %T18partial_apply_objc9ObjCClassC\* }>]]* |
| // CHECK: insertvalue {{.*}} [[OBJC_CONSUMES_SELF_PARTIAL_APPLY_STUB:@_T0Ta[A-Za-z0-9_.]*]] |
| // CHECK: define internal swiftcc %T18partial_apply_objc9ObjCClassC* [[OBJC_CONSUMES_SELF_PARTIAL_APPLY_STUB]](%swift.refcounted* swiftself) {{.*}} { |
| // CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* %0 to [[DATA_TYPE]]* |
| // CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1 |
| // CHECK: [[SELF:%.*]] = load %T18partial_apply_objc9ObjCClassC*, %T18partial_apply_objc9ObjCClassC** [[X_ADDR]], align 8 |
| // CHECK: call {{.*}}@objc_retain{{.*}}(%{{.*}}* [[SELF]]) |
| // CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(fakeInitFamily)", align 8 |
| // CHECK: [[I8PTRSELF:%.*]] = bitcast %T18partial_apply_objc9ObjCClassC* [[SELF]] to [[OPAQUE4:%.*]]* |
| // CHECK: call [[OPAQUE3:%.*]]* bitcast (void ()* @objc_msgSend to [[OPAQUE3]]* ([[OPAQUE4:%.*]]*, i8*)*)([[OPAQUE4]]* [[I8PTRSELF]], i8* [[CMD]]) |
| // CHECK-NOT: release |
| // CHECK: call void @swift_rt_swift_release(%swift.refcounted* %0) |
| // CHECK-NOT: release |
| // CHECK: ret void |
| // CHECK: } |
| |
| sil @objc_partial_apply_consumes_self : $@convention(thin) ObjCClass -> @callee_owned () -> @owned ObjCClass { |
| entry(%c : $ObjCClass): |
| %m = class_method [volatile] %c : $ObjCClass, #ObjCClass.fakeInitFamily!1.foreign : (ObjCClass) -> () -> ObjCClass, $@convention(objc_method) (@owned ObjCClass) -> @owned ObjCClass |
| %p = partial_apply %m(%c) : $@convention(objc_method) (@owned ObjCClass) -> @owned ObjCClass |
| return %p : $@callee_owned () -> @owned ObjCClass |
| } |
| |
| sil @dummy : $@convention(thin) Int -> () { |
| entry(%x : $Int): |
| %v = tuple () |
| return %v : $() |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @dynamic_lookup_br_partial_apply(%objc_object*) {{.*}} { |
| // CHECK: phi i8* [ bitcast (void (i64)* @dummy to i8*), {{%.*}} ], [ bitcast (void (i64, %swift.refcounted*)* [[DYNAMIC_LOOKUP_BR_PARTIAL_APPLY_STUB:@_T0Ta[A-Za-z0-9_.]*]] to i8*), {{%.*}} ] |
| // CHECK: define internal swiftcc void [[DYNAMIC_LOOKUP_BR_PARTIAL_APPLY_STUB]](i64, %swift.refcounted* swiftself) {{.*}} { |
| // CHECK: load i8*, i8** @"\01L_selector(methodWithX:)", align 8 |
| |
| sil @dynamic_lookup_br_partial_apply : $@convention(thin) Builtin.UnknownObject -> @callee_owned Int -> () { |
| entry(%o : $Builtin.UnknownObject): |
| dynamic_method_br %o : $Builtin.UnknownObject, #ObjCClass.method!1.foreign, yes, no |
| |
| yes(%m : $@convention(objc_method) (Int, Builtin.UnknownObject) -> ()): |
| %p = partial_apply %m(%o) : $@convention(objc_method) (Int, Builtin.UnknownObject) -> () |
| br done(%p : $@callee_owned Int -> ()) |
| |
| no: |
| %q = function_ref @dummy : $@convention(thin) Int -> () |
| %r = thin_to_thick_function %q : $@convention(thin) Int -> () to $@callee_owned Int -> () |
| br done(%r : $@callee_owned Int -> ()) |
| |
| done(%f : $@callee_owned Int -> ()): |
| return %f : $@callee_owned Int -> () |
| } |
| |
| sil @partially_applyable_to_pure_objc : $@convention(thin) Gizmo -> () |
| |
| // CHECK: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_pure_objc |
| // CHECK: @swift_rt_swift_allocObject |
| sil @partial_apply_pure_objc : $@convention(thin) Gizmo -> @callee_owned () -> () { |
| entry(%c : $Gizmo): |
| %f = function_ref @partially_applyable_to_pure_objc : $@convention(thin) Gizmo -> () |
| %g = partial_apply %f(%c) : $@convention(thin) Gizmo -> () |
| return %g : $@callee_owned () -> () |
| } |