Files
swift-mirror/test/IRGen/partial_apply.sil
John McCall 2840478147 When preparing necessary bindings, we sometimes decide to capture
bound generic type metadata rather than its individual components.
Don't crash when actually restoring that metadata.

Fixes SR-901.
2016-03-09 15:12:27 -08:00

590 lines
34 KiB
Plaintext

// RUN: rm -rf %t && mkdir %t
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) %s -emit-ir -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 {
func method(x x: Int) {}
func initFamily() -> ObjCClass { return self }
}
sil_vtable ObjCClass {}
sil @_TFC13partial_apply9ObjCClassD : $@convention(method) (ObjCClass) -> ()
sil @_TFC13partial_apply9ObjCClasscfMS_FT_S_ : $@convention(method) (ObjCClass) -> ObjCClass {
bb0(%0 : $ObjCClass):
return %0 : $ObjCClass
}
sil @_TToFC13partial_apply9ObjCClasscfT_S0_ : $@convention(objc_method) (ObjCClass) -> ObjCClass {
bb0(%0 : $ObjCClass):
// function_ref ObjectiveC.ObjCClass.constructor (ObjectiveC.ObjCClass.Type)() -> ObjectiveC.ObjCClass
%1 = function_ref @_TFC13partial_apply9ObjCClasscfMS_FT_S_ : $@convention(method) (ObjCClass) -> ObjCClass // user: %2
%2 = apply %1(%0) : $@convention(method) (ObjCClass) -> ObjCClass // user: %3
return %2 : $ObjCClass
}
sil @_TToFC13partial_apply9ObjCClass6methodfT1xSi_T_ : $@convention(objc_method) (Int, ObjCClass) -> () {
bb0(%0 : $Int, %1 : $ObjCClass):
%v = tuple()
return %v : $()
}
sil @_TToFC13partial_apply9ObjCClass10initFamilyfT_S0_ : $@convention(objc_method) (@owned ObjCClass) -> @owned ObjCClass {
bb0(%0 : $ObjCClass):
return %0 : $ObjCClass
}
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @indirect_partial_apply(i8*, %swift.refcounted*, i64) {{.*}} {
// CHECK: entry:
// CHECK: [[OBJ:%.*]] = call noalias %swift.refcounted* @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:@_TPA[A-Za-z0-9_]*]] to i8*), %swift.refcounted* undef }, %swift.refcounted* [[OBJ]], 1
// CHECK: ret { i8*, %swift.refcounted* } [[RET]]
// CHECK: }
// CHECK: define internal void [[INDIRECT_PARTIAL_APPLY_STUB]](%swift.refcounted*) {{.*}} {
// 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 void [[FN]](i64 [[X]], %swift.refcounted* [[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)?}} { i8*, %swift.refcounted* } @objc_partial_apply(%C13partial_apply9ObjCClass*) {{.*}} {
// CHECK: entry:
// CHECK: [[OBJ:%.*]] = call noalias %swift.refcounted* @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, %C13partial_apply9ObjCClass\* }>]]*
// CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1
// CHECK: store %C13partial_apply9ObjCClass* %0, %C13partial_apply9ObjCClass** [[X_ADDR]], align 8
// CHECK: [[RET:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (i64, %swift.refcounted*)* [[OBJC_PARTIAL_APPLY_STUB:@_TPA[A-Za-z0-9_]*]] to i8*), %swift.refcounted* undef }, %swift.refcounted* [[OBJ]], 1
// CHECK: ret { i8*, %swift.refcounted* } [[RET]]
// CHECK: }
// CHECK: define internal void [[OBJC_PARTIAL_APPLY_STUB]](i64, %swift.refcounted*) {{.*}} {
// 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 %C13partial_apply9ObjCClass*, %C13partial_apply9ObjCClass** [[X_ADDR]], align 8
// CHECK-NOT: swift_retain
// CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(methodWithX:)", align 8
// CHECK: [[I8PTRSELF:%.*]] = bitcast %C13partial_apply9ObjCClass* [[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 -> (x: Int) -> () , $@convention(objc_method) (Int, ObjCClass) -> ()
%p = partial_apply %m(%c) : $@convention(objc_method) (Int, ObjCClass) -> ()
return %p : $@callee_owned Int -> ()
}
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @objc_partial_apply_consumes_self(%C13partial_apply9ObjCClass*) {{.*}} {
// CHECK: bitcast %swift.refcounted* {{%.*}} to [[DATA_TYPE:<{ %swift.refcounted, %C13partial_apply9ObjCClass\* }>]]*
// CHECK: insertvalue {{.*}} [[OBJC_CONSUMES_SELF_PARTIAL_APPLY_STUB:@_TPA[A-Za-z0-9_.]*]]
// CHECK: define internal %C13partial_apply9ObjCClass* [[OBJC_CONSUMES_SELF_PARTIAL_APPLY_STUB]](%swift.refcounted*) {{.*}} {
// 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 %C13partial_apply9ObjCClass*, %C13partial_apply9ObjCClass** [[X_ADDR]], align 8
// CHECK: call void @rt_swift_retain(%swift.refcounted* %4)
// CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(initFamily)", align 8
// CHECK: [[I8PTRSELF:%.*]] = bitcast %C13partial_apply9ObjCClass* [[SELF]] to [[OPAQUE4:%.*]]*
// CHECK: call [[OPAQUE3:%.*]]* bitcast (void ()* @objc_msgSend to [[OPAQUE3]]* ([[OPAQUE4:%.*]]*, i8*)*)([[OPAQUE4]]* [[I8PTRSELF]], i8* [[CMD]])
// 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.initFamily!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)?}} { 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:@_TPA[A-Za-z0-9_.]*]] to i8*), {{%.*}} ]
// CHECK: define internal void [[DYNAMIC_LOOKUP_BR_PARTIAL_APPLY_STUB]](i64, %swift.refcounted*) {{.*}} {
// 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 -> ()
}
class SwiftClass {}
sil_vtable SwiftClass {}
sil @_TFC13partial_apply10SwiftClassD : $@convention(method) (SwiftClass) -> ()
sil @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
// CHECK: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_class(%C13partial_apply10SwiftClass*) {{.*}} {
// CHECK: entry:
// CHECK: %1 = bitcast %C13partial_apply10SwiftClass* %0 to %swift.refcounted*
// CHECK: %2 = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%C13partial_apply10SwiftClass*)* @partially_applyable_to_class to i8*), %swift.refcounted* undef }, %swift.refcounted* %1, 1
// CHECK: ret { i8*, %swift.refcounted* } %2
// CHECK: }
sil @partial_apply_class : $@convention(thin) SwiftClass -> @callee_owned () -> () {
entry(%c : $SwiftClass):
%f = function_ref @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
%g = partial_apply %f(%c) : $@convention(thin) (@owned SwiftClass) -> ()
return %g : $@callee_owned () -> ()
}
sil @partially_applyable_to_pure_objc : $@convention(thin) Gizmo -> ()
// CHECK: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_pure_objc
// CHECK: @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 () -> ()
}
//
// Check that partially applied generic parameters are correctly substituted
// in the forwarder.
//
// CHECK-LABEL: define internal i64 @_TPA_generic_captured_param(i64, %swift.refcounted*) {{.*}} {
// CHECK: bitcast %Si* {{%.*}} to %swift.opaque*
sil public_external @generic_captured_param : $@convention(thin) <T> (Int, @inout T) -> Int
sil @partial_apply_generic_capture : $@convention(thin) Int -> @callee_owned Int -> Int {
entry(%x : $Int):
%a = alloc_stack $Int
store %x to %a : $*Int
%f = function_ref @generic_captured_param : $@convention(thin) <T> (Int, @inout T) -> Int
%p = partial_apply %f<Int>(%a) : $@convention(thin) <T> (Int, @inout T) -> Int
dealloc_stack %a : $*Int
return %p : $@callee_owned Int -> Int
}
sil public_external @generic_captured_and_open_param : $@convention(thin) <T> (@in T, @inout T) -> @out T
// CHECK-LABEL: define {{.*}} @partial_apply_open_generic_capture({{.*}} %swift.type* %T) {{.*}} {
// CHECK: store %swift.type* %T
// CHECK: insertvalue {{.*}} [[PARTIAL_APPLY_STUB:@_TPA_[A-Za-z0-9_]+]]
// CHECK: define {{.*}} [[PARTIAL_APPLY_STUB]]
// CHECK: [[T:%.*]] = load %swift.type*, %swift.type**
// CHECK: tail call void @generic_captured_and_open_param({{.*}} %swift.type* [[T]])
sil @partial_apply_open_generic_capture : $@convention(thin) <T> (@inout T) -> @callee_owned (@in T) -> @out T {
entry(%a : $*T):
%f = function_ref @generic_captured_and_open_param : $@convention(thin) <U> (@in U, @inout U) -> @out U
%p = partial_apply %f<T>(%a) : $@convention(thin) <U> (@in U, @inout U) -> @out U
return %p : $@callee_owned (@in T) -> @out T
}
/*****************************************************************************/
/* Swift-refcounted class captures. Optimizable by using the reference */
/* as the partial apply context. */
/*****************************************************************************/
sil public_external @guaranteed_captured_class_param : $@convention(thin) (Int, @guaranteed SwiftClass) -> Int
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_guaranteed_class_param(%C13partial_apply10SwiftClass*)
// CHECK: [[CONTEXT_OBJ:%.*]] = bitcast %C13partial_apply10SwiftClass* {{%.*}} to %swift.refcounted*
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_TPA_[A-Za-z0-9_]+]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[X:%.*]] = bitcast %swift.refcounted* %1 to %C13partial_apply10SwiftClass*
// CHECK-NOT: retain
// CHECK: [[RESULT:%.*]] = call i64 @guaranteed_captured_class_param(i64 %0, %C13partial_apply10SwiftClass* [[X]])
// CHECK: release{{.*}} %1)
// CHECK: ret i64 [[RESULT]]
sil @partial_apply_guaranteed_class_param : $@convention(thin) (@owned SwiftClass) -> @callee_owned (Int) -> Int {
bb0(%x : $SwiftClass):
%f = function_ref @guaranteed_captured_class_param : $@convention(thin) (Int, @guaranteed SwiftClass) -> Int
%p = partial_apply %f(%x) : $@convention(thin) (Int, @guaranteed SwiftClass) -> Int
return %p : $@callee_owned (Int) -> Int
}
sil public_external @indirect_guaranteed_captured_class_param : $@convention(thin) (Int, @in_guaranteed SwiftClass) -> Int
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_indirect_guaranteed_class_param(%C13partial_apply10SwiftClass** noalias nocapture dereferenceable({{.*}}))
// CHECK-NOT: {{retain|release}}
// CHECK: [[X:%.*]] = load %C13partial_apply10SwiftClass*, %C13partial_apply10SwiftClass** %0
// CHECK-NEXT: [[CONTEXT_OBJ:%.*]] = bitcast %C13partial_apply10SwiftClass* [[X]] to %swift.refcounted*
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_TPA_[A-Za-z0-9_]+]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[X_TMP:%.*]] = alloca %C13partial_apply10SwiftClass*
// CHECK-NEXT: [[X:%.*]] = bitcast %swift.refcounted* %1 to %C13partial_apply10SwiftClass*
// CHECK-NEXT: store %C13partial_apply10SwiftClass* [[X]], %C13partial_apply10SwiftClass** [[X_TMP]], align
// CHECK-NOT: load
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: [[RESULT:%.*]] = call i64 @indirect_guaranteed_captured_class_param(i64 %0, %C13partial_apply10SwiftClass** noalias nocapture dereferenceable({{.*}}) [[X_TMP]])
// CHECK-NOT: retain
// CHECK: call void @rt_swift_release(%swift.refcounted* %1)
// CHECK: ret i64 [[RESULT]]
sil @partial_apply_indirect_guaranteed_class_param : $@convention(thin) (@in SwiftClass) -> @callee_owned (Int) -> Int {
bb0(%x : $*SwiftClass):
%f = function_ref @indirect_guaranteed_captured_class_param : $@convention(thin) (Int, @in_guaranteed SwiftClass) -> Int
%p = partial_apply %f(%x) : $@convention(thin) (Int, @in_guaranteed SwiftClass) -> Int
return %p : $@callee_owned (Int) -> Int
}
sil public_external @indirect_consumed_captured_class_param : $@convention(thin) (Int, @in SwiftClass) -> Int
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_indirect_consumed_class_param(%C13partial_apply10SwiftClass** noalias nocapture dereferenceable({{.*}}))
// CHECK-NOT: {{retain|release}}
// CHECK: [[X:%.*]] = load %C13partial_apply10SwiftClass*, %C13partial_apply10SwiftClass** %0
// CHECK-NEXT: [[CONTEXT_OBJ:%.*]] = bitcast %C13partial_apply10SwiftClass* [[X]] to %swift.refcounted*
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_TPA_[A-Za-z0-9_]+]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[X_TMP:%.*]] = alloca %C13partial_apply10SwiftClass*
// CHECK-NEXT: [[X:%.*]] = bitcast %swift.refcounted* %1 to %C13partial_apply10SwiftClass*
// CHECK-NEXT: store %C13partial_apply10SwiftClass* [[X]], %C13partial_apply10SwiftClass** [[X_TMP]], align
// CHECK-NOT: load
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: [[RESULT:%.*]] = tail call i64 @indirect_consumed_captured_class_param(i64 %0, %C13partial_apply10SwiftClass** noalias nocapture dereferenceable({{.*}}) [[X_TMP]])
// CHECK-NOT: retain
// CHECK-NOT: release
// CHECK: ret i64 [[RESULT]]
sil @partial_apply_indirect_consumed_class_param : $@convention(thin) (@in SwiftClass) -> @callee_owned (Int) -> Int {
bb0(%x : $*SwiftClass):
%f = function_ref @indirect_consumed_captured_class_param : $@convention(thin) (Int, @in SwiftClass) -> Int
%p = partial_apply %f(%x) : $@convention(thin) (Int, @in SwiftClass) -> Int
return %p : $@callee_owned (Int) -> Int
}
/*****************************************************************************/
/* A non-trivial capture. Indirect applications can directly reference the */
/* field from the partial apply context. */
/*****************************************************************************/
struct SwiftClassPair { var x: SwiftClass, y: SwiftClass }
sil public_external @guaranteed_captured_class_pair_param : $@convention(thin) (Int, @guaranteed SwiftClassPair) -> Int
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_guaranteed_class_pair_param(%C13partial_apply10SwiftClass*, %C13partial_apply10SwiftClass*)
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject
// CHECK: [[PAIR_ADDR:%.*]] = getelementptr
// CHECK-NEXT: [[X_ADDR:%.*]] = getelementptr inbounds %V13partial_apply14SwiftClassPair, %V13partial_apply14SwiftClassPair* [[PAIR_ADDR]], i32 0, i32 0
// CHECK-NEXT: store %C13partial_apply10SwiftClass* %0, %C13partial_apply10SwiftClass** [[X_ADDR]], align
// CHECK-NEXT: [[Y_ADDR:%.*]] = getelementptr inbounds %V13partial_apply14SwiftClassPair, %V13partial_apply14SwiftClassPair* [[PAIR_ADDR]], i32 0, i32 1
// CHECK-NEXT: store %C13partial_apply10SwiftClass* %1, %C13partial_apply10SwiftClass** [[Y_ADDR]], align
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_TPA_[A-Za-z0-9_]+]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[PAIR_ADDR:%.*]] = getelementptr
// CHECK-NEXT: [[X_ADDR:%.*]] = getelementptr inbounds %V13partial_apply14SwiftClassPair, %V13partial_apply14SwiftClassPair* [[PAIR_ADDR]], i32 0, i32 0
// CHECK-NEXT: [[X:%.*]] = load %C13partial_apply10SwiftClass*, %C13partial_apply10SwiftClass** [[X_ADDR]], align
// CHECK-NEXT: [[Y_ADDR:%.*]] = getelementptr inbounds %V13partial_apply14SwiftClassPair, %V13partial_apply14SwiftClassPair* [[PAIR_ADDR]], i32 0, i32 1
// CHECK-NEXT: [[Y:%.*]] = load %C13partial_apply10SwiftClass*, %C13partial_apply10SwiftClass** [[Y_ADDR]], align
// CHECK-NOT: retain
// CHECK: [[RESULT:%.*]] = call i64 @guaranteed_captured_class_pair_param(i64 %0, %C13partial_apply10SwiftClass* [[X]], %C13partial_apply10SwiftClass* [[Y]])
// CHECK: release{{.*}}%1)
// CHECK: ret i64 [[RESULT]]
sil @partial_apply_guaranteed_class_pair_param : $@convention(thin) (@owned SwiftClassPair) -> @callee_owned (Int) -> Int {
bb0(%x : $SwiftClassPair):
%f = function_ref @guaranteed_captured_class_pair_param : $@convention(thin) (Int, @guaranteed SwiftClassPair) -> Int
%p = partial_apply %f(%x) : $@convention(thin) (Int, @guaranteed SwiftClassPair) -> Int
return %p : $@callee_owned (Int) -> Int
}
sil public_external @indirect_guaranteed_captured_class_pair_param : $@convention(thin) (Int, @in_guaranteed SwiftClassPair) -> Int
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_indirect_guaranteed_class_pair_param(%V13partial_apply14SwiftClassPair* noalias nocapture dereferenceable({{.*}}))
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_TPA_[A-Za-z0-9_]+]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[PAIR_ADDR:%.*]] = getelementptr
// CHECK-NOT: load
// CHECK-NOT: retain
// CHECK: [[RESULT:%.*]] = call i64 @indirect_guaranteed_captured_class_pair_param(i64 %0, %V13partial_apply14SwiftClassPair* noalias nocapture dereferenceable({{.*}}) [[PAIR_ADDR]])
// CHECK: release{{.*}}%1)
// CHECK: ret i64 [[RESULT]]
sil @partial_apply_indirect_guaranteed_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> @callee_owned (Int) -> Int {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_guaranteed_captured_class_pair_param : $@convention(thin) (Int, @in_guaranteed SwiftClassPair) -> Int
%p = partial_apply %f(%x) : $@convention(thin) (Int, @in_guaranteed SwiftClassPair) -> Int
return %p : $@callee_owned (Int) -> Int
}
sil public_external @indirect_consumed_captured_class_pair_param : $@convention(thin) (Int, @in SwiftClassPair) -> Int
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_indirect_consumed_class_pair_param(%V13partial_apply14SwiftClassPair* noalias nocapture dereferenceable({{.*}}))
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_TPA_[A-Za-z0-9_]+]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[X_TMP:%.*]] = alloca
// CHECK: retain
// CHECK: retain
// CHECK-NOT: retain
// CHECK: release{{.*}}%1)
// CHECK: [[RESULT:%.*]] = call i64 @indirect_consumed_captured_class_pair_param(i64 %0, %V13partial_apply14SwiftClassPair* noalias nocapture dereferenceable({{.*}}) [[X_TMP]])
// CHECK: ret i64 [[RESULT]]
sil @partial_apply_indirect_consumed_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> @callee_owned (Int) -> Int {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_consumed_captured_class_pair_param : $@convention(thin) (Int, @in SwiftClassPair) -> Int
%p = partial_apply %f(%x) : $@convention(thin) (Int, @in SwiftClassPair) -> Int
return %p : $@callee_owned (Int) -> Int
}
sil public_external @captured_fixed_and_dependent_params : $@convention(thin) <A> (@owned SwiftClass, @in A, Int) -> ()
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_indirect_non_fixed_layout(%C13partial_apply10SwiftClass*, %swift.opaque* noalias nocapture, i64, %swift.type* %T)
// -- Round the base offset for the T field up to T's alignment.
// CHECK: [[T_METADATA_BASE:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[T_VWTABLE_ADDR:%.*]] = getelementptr {{.*}} [[T_METADATA_BASE]], [[WORD:i[0-9]+]] -1
// CHECK: [[T_VWTABLE:%.*]] = load {{.*}} [[T_VWTABLE_ADDR]]
// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 18
// CHECK: [[T_FLAGS_PTR:%.*]] = load {{.*}} [[T_FLAGS_ADDR]]
// CHECK: [[T_FLAGS:%.*]] = ptrtoint {{.*}} [[T_FLAGS_PTR]] to [[WORD]]
// CHECK: [[T_ALIGN_MASK:%.*]] = and [[WORD]] [[T_FLAGS]], 65535
// CHECK: [[T_ALIGN_MASK_NOT:%.*]] = xor [[WORD]] [[T_ALIGN_MASK]], -1
// -- 32 is 64-bit offset of 'T' field, 16 for obj header + 8 for T metadata + 8 for SwiftClass field
// CHECK-64: [[T_UP_TO_ALIGN_1:%.*]] = add i64 32, [[T_ALIGN_MASK]]
// -- 16 is 32-bit
// CHECK-32: [[T_UP_TO_ALIGN_1:%.*]] = add i32 16, [[T_ALIGN_MASK]]
// CHECK: [[T_OFFSET:%.*]] = and [[WORD]] [[T_UP_TO_ALIGN_1]], [[T_ALIGN_MASK_NOT]]
// -- Add the size of T to start the Int field.
// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 17
// CHECK: [[T_SIZE_PTR:%.*]] = load {{.*}} [[T_SIZE_ADDR]]
// CHECK: [[T_SIZE:%.*]] = ptrtoint {{.*}} [[T_SIZE_PTR]] to [[WORD]]
// CHECK: [[T_END:%.*]] = add [[WORD]] [[T_OFFSET]], [[T_SIZE]]
// -- Accumulate total alignment.
// CHECK: [[TOTAL_ALIGN_1:%.*]] = or [[WORD]] 7, [[T_ALIGN_MASK]]
// -- Round up to alignment for the Int field.
// TODO: could skip this since the best-known alignment is better than
// fixed alignment of Int
// CHECK-64: [[INT_UP_TO_ALIGN_1:%.*]] = add [[WORD]] [[T_END]], 7
// CHECK-64: [[INT_OFFSET:%.*]] = and [[WORD]] [[INT_UP_TO_ALIGN_1]], -8
// CHECK-32: [[INT_UP_TO_ALIGN_1:%.*]] = add [[WORD]] [[T_END]], 3
// CHECK-32: [[INT_OFFSET:%.*]] = and [[WORD]] [[INT_UP_TO_ALIGN_1]], -4
// -- Add the size of Int, and accumulate total alignment.
// CHECK-64: [[TOTAL_SIZE:%.*]] = add [[WORD]] [[INT_OFFSET]], 8
// CHECK-64: [[TOTAL_ALIGN:%.*]] = or [[WORD]] [[TOTAL_ALIGN_1]], 7
// CHECK-32: [[TOTAL_SIZE:%.*]] = add [[WORD]] [[INT_OFFSET]], 4
// CHECK-32: [[TOTAL_ALIGN:%.*]] = or [[WORD]] [[TOTAL_ALIGN_1]], 3
// -- Allocate using the total size and alignment.
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject(%swift.type* {{.*}}, [[WORD]] [[TOTAL_SIZE]], [[WORD]] [[TOTAL_ALIGN]])
// CHECK: [[BOX_DATA:%.*]] = bitcast %swift.refcounted* [[BOX]]
// -- metadata
// CHECK: getelementptr inbounds {{.*}} [[BOX_DATA]], i32 0, i32 1
// -- SwiftClass
// CHECK: getelementptr inbounds {{.*}} [[BOX_DATA]], i32 0, i32 2
// -- T
// CHECK: [[BOX_BYTES:%.*]] = bitcast {{.*}} [[BOX_DATA]] to i8*
// CHECK: getelementptr inbounds {{.*}} [[BOX_BYTES]], [[WORD]] [[T_OFFSET]]
// -- Int
// CHECK: [[BOX_BYTES:%.*]] = bitcast {{.*}} [[BOX_DATA]] to i8*
// CHECK: getelementptr inbounds {{.*}} [[BOX_BYTES]], [[WORD]] [[INT_OFFSET]]
// CHECK: insertvalue {{.*}} [[PARTIAL_APPLY_STUB:@_TPA[A-Za-z0-9_]+]]
// CHECK: define internal void [[PARTIAL_APPLY_STUB]](%swift.refcounted*)
sil @partial_apply_indirect_non_fixed_layout : $@convention(thin) <T> (@owned SwiftClass, @in T, Int) -> @callee_owned () -> () {
bb0(%a : $SwiftClass, %b : $*T, %c : $Int):
%f = function_ref @captured_fixed_and_dependent_params : $@convention(thin) <B> (@owned SwiftClass, @in B, Int) -> ()
%p = partial_apply %f<T>(%a, %b, %c) : $@convention(thin) <C> (@owned SwiftClass, @in C, Int) -> ()
return %p : $@callee_owned () -> ()
}
sil public_external @captured_dependent_out_param : $@convention(thin) <A> (@in A) -> @out A
sil @partial_apply_with_out_param : $@convention(thin) <T> (@in T) -> @callee_owned () -> @out T {
bb0(%x : $*T):
%f = function_ref @captured_dependent_out_param : $@convention(thin) <B> (@in B) -> @out B
%p = partial_apply %f<T>(%x) : $@convention(thin) <C> (@in C) -> @out C
return %p : $@callee_owned () -> @out T
}
// CHECK-LABEL: define internal void @_TPA_captured_dependent_out_param(%swift.opaque* noalias nocapture sret, %swift.refcounted*) {{.*}} {
// CHECK: call void @captured_dependent_out_param(%swift.opaque* noalias nocapture sret
sil @partial_apply_dynamic_with_out_param : $@convention(thin) <T> (Int32, @owned @callee_owned (Int32) -> @out T) -> @callee_owned () -> @out T {
bb0(%x : $Int32, %f : $@callee_owned (Int32) -> @out T):
%p = partial_apply %f(%x) : $@callee_owned (Int32) -> @out T
return %p : $@callee_owned () -> @out T
}
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_dynamic_with_out_param
// CHECK: insertvalue {{.*}} [[FORWARDER:@_TPA[A-Za-z0-9_]*]]
// CHECK: define internal void [[FORWARDER]]
// CHECK: call void {{%.*}}(%swift.opaque* noalias nocapture sret
class Base {
}
sil_vtable Base {}
class Sub : Base {
}
sil_vtable Sub {}
sil @parametric_casting_closure : $@convention(thin) <C where C : Base> (@owned Base) -> @owned C {
bb0(%0 : $Base):
%1 = unconditional_checked_cast %0 : $Base to $C
return %1 : $C
}
sil public_external @receive_closure : $@convention(thin) <C where C : Base> (@owned @callee_owned () -> (@owned C)) -> ()
// CHECK-LABEL: define{{( protected)?}} void @test_partial_apply(%C13partial_apply4Base*)
// CHECK: [[CTX:%.*]] = bitcast %C13partial_apply4Base* %0 to %swift.refcounted*
// CHECK: [[TYPE:%.*]] = call %swift.type* @_TMaC13partial_apply3Sub()
// CHECK: call void @receive_closure(i8* bitcast (%C13partial_apply3Sub* (%swift.refcounted*)* @_TPA_parametric_casting_closure.28 to i8*), %swift.refcounted* [[CTX]], %swift.type* [[TYPE]])
// CHECK-LABEL: define internal %C13partial_apply3Sub* @_TPA_parametric_casting_closure(%C13partial_apply4Base*, %swift.refcounted*)
// CHECK: [[RES:%.*]] = tail call %C13partial_apply4Base* @parametric_casting_closure
// CHECK: [[CASTED:%.*]] = bitcast %C13partial_apply4Base* [[RES]] to %C13partial_apply3Sub*
// CHECK: ret %C13partial_apply3Sub* [[CASTED]]
// CHECK-LABEL: define internal %C13partial_apply3Sub* @_TPA_parametric_casting_closure.28(%swift.refcounted*)
// CHECK: [[TYPE:%.*]] = call %swift.type* @_TMaC13partial_apply3Sub()
// CHECK: [[CTX:%.*]] = bitcast %swift.refcounted* %0 to %C13partial_apply4Base*
// CHECK: [[CALL:%.*]] = tail call %C13partial_apply4Base* @parametric_casting_closure(%C13partial_apply4Base* [[CTX]], %swift.type* [[TYPE]])
// CHECK: [[CAST:%.*]] = bitcast %C13partial_apply4Base* [[CALL]] to %C13partial_apply3Sub*
// CHECK: ret %C13partial_apply3Sub* [[CAST]]
sil @test_partial_apply : $@convention(thin) (@owned Base) -> () {
bb0(%0 : $Base):
%1 = function_ref @parametric_casting_closure : $@convention(thin) <C where C : Base> (@owned Base) -> @owned C
%6 = partial_apply %1<Sub>() : $@convention(thin) <C where C : Base> (@owned Base) -> @owned C
%2 = partial_apply %1<Sub>(%0) : $@convention(thin) <C where C : Base> (@owned Base) -> @owned C
%3 = function_ref @receive_closure : $@convention(thin) <C where C : Base> (@owned @callee_owned () -> (@owned C)) -> ()
%4 = apply %3<Sub>(%2) : $@convention(thin) <C where C : Base> (@owned @callee_owned () -> (@owned C)) -> ()
%5 = tuple ()
return %5 : $()
}
sil public_external @partial_empty_box : $@convention(thin) (@owned @box (), @inout ()) -> ()
// CHECK-LABEL: define{{( protected)?}} void @empty_box()
sil @empty_box : $@convention(thin) () -> () {
entry:
// CHECK: store %swift.refcounted* null
// CHECK: store %swift.opaque* undef
%b = alloc_box $()
%ba = project_box %b : $@box ()
%f = function_ref @partial_empty_box : $@convention(thin) (@owned @box (), @inout ()) -> ()
%g = partial_apply %f(%b, %ba) : $@convention(thin) (@owned @box (), @inout ()) -> ()
return undef : $()
}
protocol P0 {}
protocol P1 { associatedtype X : P0 }
protocol P2 { associatedtype Y : P1 }
sil hidden_external @complex_generic_function : $@convention(thin) <T where T : P2, T.Y : P2> (Int) -> ()
sil @partial_apply_complex_generic_function : $@convention(thin) <T where T : P2, T.Y : P2> (Int) -> () {
bb0(%0 : $Int):
%fn = function_ref @complex_generic_function : $@convention(thin) <T where T : P2, T.Y : P2> (Int) -> ()
%pa = partial_apply %fn <T, T.Y, T.Y.X, T.Y.Y, T.Y.Y.X>(%0) : $@convention(thin) <T where T : P2, T.Y : P1, T.Y : P2, T.Y.X : P0, T.Y.Y : P1, T.Y.Y.X : P0> (Int) -> ()
%result = tuple ()
return %result : $()
}
// CHECK-LABEL: define void @partial_apply_complex_generic_function(i64, %swift.type* %T, i8** %T.P2, i8** %T.Y.P2)
// CHECK: [[T0:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject(%swift.type* {{.*}}, i64 48, i64 7)
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.refcounted* [[T0]] to <{ %swift.refcounted, [24 x i8], %Si }>*
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %Si }>, <{ %swift.refcounted, [24 x i8], %Si }>* [[T1]], i32 0, i32 1
// CHECK-NEXT: [[BUFFER:%.*]] = bitcast [24 x i8]* [[T2]] to %swift.type**
// CHECK-NEXT: store %swift.type* %T, %swift.type** [[BUFFER]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 1
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: store i8** %T.P2, i8*** [[T1]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 2
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: store i8** %T.Y.P2, i8*** [[T1]], align 8
// CHECK-LABEL: define internal void @_TPA_complex_generic_function(%swift.refcounted*)
// CHECK: [[T0:%.*]] = bitcast %swift.refcounted* %0 to <{ %swift.refcounted, [24 x i8], %Si }>*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %Si }>, <{ %swift.refcounted, [24 x i8], %Si }>* [[T0]], i32 0, i32 1
// CHECK-NEXT: [[BUFFER:%.*]] = bitcast [24 x i8]* [[T1]] to %swift.type**
// CHECK-NEXT: %T = load %swift.type*, %swift.type** [[BUFFER]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 1
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: %T.P2 = load i8**, i8*** [[T1]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 2
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: %T.Y.P2 = load i8**, i8*** [[T1]], align 8
struct ComplexBoundedType<T: P2> {}
// SR-901: Ensure that a partial_apply which captures bound generic type
// metadata doesn't crash when restoring the generic context.
sil hidden_external @generic_function : $@convention(thin) <T> () -> ()
sil @partial_apply_with_generic_type : $@convention(thin) <U: P2> () -> () {
bb0:
%fn = function_ref @generic_function : $@convention(thin) <T> () -> ()
%pa = partial_apply %fn <ComplexBoundedType<U>>() : $@convention(thin) <T> () -> ()
%result = tuple ()
return %result : $()
}