blob: 87974e3d3c67c9bf1e1868a7f4eba5d2690328ff [file] [log] [blame]
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// REQUIRES: CPU=x86_64
import Builtin
import Swift
class SwiftClass {}
sil_vtable SwiftClass {}
sil @$s13partial_apply10SwiftClassCfD : $@convention(method) (SwiftClass) -> ()
sil @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
sil @partially_applyable_to_two_classes : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> ()
sil @use_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: define{{( dllexport)?}}{{( 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*)* @"$s28partially_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: define{{.*}} swiftcc void @partial_apply_class_on_stack(%T13partial_apply10SwiftClassC*)
// CHECK: entry:
// CHECK: [[CTX:%.*]] = bitcast %T13partial_apply10SwiftClassC* %0 to %swift.opaque*
// CHECK: call swiftcc void @use_closure(i8* bitcast (void (%swift.refcounted*)* @"$s28partially_applyable_to_classTA.1" to i8*), %swift.opaque* [[CTX]])
// CHECK: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T13partial_apply10SwiftClassC*)*)(%T13partial_apply10SwiftClassC* %0)
// CHECK: ret void
// CHECK: }
sil @partial_apply_class_on_stack : $@convention(thin) (@owned SwiftClass) -> () {
entry(%a : $SwiftClass):
%f = function_ref @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
%c = partial_apply [callee_guaranteed] [on_stack] %f(%a) : $@convention(thin) (@owned SwiftClass) -> ()
%use = function_ref @use_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
apply %use(%c) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
dealloc_stack %c : $@noescape @callee_guaranteed () ->()
strong_release %a : $SwiftClass
%t = tuple()
return %t : $()
}
// CHECK: define{{.*}} swiftcc void @partial_apply_two_classes_on_stack(%T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC*)
// CHECK: entry:
// CHECK: [[CTX:%.*]] = alloca i8, i64 32, align 16
// CHECK: [[CTX2:%.*]] = bitcast i8* [[CTX]] to %swift.opaque*
// CHECK: [[LAYOUT:%.*]] = bitcast %swift.opaque* [[CTX2]] to <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>*
// CHECK: [[CAPTURE1:%.*]] = getelementptr inbounds <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>, <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>* [[LAYOUT]], i32 0, i32 1
// CHECK: store %T13partial_apply10SwiftClassC* %0, %T13partial_apply10SwiftClassC** [[CAPTURE1]], align 8
// CHECK: [[CAPTURE2:%.*]] = getelementptr inbounds <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>, <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>* [[LAYOUT]], i32 0, i32 2
// CHECK: store %T13partial_apply10SwiftClassC* %1, %T13partial_apply10SwiftClassC** [[CAPTURE2]], align 8
// CHECK: call swiftcc void @use_closure(i8* bitcast (void (%swift.refcounted*)* @"$s34partially_applyable_to_two_classesTA" to i8*), %swift.opaque* [[CTX2]])
// CHECK: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T13partial_apply10SwiftClassC*)*)(%T13partial_apply10SwiftClassC* %0)
// CHECK: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T13partial_apply10SwiftClassC*)*)(%T13partial_apply10SwiftClassC* %1)
// CHECK: ret void
// CHECK: }
sil @partial_apply_two_classes_on_stack : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> () {
entry(%a : $SwiftClass, %b: $SwiftClass):
%f = function_ref @partially_applyable_to_two_classes : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> ()
%c = partial_apply [callee_guaranteed] [on_stack] %f(%a, %b) : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> ()
%use = function_ref @use_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
apply %use(%c) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
dealloc_stack %c : $@noescape @callee_guaranteed () ->()
strong_release %a : $SwiftClass
strong_release %b : $SwiftClass
%t = tuple()
return %t : $()
}
//
// Check that partially applied generic parameters are correctly substituted
// in the forwarder.
//
// CHECK-LABEL: define internal swiftcc i64 @"$s22generic_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:@"\$s[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{{( dllexport)?}}{{( 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:@"\$s[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{{( dllexport)?}}{{( 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:@"\$s[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_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{{( dllexport)?}}{{( 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:@"\$s[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_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{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_guaranteed_class_pair_param(%T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC*)
// CHECK: [[CONTEXT_OBJ:%.*]] = call noalias %swift.refcounted* @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:@"\$s[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{{( dllexport)?}}{{( 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_allocObject
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@"\$s[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{{( dllexport)?}}{{( 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_allocObject
// CHECK-NOT: {{retain|release}}
// CHECK: [[T0:%.*]] = insertvalue {{.*}} [[PARTIAL_APPLY_FORWARDER:@"\$s[A-Za-z0-9_]+TA"]] {{.*}} [[CONTEXT_OBJ]]
// CHECK: ret {{.*}} [[T0]]
// CHECK: define internal swiftcc i64 [[PARTIAL_APPLY_FORWARDER]]
// CHECK: [[X_TMP:%.*]] = alloca
// CHECK: call %T13partial_apply14SwiftClassPairV* @"$s13partial_apply14SwiftClassPairVWOc"
// 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{{( dllexport)?}}{{( 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_VWTABLE_CAST:%.*]] = bitcast i8** [[T_VWTABLE]] to %swift.vwtable*
// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T_VWTABLE_CAST]], i32 0, i32 10
// CHECK: [[T_FLAGS:%.*]] = load i32, i32* [[T_FLAGS_ADDR]]
// CHECK-64: [[T0:%.*]] = zext i32 [[T_FLAGS]] to i64
// CHECK-64: [[T_ALIGN_MASK:%.*]] = and i64 [[T0]], 255
// CHECK-32: [[T_ALIGN_MASK:%.*]] = and i32 [[T_FLAGS]], 255
// CHECK-16: [[T0:%.*]] = trunc i32 [[T_FLAGS]] to i16
// CHECK-16: [[T_ALIGN_MASK:%.*]] = and i16 [[T0]], 255
// 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_VWTABLE_CAST:%.*]] = bitcast i8** [[T_VWTABLE]] to %swift.vwtable*
// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T_VWTABLE_CAST]], i32 0, i32 8
// CHECK: [[T_SIZE:%.*]] = load [[WORD]], [[WORD]]* [[T_SIZE_ADDR]]
// 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_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:@"\$s[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 @"$s28captured_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{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_dynamic_with_out_param
// CHECK: insertvalue {{.*}} [[FORWARDER:@"\$sTA[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{{( dllexport)?}}{{( protected)?}} swiftcc void @test_partial_apply(%T13partial_apply4BaseC*)
// CHECK: [[CTX:%.*]] = bitcast %T13partial_apply4BaseC* %0 to %swift.refcounted*
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s13partial_apply3SubCMa"(i64 0)
// CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// CHECK: call swiftcc void @receive_closure(i8* bitcast (%T13partial_apply3SubC* (%swift.refcounted*)* @"$s26parametric_casting_closureTA.{{[0-9]+}}" to i8*), %swift.refcounted* [[CTX]], %swift.type* [[TYPE]])
// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @"$s26parametric_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* @"$s26parametric_casting_closureTA.{{[0-9]+}}"(%swift.refcounted* swiftself)
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s13partial_apply3SubCMa"(i64 0)
// CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// 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_aliasable ()) -> ()
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @empty_box()
sil @empty_box : $@convention(thin) () -> () {
entry:
// CHECK: [[BOX:%.*]] = call {{.*}}swift_allocEmptyBox
// CHECK: store %swift.refcounted* [[BOX]]
// 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_aliasable ()) -> ()
%g = partial_apply %f(%b, %ba) : $@convention(thin) (@owned <Ï„_0_0> { var Ï„_0_0 } <()>, @inout_aliasable ()) -> ()
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>(%0) : $@convention(thin) <T where T : P2, T.Y : P1, T.Y : P2> (Int) -> ()
%result = tuple ()
return %result : $()
}
// CHECK-LABEL: define{{( dllexport)?}}{{( 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_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 @"$s24complex_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: store %swift.type* %T, %swift.type**
// 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
extension Int: P0 {}
sil hidden_external @concrete_witness_method : $@convention(witness_method: P0) (Int, Int) -> ()
sil hidden @partial_apply_witness_method : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%fn = function_ref @concrete_witness_method : $@convention(witness_method: P0) (Int, Int) -> ()
%pa = partial_apply %fn (%0) : $@convention(witness_method: P0) (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 {{.*}}$s23generic_indirect_returnTA
// CHECK-LABEL: define internal swiftcc void @"$s23generic_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 {{.*}}$s24generic_indirect_return2TA
// CHECK-LABEL: define internal swiftcc void @"$s24generic_indirect_return2TA"(%T13partial_apply12GenericEnum2OySiG* noalias nocapture sret, %swift.refcounted* swiftself)
// CHECK: [[CASTED_ADDR:%.*]] = bitcast %T13partial_apply12GenericEnum2OySiG* %0 to %T13partial_apply12GenericEnum2O*
// CHECK: call swiftcc void @generic_indirect_return2(%T13partial_apply12GenericEnum2O* noalias nocapture sret [[CASTED_ADDR]]
// CHECK: ret void
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*)* @"$s3funTA" 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 () -> ()
}
sil @afun : $@convention(thin) (Int) -> @error Error
// Check that we don't assert on a thin noescape function.
// CHECK-LABEL: define{{.*}} swiftcc void @convert_thin_test
// CHECK: call swiftcc void @afun(i64 {{.*}}, %swift.refcounted* swiftself undef
// CHECK: ret void
sil @convert_thin_test : $@convention(thin) (Int) -> () {
bb(%0 : $Int):
%f = function_ref @afun : $@convention(thin) (Int) -> @error Error
%c = convert_function %f : $@convention(thin) (Int) -> @error Error to $@convention(thin) @noescape (Int) -> @error Error
try_apply %c(%0) : $@convention(thin) @noescape (Int) -> @error Error, normal bb2, error bb1
bb1(%err: $Error):
%t = tuple ()
br bb3(%t: $())
bb2(%r : $()):
br bb3(%r : $())
bb3(%v : $()):
return %v : $()
}
struct A1 {
let b: () -> ()
}
struct A2<T> {
let a: T
}
class A3 {}
sil @amethod : $@convention(method) (@in_guaranteed A2<A3>) -> (@owned A1, @error Error)
sil @repo : $@convention(thin) (@in_guaranteed A2<A3>) -> @owned @callee_guaranteed () -> (@owned A1, @error Error) {
bb0(%0 : $*A2<A3>):
%1 = load %0 : $*A2<A3>
%2 = alloc_stack $A2<A3>
store %1 to %2 : $*A2<A3>
%4 = function_ref @amethod : $@convention(method) (@in_guaranteed A2<A3>) -> (@owned A1, @error Error)
%5 = partial_apply [callee_guaranteed] %4(%2) : $@convention(method) (@in_guaranteed A2<A3>) -> (@owned A1, @error Error)
dealloc_stack %2 : $*A2<A3>
return %5 : $@callee_guaranteed () -> (@owned A1, @error Error)
}
sil @capture_class : $@convention(thin) (@guaranteed A3) -> ()
// CHECK-LABEL: define{{.*}} swiftcc i8* @partial_apply_stack_in_coroutine(i8* {{.*}}, %T13partial_apply2A3C*)
// CHECK: entry:
// CHECK: [[CLOSURE_CONTEXT:%.*]] = bitcast %T13partial_apply2A3C* %1 to %swift.opaque*
// CHECK: [[CONTEXT:%.*]] = bitcast %swift.opaque* [[CLOSURE_CONTEXT]] to %swift.refcounted*
// CHECK: call swiftcc void @"$s13capture_classTA"(%swift.refcounted* swiftself [[CONTEXT]])
sil @partial_apply_stack_in_coroutine : $@yield_once (@owned A3) -> () {
entry(%0: $A3):
%f = function_ref @capture_class : $@convention(thin) (@guaranteed A3) -> ()
%p = partial_apply [callee_guaranteed] [on_stack] %f(%0) : $@convention(thin) (@guaranteed A3) -> ()
apply %p() : $@noescape @callee_guaranteed () -> ()
dealloc_stack %p : $@noescape @callee_guaranteed () -> ()
%1000 = integer_literal $Builtin.Int32, 1000
yield (), resume resume, unwind unwind
resume:
%ret = tuple ()
return %ret : $()
unwind:
unwind
}
sil_vtable A3 {}