mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Both the syntax and relative order of the LLVM `nocapture` parameter attribute changed upstream in 29441e4f5fa5f5c7709f7cf180815ba97f611297. To reduce conflicts with rebranch, adjust FileCheck patterns to expect both syntaxes and orders anywhere the presence of the attribute is not critical to the test. These changes are temporary and will be cleaned up once rebranch is merged into main.
225 lines
8.8 KiB
Plaintext
225 lines
8.8 KiB
Plaintext
// RUN: %empty-directory(%t)
|
|
// RUN: %build-irgen-test-overlays
|
|
// RUN: %target-swift-frontend -disable-type-layout -sdk %S/Inputs -I %t %s -emit-ir | %FileCheck %s
|
|
|
|
// REQUIRES: CPU=x86_64
|
|
// REQUIRES: objc_interop
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import gizmo
|
|
|
|
typealias AnyObject = Builtin.AnyObject
|
|
|
|
// rdar://16621578
|
|
|
|
sil @init_opaque_existential : $@convention(thin) <T where T : Gizmo> (@owned T) -> @out Any {
|
|
bb0(%0 : $*Any, %1 : $T):
|
|
%2 = init_existential_addr %0 : $*Any, $T
|
|
store %1 to %2 : $*T
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-DAG: define{{( protected)?}} swiftcc void @init_opaque_existential(ptr noalias{{( nocapture)?}} sret({{.*}}){{( captures\(none\))?}} %0, ptr %1, ptr %T) {{.*}} {
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} [[ANY:%Any]], ptr %0, i32 0, i32 1
|
|
// CHECK-NEXT: store ptr %T, ptr [[T0]], align 8
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds{{.*}} [[ANY]], ptr %0, i32 0, i32 0
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds{{.*}} [[ANY]], ptr %0, i32 0, i32 0
|
|
// CHECK-NEXT: store ptr %1, ptr [[T0]], align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
sil @take_opaque_existential : $@convention(thin) (@in Any) -> @out Any {
|
|
bb0(%0 : $*Any, %1 : $*Any):
|
|
copy_addr [take] %1 to [init] %0 : $*Any
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-DAG: define{{( protected)?}} swiftcc void @take_opaque_existential(ptr noalias{{( nocapture)?}} sret({{.*}}){{( captures\(none\))?}} %0, ptr noalias {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK: call ptr @"$sypWOb"(ptr %1, ptr %0)
|
|
// CHECK-NEXT: ret void
|
|
|
|
// CHECK-DAG: define linkonce_odr hidden ptr @"$sypWOb"(ptr %0, ptr %1)
|
|
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %1, ptr align 8 %0, i64 32, i1 false)
|
|
// CHECK-NEXT: ret ptr %1
|
|
|
|
// rdar://problem/19035529
|
|
@objc protocol OP {}
|
|
@objc protocol OP2: OP {}
|
|
|
|
// CHECK-DAG: define{{( protected)?}} swiftcc ptr @init_existential_objc_to_objc(ptr %0) {{.*}} {
|
|
// CHECK: ret ptr %0
|
|
sil @init_existential_objc_to_objc : $@convention(thin) (@owned OP2) -> @owned OP {
|
|
entry(%o : $OP2):
|
|
%a = init_existential_ref %o : $OP2 : $OP2, $OP
|
|
return %a : $OP
|
|
}
|
|
|
|
protocol CP: class {}
|
|
|
|
// CHECK-DAG: define{{( protected)?}} swiftcc { ptr, ptr } @class_existential_unowned(ptr %0, ptr %1) {{.*}} {
|
|
sil @class_existential_unowned : $@convention(thin) (@owned CP) -> @owned CP {
|
|
entry(%s : $CP):
|
|
%u1 = alloc_stack $@sil_unowned CP
|
|
%u2 = alloc_stack $@sil_unowned CP
|
|
// CHECK: [[U1:%.*]] = alloca [[UREF:{ %swift.unowned, ptr }]], align 8
|
|
// CHECK: [[U2:%.*]] = alloca [[UREF]], align 8
|
|
|
|
store_unowned %s to [init] %u1 : $*@sil_unowned CP
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} [[UREF]], ptr [[U1]], i32 0, i32 1
|
|
// CHECK: store ptr %1, ptr [[T0]], align 8
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} [[UREF]], ptr [[U1]], i32 0, i32 0
|
|
// CHECK: call ptr @swift_unknownObjectUnownedInit(ptr returned [[T0]], ptr %0)
|
|
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} [[UREF]], ptr [[U1]], i32 0, i32 0
|
|
// CHECK: [[T1:%.*]] = call ptr @swift_unknownObjectUnownedLoadStrong(ptr [[T0]])
|
|
%t = load_unowned %u1 : $*@sil_unowned CP
|
|
// CHECK: call void @swift_unknownObjectRelease(ptr [[T1]])
|
|
strong_release %t : $CP
|
|
|
|
dealloc_stack %u2 : $*@sil_unowned CP
|
|
dealloc_stack %u1 : $*@sil_unowned CP
|
|
|
|
%v = ref_to_unmanaged %s : $CP to $@sil_unmanaged CP
|
|
// CHECK: call ptr @swift_unknownObjectRetain(ptr
|
|
%v_copy = strong_copy_unmanaged_value %v : $@sil_unmanaged CP
|
|
// CHECK: call void @swift_unknownObjectRelease(ptr
|
|
strong_release %v_copy : $CP
|
|
|
|
%z = unmanaged_to_ref %v : $@sil_unmanaged CP to $CP
|
|
|
|
// CHECK: [[RESULT_A:%.*]] = insertvalue { ptr, ptr } undef, ptr %0, 0
|
|
// CHECK: [[RESULT_B:%.*]] = insertvalue { ptr, ptr } [[RESULT_A]], ptr %1, 1
|
|
// CHECK: ret { ptr, ptr } [[RESULT_B]]
|
|
|
|
return %z : $CP
|
|
}
|
|
|
|
// CHECK-DAG: define{{( protected)?}} swiftcc void @class_existential_weak(ptr noalias sret({{.*}}) %0, i64 %1, i64 %2)
|
|
sil @class_existential_weak : $@convention(thin) (@owned CP?) -> @out @sil_weak CP? {
|
|
entry(%w : $*@sil_weak CP?, %a : $CP?):
|
|
// CHECK: [[V:%.*]] = alloca { %swift.weak, ptr }
|
|
%v = alloc_stack $@sil_weak CP?
|
|
|
|
// CHECK: [[SRC_REF:%.*]] = inttoptr {{.*}} ptr
|
|
// CHECK: [[SRC_WITNESS:%.*]] = inttoptr {{.*}} ptr
|
|
// CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 1
|
|
// CHECK: store ptr [[SRC_WITNESS]], ptr [[DEST_WITNESS_ADDR]]
|
|
// CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 0
|
|
// CHECK: call ptr @swift_unknownObjectWeakInit(ptr returned [[DEST_REF_ADDR]], ptr [[SRC_REF]])
|
|
store_weak %a to [init] %w : $*@sil_weak CP?
|
|
|
|
// CHECK: [[SRC_REF:%.*]] = inttoptr {{.*}} ptr
|
|
// CHECK: [[SRC_WITNESS:%.*]] = inttoptr {{.*}} ptr
|
|
// CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 1
|
|
// CHECK: store ptr [[SRC_WITNESS]], ptr [[DEST_WITNESS_ADDR]]
|
|
// CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 0
|
|
// CHECK: call ptr @swift_unknownObjectWeakAssign(ptr returned [[DEST_REF_ADDR]], ptr [[SRC_REF]])
|
|
store_weak %a to %w : $*@sil_weak CP?
|
|
|
|
// CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 0
|
|
// CHECK: [[DEST_REF:%.*]] = call ptr @swift_unknownObjectWeakTakeStrong(ptr [[SRC_REF_ADDR]])
|
|
// CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 1
|
|
// CHECK: [[DEST_WITNESS:%.*]] = load ptr, ptr [[SRC_WITNESS_ADDR]]
|
|
%b = load_weak [take] %w : $*@sil_weak CP?
|
|
|
|
// CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 0
|
|
// CHECK: [[DEST_REF:%.*]] = call ptr @swift_unknownObjectWeakLoadStrong(ptr [[SRC_REF_ADDR]])
|
|
// CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds{{.*}} { %swift.weak, ptr }, ptr %0, i32 0, i32 1
|
|
// CHECK: [[DEST_WITNESS:%.*]] = load ptr, ptr [[SRC_WITNESS_ADDR]]
|
|
%c = load_weak %w : $*@sil_weak CP?
|
|
|
|
// CHECK: call ptr @"$s17existentials_objc2CP_pSgXwWOb"(ptr %0, ptr [[V]])
|
|
copy_addr [take] %w to [init] %v : $*@sil_weak CP?
|
|
|
|
// CHECK: call ptr @"$s17existentials_objc2CP_pSgXwWOd"(ptr %0, ptr [[V]])
|
|
copy_addr [take] %w to %v : $*@sil_weak CP?
|
|
|
|
// CHECK: call ptr @"$s17existentials_objc2CP_pSgXwWOc"(ptr %0, ptr [[V]])
|
|
copy_addr %w to [init] %v : $*@sil_weak CP?
|
|
|
|
// CHECK: call ptr @"$s17existentials_objc2CP_pSgXwWOf"(ptr %0, ptr [[V]])
|
|
copy_addr %w to %v : $*@sil_weak CP?
|
|
|
|
// CHECK: call ptr @"$s17existentials_objc2CP_pSgXwWOh"(ptr [[V]])
|
|
destroy_addr %v : $*@sil_weak CP?
|
|
|
|
dealloc_stack %v : $*@sil_weak CP?
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
@objc protocol ProtocolA : class {
|
|
@objc optional func funcA()
|
|
}
|
|
|
|
// CHECK: define swiftcc void @useObjcProtocol(ptr swiftself %0)
|
|
// CHECK: entry:
|
|
// CHECK: load ptr, ptr @"\01L_selector(funcA)"
|
|
// CHECK: load ptr, ptr @"\01L_selector(respondsToSelector:)"
|
|
// CHECK: [[TMP:%.*]] = call i1 @objc_msgSend
|
|
// CHECK: br i1 [[TMP]]
|
|
//
|
|
// CHECK: call void @objc_msgSend(ptr %0
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
|
|
sil public @useObjcProtocol : $@convention(method) (@guaranteed ProtocolA) -> () {
|
|
bb0(%0 : $ProtocolA):
|
|
dynamic_method_br %0 : $ProtocolA, #ProtocolA.funcA!foreign, bb1, bb2
|
|
|
|
bb1(%1 : $@convention(objc_method) (ProtocolA) -> ()):
|
|
%3 = apply %1(%0) : $@convention(objc_method) (ProtocolA) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
protocol TestP : AnyObject {}
|
|
|
|
class NSObject {}
|
|
|
|
class TestC {
|
|
@_hasStorage unowned final let t: @sil_unowned NSObject & TestP
|
|
init(t: NSObject & TestP)
|
|
}
|
|
|
|
// CHECK-LABEL: define {{.*}}@test_load_unowned
|
|
// CHECK: [[REF:%.*]] = load ptr, ptr
|
|
// CHECK: swift_unownedRetainStrong
|
|
// CHECK: [[EXIST0:%.*]] = insertvalue { ptr, ptr } undef, ptr [[REF]], 0
|
|
// CHECK: [[EXIST:%.*]] = insertvalue { ptr, ptr } [[EXIST0]], ptr {{.*}}, 1
|
|
// CHECK: ret { ptr, ptr } [[EXIST]]
|
|
|
|
sil @test_load_unowned : $@convention(method) (@guaranteed TestC) -> @owned NSObject & TestP {
|
|
bb0(%0 : $TestC):
|
|
%2 = ref_element_addr %0 : $TestC, #TestC.t
|
|
%3 = load_unowned %2 : $*@sil_unowned NSObject & TestP
|
|
return %3 : $NSObject & TestP
|
|
}
|
|
|
|
// CHECK-LABEL: define {{.*}}@test_load_take_unowned
|
|
// CHECK: [[REF:%.*]] = load ptr, ptr
|
|
// CHECK: swift_unownedRetainStrongAndRelease
|
|
// CHECK: [[EXIST0:%.*]] = insertvalue { ptr, ptr } undef, ptr [[REF]], 0
|
|
// CHECK: [[EXIST:%.*]] = insertvalue { ptr, ptr } [[EXIST0]], ptr {{.*}}, 1
|
|
// CHECK: ret { ptr, ptr } [[EXIST]]
|
|
|
|
sil @test_load_take_unowned : $@convention(method) (@guaranteed TestC) -> @owned NSObject & TestP {
|
|
bb0(%0 : $TestC):
|
|
%2 = ref_element_addr %0 : $TestC, #TestC.t
|
|
%3 = load_unowned [take] %2 : $*@sil_unowned NSObject & TestP
|
|
return %3 : $NSObject & TestP
|
|
}
|
|
|
|
sil_vtable TestC { }
|
|
|
|
sil_vtable NSObject { }
|