mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
We would run into an assertion during building the partial apply forwarding thunk because we passed down a parameter convention of an empty argument although we ignore it for the purpose of adding to the closure context. However, the code path for the non-allocated closure context (0 or one capture) would assert that there is only one convention. Reconcile this by not adding the empty parameter to the convention array. rdar://31487947
516 lines
30 KiB
Plaintext
516 lines
30 KiB
Plaintext
// RUN: %target-swift-frontend %s -emit-ir -assume-parsing-unqualified-ownership-sil | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
|
|
|
|
// REQUIRES: CPU=x86_64
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class SwiftClass {}
|
|
sil_vtable SwiftClass {}
|
|
sil @_T013partial_apply10SwiftClassCfD : $@convention(method) (SwiftClass) -> ()
|
|
|
|
sil @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_class(%T13partial_apply10SwiftClassC*) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: %1 = bitcast %T13partial_apply10SwiftClassC* %0 to %swift.refcounted*
|
|
// CHECK: %2 = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%swift.refcounted*)* @_T028partially_applyable_to_classTA 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 () -> ()
|
|
}
|
|
|
|
//
|
|
// Check that partially applied generic parameters are correctly substituted
|
|
// in the forwarder.
|
|
//
|
|
|
|
// CHECK-LABEL: define internal swiftcc i64 @_T022generic_captured_paramTA(i64, %swift.refcounted* swiftself) {{.*}} {
|
|
// CHECK: bitcast %TSi* {{%.*}} 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:@_T0[A-Za-z0-9_]+TA]]
|
|
|
|
// CHECK: define {{.*}} [[PARTIAL_APPLY_STUB]]
|
|
// CHECK: [[T:%.*]] = load %swift.type*, %swift.type**
|
|
// CHECK: tail call swiftcc 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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_guaranteed_class_param(%T13partial_apply10SwiftClassC*)
|
|
// CHECK: [[CONTEXT_OBJ:%.*]] = bitcast %T13partial_apply10SwiftClassC* {{%.*}} to %swift.refcounted*
|
|
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_T0[A-Za-z0-9_]+TA]] {{.*}} [[CONTEXT_OBJ]]
|
|
// CHECK: ret {{.*}} [[T0]]
|
|
|
|
// CHECK: define internal swiftcc i64 [[PARTIAL_APPLY_FORWARDER]]
|
|
// CHECK: [[X:%.*]] = bitcast %swift.refcounted* %1 to %T13partial_apply10SwiftClassC*
|
|
// CHECK-NOT: retain
|
|
// CHECK: [[RESULT:%.*]] = call swiftcc i64 @guaranteed_captured_class_param(i64 %0, %T13partial_apply10SwiftClassC* [[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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_indirect_guaranteed_class_param(%T13partial_apply10SwiftClassC** noalias nocapture dereferenceable({{.*}}))
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[X:%.*]] = load %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC** %0
|
|
// CHECK-NEXT: [[CONTEXT_OBJ:%.*]] = bitcast %T13partial_apply10SwiftClassC* [[X]] to %swift.refcounted*
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_T0[A-Za-z0-9_]+TA]] {{.*}} [[CONTEXT_OBJ]]
|
|
// CHECK: ret {{.*}} [[T0]]
|
|
|
|
// CHECK: define internal swiftcc 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 %T13partial_apply10SwiftClassC**
|
|
// CHECK-NOT: load
|
|
// CHECK-NOT: retain
|
|
// CHECK-NOT: release
|
|
// CHECK: [[RESULT:%.*]] = call swiftcc i64 @indirect_guaranteed_captured_class_param(i64 %0, %T13partial_apply10SwiftClassC** noalias nocapture dereferenceable({{.*}}) [[X_CAST]]
|
|
// CHECK-NOT: retain
|
|
// CHECK: call void @swift_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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_indirect_consumed_class_param(%T13partial_apply10SwiftClassC** noalias nocapture dereferenceable({{.*}}))
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[X:%.*]] = load %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC** %0
|
|
// CHECK-NEXT: [[CONTEXT_OBJ:%.*]] = bitcast %T13partial_apply10SwiftClassC* [[X]] to %swift.refcounted*
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_T0[A-Za-z0-9_]+TA]] {{.*}} [[CONTEXT_OBJ]]
|
|
// CHECK: ret {{.*}} [[T0]]
|
|
|
|
// CHECK: define internal swiftcc 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 %T13partial_apply10SwiftClassC**
|
|
// CHECK-NOT: load
|
|
// CHECK-NOT: retain
|
|
// CHECK-NOT: release
|
|
// CHECK: [[RESULT:%.*]] = tail call swiftcc i64 @indirect_consumed_captured_class_param(i64 %0, %T13partial_apply10SwiftClassC** 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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_guaranteed_class_pair_param(%T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC*)
|
|
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject
|
|
// CHECK: [[PAIR_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[X_ADDR:%.*]] = getelementptr inbounds %T13partial_apply14SwiftClassPairV, %T13partial_apply14SwiftClassPairV* [[PAIR_ADDR]], i32 0, i32 0
|
|
// CHECK-NEXT: store %T13partial_apply10SwiftClassC* %0, %T13partial_apply10SwiftClassC** [[X_ADDR]], align
|
|
// CHECK-NEXT: [[Y_ADDR:%.*]] = getelementptr inbounds %T13partial_apply14SwiftClassPairV, %T13partial_apply14SwiftClassPairV* [[PAIR_ADDR]], i32 0, i32 1
|
|
// CHECK-NEXT: store %T13partial_apply10SwiftClassC* %1, %T13partial_apply10SwiftClassC** [[Y_ADDR]], align
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_T0[A-Za-z0-9_]+TA]] {{.*}} [[CONTEXT_OBJ]]
|
|
// CHECK: ret {{.*}} [[T0]]
|
|
|
|
// CHECK: define internal swiftcc i64 [[PARTIAL_APPLY_FORWARDER]]
|
|
// CHECK: [[PAIR_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[X_ADDR:%.*]] = getelementptr inbounds %T13partial_apply14SwiftClassPairV, %T13partial_apply14SwiftClassPairV* [[PAIR_ADDR]], i32 0, i32 0
|
|
// CHECK-NEXT: [[X:%.*]] = load %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC** [[X_ADDR]], align
|
|
// CHECK-NEXT: [[Y_ADDR:%.*]] = getelementptr inbounds %T13partial_apply14SwiftClassPairV, %T13partial_apply14SwiftClassPairV* [[PAIR_ADDR]], i32 0, i32 1
|
|
// CHECK-NEXT: [[Y:%.*]] = load %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC** [[Y_ADDR]], align
|
|
// CHECK-NOT: retain
|
|
// CHECK: [[RESULT:%.*]] = call swiftcc i64 @guaranteed_captured_class_pair_param(i64 %0, %T13partial_apply10SwiftClassC* [[X]], %T13partial_apply10SwiftClassC* [[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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_indirect_guaranteed_class_pair_param(%T13partial_apply14SwiftClassPairV* noalias nocapture dereferenceable({{.*}}))
|
|
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_T0[A-Za-z0-9_]+TA]] {{.*}} [[CONTEXT_OBJ]]
|
|
// CHECK: ret {{.*}} [[T0]]
|
|
|
|
// CHECK: define internal swiftcc i64 [[PARTIAL_APPLY_FORWARDER]]
|
|
// CHECK: [[PAIR_ADDR:%.*]] = getelementptr
|
|
// CHECK-NOT: load
|
|
// CHECK-NOT: retain
|
|
// CHECK: [[RESULT:%.*]] = call swiftcc i64 @indirect_guaranteed_captured_class_pair_param(i64 %0, %T13partial_apply14SwiftClassPairV* 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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_indirect_consumed_class_pair_param(%T13partial_apply14SwiftClassPairV* noalias nocapture dereferenceable({{.*}}))
|
|
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject
|
|
// CHECK-NOT: {{retain|release}}
|
|
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@_T0[A-Za-z0-9_]+TA]] {{.*}} [[CONTEXT_OBJ]]
|
|
// CHECK: ret {{.*}} [[T0]]
|
|
|
|
// CHECK: define internal swiftcc i64 [[PARTIAL_APPLY_FORWARDER]]
|
|
// CHECK: [[X_TMP:%.*]] = alloca
|
|
// CHECK: retain
|
|
// CHECK: retain
|
|
// CHECK-NOT: retain
|
|
// CHECK: release{{.*}}%1)
|
|
// CHECK: [[RESULT:%.*]] = call swiftcc i64 @indirect_consumed_captured_class_pair_param(i64 %0, %T13partial_apply14SwiftClassPairV* 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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_indirect_non_fixed_layout(%T13partial_apply10SwiftClassC*, %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* @swift_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:@_T0[A-Za-z0-9_]+TA]]
|
|
// CHECK: define internal swiftcc void [[PARTIAL_APPLY_STUB]](%swift.refcounted* swiftself)
|
|
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 swiftcc void @_T028captured_dependent_out_paramTA(%swift.opaque* noalias nocapture sret, %swift.refcounted* swiftself) {{.*}} {
|
|
// CHECK: call swiftcc 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)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_dynamic_with_out_param
|
|
// CHECK: insertvalue {{.*}} [[FORWARDER:@_T0TA[A-Za-z0-9_]*]]
|
|
// CHECK: define internal swiftcc void [[FORWARDER]]
|
|
// CHECK: call swiftcc 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)?}} swiftcc void @test_partial_apply(%T13partial_apply4BaseC*)
|
|
// CHECK: [[CTX:%.*]] = bitcast %T13partial_apply4BaseC* %0 to %swift.refcounted*
|
|
// CHECK: [[TYPE:%.*]] = call %swift.type* @_T013partial_apply3SubCMa()
|
|
// CHECK: call swiftcc void @receive_closure(i8* bitcast (%T13partial_apply3SubC* (%swift.refcounted*)* @_T026parametric_casting_closureTA.{{[0-9]+}} to i8*), %swift.refcounted* [[CTX]], %swift.type* [[TYPE]])
|
|
|
|
// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @_T026parametric_casting_closureTA(%T13partial_apply4BaseC*, %swift.refcounted* swiftself)
|
|
// CHECK: [[RES:%.*]] = tail call swiftcc %T13partial_apply4BaseC* @parametric_casting_closure
|
|
// CHECK: [[CASTED:%.*]] = bitcast %T13partial_apply4BaseC* [[RES]] to %T13partial_apply3SubC*
|
|
// CHECK: ret %T13partial_apply3SubC* [[CASTED]]
|
|
|
|
|
|
// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @_T026parametric_casting_closureTA.{{[0-9]+}}(%swift.refcounted* swiftself)
|
|
// CHECK: [[TYPE:%.*]] = call %swift.type* @_T013partial_apply3SubCMa()
|
|
// CHECK: [[CTX:%.*]] = bitcast %swift.refcounted* %0 to %T13partial_apply4BaseC*
|
|
// CHECK: [[CALL:%.*]] = tail call swiftcc %T13partial_apply4BaseC* @parametric_casting_closure(%T13partial_apply4BaseC* [[CTX]], %swift.type* [[TYPE]])
|
|
// CHECK: [[CAST:%.*]] = bitcast %T13partial_apply4BaseC* [[CALL]] to %T13partial_apply3SubC*
|
|
// CHECK: ret %T13partial_apply3SubC* [[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 <τ_0_0> { var τ_0_0 } <()>, @inout ()) -> ()
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @empty_box()
|
|
sil @empty_box : $@convention(thin) () -> () {
|
|
entry:
|
|
// CHECK: store %swift.refcounted* null
|
|
// CHECK: store %swift.opaque* undef
|
|
%b = alloc_box $<τ_0_0> { var τ_0_0 } <()>
|
|
%ba = project_box %b : $<τ_0_0> { var τ_0_0 } <()>, 0
|
|
%f = function_ref @partial_empty_box : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <()>, @inout ()) -> ()
|
|
%g = partial_apply %f(%b, %ba) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <()>, @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>(%0) : $@convention(thin) <T where T : P2, T.Y : P1, T.Y : P2> (Int) -> ()
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @partial_apply_complex_generic_function(i64, %swift.type* %T, i8** %T.P2, i8** %T.Y.P2)
|
|
// CHECK: [[T0:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}}, i64 48, i64 7)
|
|
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.refcounted* [[T0]] to <{ %swift.refcounted, [24 x i8], %TSi }>*
|
|
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, <{ %swift.refcounted, [24 x i8], %TSi }>* [[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 swiftcc void @_T024complex_generic_functionTA(%swift.refcounted* swiftself)
|
|
// CHECK: [[T0:%.*]] = bitcast %swift.refcounted* %0 to <{ %swift.refcounted, [24 x i8], %TSi }>*
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, <{ %swift.refcounted, [24 x i8], %TSi }>* [[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 : $()
|
|
}
|
|
|
|
// Crash on partial apply of witness_method without generic signature
|
|
|
|
sil hidden_external @concrete_witness_method : $@convention(witness_method) (Int, Int) -> ()
|
|
|
|
sil hidden @partial_apply_witness_method : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%fn = function_ref @concrete_witness_method : $@convention(witness_method) (Int, Int) -> ()
|
|
%pa = partial_apply %fn (%0) : $@convention(witness_method) (Int, Int) -> ()
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
|
|
// Crash on partial apply of a generic enum.
|
|
enum GenericEnum<T> {
|
|
case X(String)
|
|
case Y(T, T, T, T, T)
|
|
}
|
|
sil public_external @generic_indirect_return : $@convention(thin) <T> (Int) -> @owned GenericEnum<T>
|
|
|
|
// CHECK-LABEL: define{{.*}} @partial_apply_generic_indirect_return
|
|
// CHECK: insertvalue {{.*}}_T023generic_indirect_returnTA
|
|
|
|
// CHECK-LABEL: define internal swiftcc void @_T023generic_indirect_returnTA(%T13partial_apply11GenericEnumOySiG* noalias nocapture sret, %swift.refcounted* swiftself
|
|
// CHECK: [[CASTEDRETURN:%.*]] = bitcast %T13partial_apply11GenericEnumOySiG* %0 to %T13partial_apply11GenericEnumO*
|
|
// CHECK: call swiftcc void @generic_indirect_return({{.*}}[[CASTEDRETURN]]
|
|
// CHECK: ret void
|
|
sil @partial_apply_generic_indirect_return : $@convention(thin) (Int) -> @callee_owned () -> @owned GenericEnum<Int> {
|
|
bb0(%0 : $Int):
|
|
%fn = function_ref @generic_indirect_return :$@convention(thin) <T> (Int) -> @owned GenericEnum<T>
|
|
%pa = partial_apply %fn<Int> (%0) : $@convention(thin) <T> (Int) -> @owned GenericEnum<T>
|
|
return %pa : $@callee_owned () -> @owned GenericEnum<Int>
|
|
|
|
}
|
|
|
|
// Crash on partial apply of a generic enum.
|
|
enum GenericEnum2<T> {
|
|
case X(String)
|
|
case Y(T)
|
|
}
|
|
sil public_external @generic_indirect_return2 : $@convention(thin) <T> (Int) -> @owned GenericEnum2<T>
|
|
|
|
// CHECK-LABEL: define{{.*}} @partial_apply_generic_indirect_return2
|
|
// CHECK: insertvalue {{.*}}_T024generic_indirect_return2TA
|
|
|
|
// CHECK-LABEL: define internal swiftcc { i64, i64, i64, i8 } @_T024generic_indirect_return2TA(%swift.refcounted* swiftself) #0 {
|
|
// CHECK: [[TMP:%.*]] = alloca %T13partial_apply12GenericEnum2OySiG
|
|
// CHECK: [[CASTED_ADDR:%.*]] = bitcast %T13partial_apply12GenericEnum2OySiG* [[TMP]] to %T13partial_apply12GenericEnum2O*
|
|
// CHECK: call swiftcc void @generic_indirect_return2(%T13partial_apply12GenericEnum2O* noalias nocapture sret [[CASTED_ADDR]]
|
|
// CHECK: [[SUBST_ADDR:%.*]] = bitcast %T13partial_apply12GenericEnum2OySiG* [[TMP]] to { i64, i64, i64 }*
|
|
// CHECK: [[ELT_ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[SUBST_ADDR]], i32 0, i32 0
|
|
// CHECK: [[ELT:%.*]] = load i64, i64* [[ELT_ADDR]]
|
|
// CHECK: [[ELT_ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[SUBST_ADDR]], i32 0, i32 1
|
|
// CHECK: [[ELT2:%.*]] = load i64, i64* [[ELT_ADDR]]
|
|
// CHECK: [[ELT_ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[SUBST_ADDR]], i32 0, i32 2
|
|
// CHECK: [[ELT3:%.*]] = load i64, i64* [[ELT_ADDR]]
|
|
// CHECK: [[ENUMTAGADDR:%.*]] = getelementptr inbounds %T13partial_apply12GenericEnum2OySiG, %T13partial_apply12GenericEnum2OySiG* [[TMP]], i32 0, i32 1
|
|
// CHECK: [[ENUMTAGBITADDR:%.*]] = bitcast [1 x i8]* [[ENUMTAGADDR]] to i1*
|
|
// CHECK: [[TAGBIT:%.*]] = load i1, i1* [[ENUMTAGBITADDR]]
|
|
// CHECK: [[ELT4:%.*]] = zext i1 [[TAGBIT]] to i8
|
|
// CHECK: [[TMP:%.*]] = insertvalue { i64, i64, i64, i8 } undef, i64 [[ELT]], 0
|
|
// CHECK: [[TMP2:%.*]] = insertvalue { i64, i64, i64, i8 } [[TMP]], i64 [[ELT2]], 1
|
|
// CHECK: [[TMP3:%.*]] = insertvalue { i64, i64, i64, i8 } [[TMP2]], i64 [[ELT3]], 2
|
|
// CHECK: [[TMP4:%.*]] = insertvalue { i64, i64, i64, i8 } [[TMP3]], i8 [[ELT4]], 3
|
|
// CHECK: ret { i64, i64, i64, i8 } [[TMP4]]
|
|
sil @partial_apply_generic_indirect_return2 : $@convention(thin) (Int) -> @callee_owned () -> @owned GenericEnum2<Int> {
|
|
bb0(%0 : $Int):
|
|
%fn = function_ref @generic_indirect_return2 :$@convention(thin) <T> (Int) -> @owned GenericEnum2<T>
|
|
%pa = partial_apply %fn<Int> (%0) : $@convention(thin) <T> (Int) -> @owned GenericEnum2<T>
|
|
return %pa : $@callee_owned () -> @owned GenericEnum2<Int>
|
|
}
|
|
|
|
struct SwiftStruct {}
|
|
|
|
sil @fun : $@convention(thin) (@thin SwiftStruct.Type, @owned SwiftClass) -> ()
|
|
|
|
// CHECK-LABEL: define{{.*}} swiftcc { i8*, %swift.refcounted* } @partial_apply_thin_type(%T13partial_apply10SwiftClassC*)
|
|
// CHECK: [[CONTEXT:%.*]] = bitcast %T13partial_apply10SwiftClassC* %0 to %swift.refcounted*
|
|
// CHECK: [[CLOSURE:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%swift.refcounted*)* @_T03funTA to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CONTEXT]], 1
|
|
// CHECK: ret { i8*, %swift.refcounted* } [[CLOSURE]]
|
|
|
|
sil @partial_apply_thin_type : $@convention(thin) (@thin SwiftStruct.Type, @owned SwiftClass) -> @callee_owned () -> () {
|
|
entry(%0: $@thin SwiftStruct.Type, %1: $SwiftClass):
|
|
%fun = function_ref @fun : $@convention(thin) (@thin SwiftStruct.Type, @owned SwiftClass) -> ()
|
|
%closure = partial_apply %fun (%0, %1) : $@convention(thin) (@thin SwiftStruct.Type, @owned SwiftClass) -> ()
|
|
return %closure : $@callee_owned () -> ()
|
|
}
|