mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
223 lines
12 KiB
Swift
223 lines
12 KiB
Swift
// RUN: %target-swift-frontend -enable-experimental-keypaths -emit-silgen %s | %FileCheck %s
|
|
|
|
class A {}
|
|
class B {}
|
|
protocol P {}
|
|
protocol Q {}
|
|
|
|
// CHECK-LABEL: sil hidden @{{.*}}loadable
|
|
func loadable(readonly: A, writable: inout A,
|
|
value: B,
|
|
kp: KeyPath<A, B>,
|
|
wkp: WritableKeyPath<A, B>,
|
|
rkp: ReferenceWritableKeyPath<A, B>) {
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
|
|
// CHECK: [[ROOT_BORROW:%.*]] = begin_borrow %0
|
|
// CHECK: [[ROOT_COPY:%.*]] = copy_value [[ROOT_BORROW]]
|
|
// CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %3
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
|
|
// CHECK: [[RESULT_TMP:%.*]] = alloc_stack $B
|
|
// CHECK: apply [[PROJECT]]<A, B>([[RESULT_TMP]], [[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[RESULT:%.*]] = load [take] [[RESULT_TMP]]
|
|
// CHECK: destroy_value [[RESULT]]
|
|
_ = readonly[keyPath: kp]
|
|
_ = writable[keyPath: kp]
|
|
_ = readonly[keyPath: wkp]
|
|
|
|
// CHECK: [[TEMP:%.*]] = mark_uninitialized
|
|
// CHECK: [[ROOT_ACCESS:%.*]] = begin_access [read] [unknown] %1 : $*A
|
|
// CHECK: [[ROOT_RAW_PTR:%.*]] = address_to_pointer [[ROOT_ACCESS]]
|
|
// CHECK: [[ROOT_PTR:%.*]] = struct $UnsafeMutablePointer<A> ([[ROOT_RAW_PTR]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %4
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
|
|
// CHECK: [[PROJECTED:%.*]] = apply [[PROJECT]]<A, B>([[ROOT_PTR]], [[KP_COPY]])
|
|
// CHECK: [[PROJECTED_BORROW:%.*]] = begin_borrow [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_PTR:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER_B:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER:%.*]] = copy_value [[PROJECTED_OWNER_B]]
|
|
// CHECK: destroy_value [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_RAW_PTR:%.*]] = struct_extract [[PROJECTED_PTR]]
|
|
// CHECK: [[PROJECTED_ADDR:%.*]] = pointer_to_address [[PROJECTED_RAW_PTR]]
|
|
// CHECK: [[PROJECTED_DEP:%.*]] = mark_dependence [[PROJECTED_ADDR]] : $*B on [[PROJECTED_OWNER]]
|
|
// CHECK: [[COPY_TMP:%.*]] = load [copy] [[PROJECTED_DEP]] : $*B
|
|
// CHECK: assign [[COPY_TMP]] to [[TEMP]] : $*B
|
|
// CHECK: destroy_value [[PROJECTED_OWNER]]
|
|
_ = writable[keyPath: wkp]
|
|
|
|
// CHECK: [[TEMP:%.*]] = mark_uninitialized
|
|
// CHECK: [[ROOT_BORROW:%.*]] = begin_borrow %0
|
|
// CHECK: [[ROOT_COPY:%.*]] = copy_value [[ROOT_BORROW]]
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
|
|
// CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %5
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
|
|
// CHECK: [[PROJECTED:%.*]] = apply [[PROJECT]]<A, B>([[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[PROJECTED_BORROW:%.*]] = begin_borrow [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_PTR:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER_B:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER:%.*]] = copy_value [[PROJECTED_OWNER_B]]
|
|
// CHECK: destroy_value [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_RAW_PTR:%.*]] = struct_extract [[PROJECTED_PTR]]
|
|
// CHECK: [[PROJECTED_ADDR:%.*]] = pointer_to_address [[PROJECTED_RAW_PTR]]
|
|
// CHECK: [[PROJECTED_DEP:%.*]] = mark_dependence [[PROJECTED_ADDR]] : $*B on [[PROJECTED_OWNER]]
|
|
// CHECK: [[COPY_TMP:%.*]] = load [copy] [[PROJECTED_DEP]] : $*B
|
|
// CHECK: assign [[COPY_TMP]] to [[TEMP]] : $*B
|
|
// CHECK: destroy_value [[PROJECTED_OWNER]]
|
|
_ = readonly[keyPath: rkp]
|
|
_ = writable[keyPath: rkp]
|
|
|
|
writable[keyPath: wkp] = value
|
|
readonly[keyPath: rkp] = value
|
|
writable[keyPath: rkp] = value
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden @{{.*}}addressOnly
|
|
func addressOnly(readonly: P, writable: inout P,
|
|
value: Q,
|
|
kp: KeyPath<P, Q>,
|
|
wkp: WritableKeyPath<P, Q>,
|
|
rkp: ReferenceWritableKeyPath<P, Q>) {
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $P
|
|
// CHECK: copy_addr %0 to [initialization] [[ROOT_TMP]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %3
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
|
|
// CHECK: [[RESULT:%.*]] = alloc_stack $Q
|
|
// CHECK: apply [[PROJECT]]<P, Q>([[RESULT]], [[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: destroy_addr [[RESULT]]
|
|
_ = readonly[keyPath: kp]
|
|
_ = writable[keyPath: kp]
|
|
_ = readonly[keyPath: wkp]
|
|
|
|
// CHECK: [[TEMP:%.*]] = mark_uninitialized
|
|
// CHECK: [[ROOT_ACCESS:%.*]] = begin_access [read] [unknown] %1 : $*P
|
|
// CHECK: [[ROOT_RAW_PTR:%.*]] = address_to_pointer [[ROOT_ACCESS]]
|
|
// CHECK: [[ROOT_PTR:%.*]] = struct $UnsafeMutablePointer<P> ([[ROOT_RAW_PTR]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %4
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
|
|
// CHECK: [[PROJECTED:%.*]] = apply [[PROJECT]]<P, Q>([[ROOT_PTR]], [[KP_COPY]])
|
|
// CHECK: [[PROJECTED_BORROW:%.*]] = begin_borrow [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_PTR:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER_B:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER:%.*]] = copy_value [[PROJECTED_OWNER_B]]
|
|
// CHECK: destroy_value [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_RAW_PTR:%.*]] = struct_extract [[PROJECTED_PTR]]
|
|
// CHECK: [[PROJECTED_ADDR:%.*]] = pointer_to_address [[PROJECTED_RAW_PTR]]
|
|
// CHECK: [[PROJECTED_DEP:%.*]] = mark_dependence [[PROJECTED_ADDR]] : $*Q on [[PROJECTED_OWNER]]
|
|
// CHECK: copy_addr [[PROJECTED_DEP]] to [initialization] [[CPY_TMP:%.*]] : $*Q
|
|
// CHECK: copy_addr [take] [[CPY_TMP]] to [[TEMP]] : $*Q
|
|
// CHECK: destroy_value [[PROJECTED_OWNER]]
|
|
_ = writable[keyPath: wkp]
|
|
|
|
// CHECK: [[TEMP:%.*]] = mark_uninitialized
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $P
|
|
// CHECK: copy_addr %0 to [initialization] [[ROOT_TMP]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %5
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
|
|
// CHECK: [[PROJECTED:%.*]] = apply [[PROJECT]]<P, Q>([[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[PROJECTED_BORROW:%.*]] = begin_borrow [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_PTR:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER_B:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER:%.*]] = copy_value [[PROJECTED_OWNER_B]]
|
|
// CHECK: destroy_value [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_RAW_PTR:%.*]] = struct_extract [[PROJECTED_PTR]]
|
|
// CHECK: [[PROJECTED_ADDR:%.*]] = pointer_to_address [[PROJECTED_RAW_PTR]]
|
|
// CHECK: [[PROJECTED_DEP:%.*]] = mark_dependence [[PROJECTED_ADDR]] : $*Q on [[PROJECTED_OWNER]]
|
|
// CHECK: copy_addr [[PROJECTED_DEP]] to [initialization] [[CPY_TMP:%.*]] : $*Q
|
|
// CHECK: copy_addr [take] [[CPY_TMP]] to [[TEMP]] : $*Q
|
|
// CHECK: destroy_value [[PROJECTED_OWNER]]
|
|
_ = readonly[keyPath: rkp]
|
|
_ = writable[keyPath: rkp]
|
|
|
|
writable[keyPath: wkp] = value
|
|
readonly[keyPath: rkp] = value
|
|
writable[keyPath: rkp] = value
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden @{{.*}}reabstracted
|
|
func reabstracted(readonly: @escaping () -> (),
|
|
writable: inout () -> (),
|
|
value: @escaping (A) -> B,
|
|
kp: KeyPath<() -> (), (A) -> B>,
|
|
wkp: WritableKeyPath<() -> (), (A) -> B>,
|
|
rkp: ReferenceWritableKeyPath<() -> (), (A) -> B>) {
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $@callee_owned (@in ()) -> @out ()
|
|
// CHECK: [[ROOT_BORROW:%.*]] = begin_borrow %0
|
|
// CHECK: [[ROOT_COPY:%.*]] = copy_value [[ROOT_BORROW]]
|
|
// CHECK: [[ROOT_ORIG:%.*]] = partial_apply {{.*}}([[ROOT_COPY]])
|
|
// CHECK: store [[ROOT_ORIG]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %3
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
|
|
// CHECK: [[RESULT_TMP:%.*]] = alloc_stack $@callee_owned (@in A) -> @out B
|
|
// CHECK: apply [[PROJECT]]<() -> (), (A) -> B>([[RESULT_TMP]], [[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[RESULT_ORIG:%.*]] = load [take] [[RESULT_TMP]]
|
|
// CHECK: [[RESULT_SUBST:%.*]] = partial_apply {{.*}}([[RESULT_ORIG]])
|
|
// CHECK: destroy_value [[RESULT_SUBST]]
|
|
_ = readonly[keyPath: kp]
|
|
_ = writable[keyPath: kp]
|
|
_ = readonly[keyPath: wkp]
|
|
|
|
// CHECK: [[TEMP_SUBST:%.*]] = mark_uninitialized {{.*}} : $*@callee_owned (@owned A) -> @owned B
|
|
// CHECK: [[ROOT_ACCESS:%.*]] = begin_access [read] [unknown] %1 : $*@callee_owned () -> ()
|
|
// CHECK: [[ROOT_ORIG_TMP:%.*]] = alloc_stack $@callee_owned (@in ()) -> @out ()
|
|
// CHECK: [[ROOT_SUBST:%.*]] = load [copy] [[ROOT_ACCESS]]
|
|
// CHECK: [[ROOT_ORIG:%.*]] = partial_apply {{.*}}([[ROOT_SUBST]])
|
|
// CHECK: store [[ROOT_ORIG]] to [init] [[ROOT_ORIG_TMP]]
|
|
// CHECK: [[ROOT_RAW_PTR:%.*]] = address_to_pointer [[ROOT_ORIG_TMP]]
|
|
// CHECK: [[ROOT_PTR:%.*]] = struct $UnsafeMutablePointer<() -> ()> ([[ROOT_RAW_PTR]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %4
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
|
|
// CHECK: [[PROJECTED:%.*]] = apply [[PROJECT]]<() -> (), (A) -> B>([[ROOT_PTR]], [[KP_COPY]])
|
|
// CHECK: [[PROJECTED_BORROW:%.*]] = begin_borrow [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_PTR:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER_B:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER:%.*]] = copy_value [[PROJECTED_OWNER_B]]
|
|
// CHECK: destroy_value [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_RAW_PTR:%.*]] = struct_extract [[PROJECTED_PTR]]
|
|
// CHECK: [[PROJECTED_ORIG_ADDR:%.*]] = pointer_to_address [[PROJECTED_RAW_PTR]] {{.*}} to [strict] $*@callee_owned (@in A) -> @out B
|
|
// CHECK: [[PROJECTED_DEP:%.*]] = mark_dependence [[PROJECTED_ORIG_ADDR]] : $*@callee_owned (@in A) -> @out B on [[PROJECTED_OWNER]]
|
|
// CHECK: [[PROJECTED_ORIG:%.*]] = load [copy] [[PROJECTED_DEP]]
|
|
// CHECK: [[PROJECTED_SUBST:%.*]] = partial_apply {{.*}}([[PROJECTED_ORIG]])
|
|
// CHECK: destroy_addr [[ROOT_ORIG_TMP]]
|
|
// CHECK: assign [[PROJECTED_SUBST]] to [[TEMP_SUBST]]
|
|
// CHECK: destroy_value [[PROJECTED_OWNER]]
|
|
_ = writable[keyPath: wkp]
|
|
|
|
// CHECK: [[TEMP:%.*]] = mark_uninitialized
|
|
// CHECK: [[ROOT_BORROW:%.*]] = begin_borrow %0
|
|
// CHECK: [[ROOT_COPY_SUBST:%.*]] = copy_value [[ROOT_BORROW]]
|
|
// CHECK: [[ROOT_COPY_ORIG:%.*]] = partial_apply {{.*}}([[ROOT_COPY_SUBST]])
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $@callee_owned (@in ()) -> @out ()
|
|
// CHECK: store [[ROOT_COPY_ORIG]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[KP_BORROW:%.*]] = begin_borrow %5
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP_BORROW]]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
|
|
// CHECK: [[PROJECTED:%.*]] = apply [[PROJECT]]<() -> (), (A) -> B>([[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[PROJECTED_BORROW:%.*]] = begin_borrow [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_PTR:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER_B:%.*]] = tuple_extract [[PROJECTED_BORROW]]
|
|
// CHECK: [[PROJECTED_OWNER:%.*]] = copy_value [[PROJECTED_OWNER_B]]
|
|
// CHECK: destroy_value [[PROJECTED]]
|
|
// CHECK: [[PROJECTED_RAW_PTR:%.*]] = struct_extract [[PROJECTED_PTR]]
|
|
// CHECK: [[PROJECTED_ADDR_ORIG:%.*]] = pointer_to_address [[PROJECTED_RAW_PTR]] {{.*}} to [strict] $*@callee_owned (@in A) -> @out B
|
|
// CHECK: [[PROJECTED_DEP:%.*]] = mark_dependence [[PROJECTED_ADDR_ORIG]] : $*@callee_owned (@in A) -> @out B on [[PROJECTED_OWNER]]
|
|
// CHECK: [[PROJECTED_ORIG:%.*]] = load [copy] [[PROJECTED_DEP]]
|
|
// CHECK: [[PROJECTED_SUBST:%.*]] = partial_apply {{.*}}([[PROJECTED_ORIG]])
|
|
// CHECK: assign [[PROJECTED_SUBST]] to [[TEMP]]
|
|
// CHECK: destroy_value [[PROJECTED_OWNER]]
|
|
_ = readonly[keyPath: rkp]
|
|
_ = writable[keyPath: rkp]
|
|
|
|
writable[keyPath: wkp] = value
|
|
readonly[keyPath: rkp] = value
|
|
writable[keyPath: rkp] = value
|
|
}
|