| // 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 : BaseClassForMethodFamilies { |
| func method(x: Int) {} |
| |
| override func fakeInitFamily() -> 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_apply9ObjCClass14fakeInitFamilyfT_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) -> (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 {{.*}}@objc_retain{{.*}}(%{{.*}}* [[SELF]]) |
| // CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(fakeInitFamily)", 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-NOT: release |
| // CHECK: call void @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)?}} { 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 %swift.refcounted* |
| // CHECK-NEXT: store %swift.refcounted* %1, %swift.refcounted** [[X_TMP]], align |
| // CHECK-NEXT: [[X_CAST:%.*]] = bitcast %swift.refcounted** [[X_TMP]] to %C13partial_apply10SwiftClass** |
| // 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_CAST]] |
| // 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 %swift.refcounted* |
| // CHECK-NEXT: store %swift.refcounted* %1, %swift.refcounted** [[X_TMP]], align |
| // CHECK-NEXT: [[X_CAST:%.*]] = bitcast %swift.refcounted** [[X_TMP]] to %C13partial_apply10SwiftClass** |
| // 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_CAST]]) |
| // 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.{{[0-9]+}} 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.{{[0-9]+}}(%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 : $() |
| } |