Files
swift-mirror/test/IRGen/partial_apply_objc.sil
T
Greg Parker e223f1fc9b [IRGen][runtime] Simplify runtime CCs and entry point ABIs (#14175)
* Remove RegisterPreservingCC. It was unused.
* Remove DefaultCC from the runtime. The distinction between C_CC and DefaultCC
  was unused and inconsistently applied. Separate C_CC and DefaultCC are
  still present in the compiler.
* Remove function pointer indirection from runtime functions except those
  that are used by Instruments. The remaining Instruments interface is
  expected to change later due to function pointer liability.
* Remove swift_rt_ wrappers. Function pointers are an ABI liability that we
  don't want, and there are better ways to get nonlazy binding if we need it.
  The fully custom wrappers were only needed for RegisterPreservingCC and
  for optimizing the Instruments function pointers.
2018-01-29 13:22:30 -08:00

274 lines
15 KiB
Plaintext

// RUN: %empty-directory(%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 @$S18partial_apply_objc9ObjCClassCfD : $@convention(method) (ObjCClass) -> ()
sil @$S18partial_apply_objc9ObjCClassCyACycACmcfc : $@convention(method) (ObjCClass) -> ObjCClass {
bb0(%0 : $ObjCClass):
return %0 : $ObjCClass
}
sil @$S18partial_apply_objc9ObjCClassCACycfcTo : $@convention(objc_method) (ObjCClass) -> ObjCClass {
bb0(%0 : $ObjCClass):
// function_ref ObjectiveC.ObjCClass.constructor (ObjectiveC.ObjCClass.Type)() -> ObjectiveC.ObjCClass
%1 = function_ref @$S18partial_apply_objc9ObjCClassCyACycACmcfc : $@convention(method) (ObjCClass) -> ObjCClass // user: %2
%2 = apply %1(%0) : $@convention(method) (ObjCClass) -> ObjCClass // user: %3
return %2 : $ObjCClass
}
sil @$S18partial_apply_objc9ObjCClassC6method1xySi_tFTo : $@convention(objc_method) (Int, ObjCClass) -> () {
bb0(%0 : $Int, %1 : $ObjCClass):
%v = tuple()
return %v : $()
}
sil @$S18partial_apply_objc9ObjCClassC7method21rySo6NSRectV_tFTo : $@convention(objc_method) (NSRect, ObjCClass) -> () {
bb0(%0 : $NSRect, %1 : $ObjCClass):
%v = tuple()
return %v : $()
}
sil @$S18partial_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: [[T0:%.*]] = bitcast i8* %0 to void (i64, %swift.refcounted*)*
// CHECK: [[OBJ:%.*]] = call noalias %swift.refcounted* @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: [[CAST_FN:%.*]] = bitcast void (i64, %swift.refcounted*)* [[T0]] to i8*
// CHECK: store i8* [[CAST_FN]], i8** [[FN_ADDR]], align 8
// CHECK: [[RET:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%swift.refcounted*)* [[INDIRECT_PARTIAL_APPLY_STUB:@"\$STA[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_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:@"\$STa[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 = objc_method %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_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:@"\$STa[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 %TSo6NSRectV
// CHECK: [[ORIGIN:%.*]] = getelementptr inbounds %TSo6NSRectV, %TSo6NSRectV* [[TMP]]
// CHECK: [[ORIGINX:%.*]] = getelementptr inbounds %TSo7NSPointV, %TSo7NSPointV* [[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 = objc_method %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:@"\$STa[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_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 = objc_method %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:@"\$STa[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_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 () -> ()
}
// CHECK: define internal swiftcc void @"$STa.17"(i64, i64, i64, %swift.refcounted* swiftself)
// CHECK: [[TMPCOERCE:%.*]] = alloca { i64, i64, i64 }
// CHECK: [[INDIRECTTEMP:%.*]] = alloca %TSo3FobV
// CHECK: [[ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[TMPCOERCE]], i32 0, i32 0
// CHECK: store i64 %0, i64* [[ADDR]]
// CHECK: [[ADDR:%.]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[TMPCOERCE]], i32 0, i32 1
// CHECK: store i64 %1, i64* [[ADDR]]
// CHECK: [[ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[TMPCOERCE]], i32 0, i32 2
// CHECK: store i64 %2, i64* [[ADDR]]
// CHECK: load i64
// CHECK: load i32
// CHECK: load i32
// CHECK: load i64
// CHECK: store i64
// CHECK: store i32
// CHECK: store i32
// CHECK: store i64
// CHECK: objc_msgSend
// CHECK: ret void
sil @objc_partial_apply_2 : $@convention(thin) Gizmo -> @callee_owned (Fob) -> () {
entry(%c : $Gizmo):
%m = objc_method %c : $Gizmo, #Gizmo.test!1.foreign : (Gizmo) -> (Fob) -> (), $@convention(objc_method) (Fob, Gizmo) -> ()
%p = partial_apply %m(%c) : $@convention(objc_method) (Fob, Gizmo) -> ()
return %p : $@callee_owned (Fob) -> ()
}
// CHECK-LABEL: define {{.*}}@objc_partial_apply_callee_guaranteed
// CHECK: [[CONTEXT:%.*]] = call {{.*}}@swift_allocObject
// CHECK: store
// CHECK: [[CLOSURE:%.*]] = insertvalue {{.*}}@"$STa.20"{{.*}}, {{.*}}[[CONTEXT]], 1
// CHECK: ret {{.*}}[[CLOSURE]]
sil @objc_partial_apply_callee_guaranteed : $@convention(thin) ObjCClass -> @callee_guaranteed Int -> () {
entry(%c : $ObjCClass):
%m = objc_method %c : $ObjCClass, #ObjCClass.method!1.foreign : (ObjCClass) -> (Int) -> (), $@convention(objc_method) (Int, ObjCClass) -> ()
%p = partial_apply [callee_guaranteed] %m(%c) : $@convention(objc_method) (Int, ObjCClass) -> ()
return %p : $@callee_guaranteed Int -> ()
}
// CHECK-LABEL: define {{.*}}swiftcc void @"$STa.20"(i64, %swift.refcounted* swiftself)
// CHECK: entry:
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: call {{.*}}@objc_msgSend
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define {{.*}}@objc_partial_apply_2_callee_guaranteed
// CHECK: [[CONTEXT:%.*]] = call {{.*}}@swift_allocObject
// CHECK: store
// CHECK: [[CLOSURE:%.*]] = insertvalue {{.*}}@"$STa.23"{{.*}}, {{.*}}[[CONTEXT]], 1
// CHECK: ret {{.*}}[[CLOSURE]]
sil @objc_partial_apply_2_callee_guaranteed : $@convention(thin) Gizmo -> @callee_guaranteed (Fob) -> () {
entry(%c : $Gizmo):
%m = objc_method %c : $Gizmo, #Gizmo.test!1.foreign : (Gizmo) -> (Fob) -> (), $@convention(objc_method) (Fob, Gizmo) -> ()
%p = partial_apply [callee_guaranteed] %m(%c) : $@convention(objc_method) (Fob, Gizmo) -> ()
return %p : $@callee_guaranteed (Fob) -> ()
}
// CHECK-LABEL: define {{.*}}swiftcc void @"$STa.23"(i64, i64, i64, %swift.refcounted* swiftself)
// CHECK: entry:
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: call {{.*}}@objc_msgSend
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: ret void
// CHECK: }