mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Type annotations for instruction operands are omitted, e.g. ``` %3 = struct $S(%1, %2) ``` Operand types are redundant anyway and were only used for sanity checking in the SIL parser. But: operand types _are_ printed if the definition of the operand value was not printed yet. This happens: * if the block with the definition appears after the block where the operand's instruction is located * if a block or instruction is printed in isolation, e.g. in a debugger The old behavior can be restored with `-Xllvm -sil-print-types`. This option is added to many existing test files which check for operand types in their check-lines.
224 lines
9.1 KiB
Swift
224 lines
9.1 KiB
Swift
|
|
// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types %s | %FileCheck %s
|
|
|
|
class A {}
|
|
class B {}
|
|
protocol P {}
|
|
protocol Q {}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @{{.*}}loadable
|
|
func loadable(readonly: A, writable: inout A,
|
|
value: B,
|
|
kp: KeyPath<A, B>,
|
|
wkp: WritableKeyPath<A, B>,
|
|
rkp: ReferenceWritableKeyPath<A, B>) {
|
|
// CHECK: [[ROOT_COPY:%.*]] = copy_value [[READONLY:%0]] :
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP:%3]]
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
|
|
// CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[GET:%.*]] = function_ref @swift_getAtKeyPath :
|
|
// CHECK: [[RESULT_TMP:%.*]] = alloc_stack $B
|
|
// CHECK: apply [[GET]]<A, B>([[RESULT_TMP]], [[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[RESULT:%.*]] = load [take] [[RESULT_TMP]]
|
|
// CHECK: destroy_value [[RESULT]]
|
|
_ = readonly[keyPath: kp]
|
|
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[WRITABLE:%1]] :
|
|
// CHECK: [[ROOT_COPY:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[KP]]
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
|
|
// CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[GET:%.*]] = function_ref @swift_getAtKeyPath :
|
|
// CHECK: [[RESULT_TMP:%.*]] = alloc_stack $B
|
|
// CHECK: apply [[GET]]<A, B>([[RESULT_TMP]], [[ROOT_TMP]], [[KP_COPY]])
|
|
// CHECK: [[RESULT:%.*]] = load [take] [[RESULT_TMP]]
|
|
// CHECK: destroy_value [[RESULT]]
|
|
_ = writable[keyPath: kp]
|
|
|
|
// CHECK: [[ROOT_COPY:%.*]] = copy_value [[READONLY]] :
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[WKP:%4]]
|
|
// CHECK: [[KP_UPCAST:%.*]] = upcast [[KP_COPY]] : $WritableKeyPath<A, B> to $KeyPath<A, B>
|
|
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
|
|
// CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
|
|
// CHECK: [[GET:%.*]] = function_ref @swift_getAtKeyPath :
|
|
// CHECK: [[RESULT_TMP:%.*]] = alloc_stack $B
|
|
// CHECK: apply [[GET]]<A, B>([[RESULT_TMP]], [[ROOT_TMP]], [[KP_UPCAST]])
|
|
// CHECK: [[RESULT:%.*]] = load [take] [[RESULT_TMP]]
|
|
// CHECK: destroy_value [[RESULT]]
|
|
_ = readonly[keyPath: wkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath
|
|
_ = writable[keyPath: wkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath
|
|
_ = readonly[keyPath: rkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath
|
|
_ = writable[keyPath: rkp]
|
|
|
|
|
|
// CHECK: [[KP_COPY:%.*]] = copy_value [[WKP]]
|
|
// CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE:%2]] : $B
|
|
// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[WRITABLE]] :
|
|
// CHECK-NEXT: [[VALUE_TEMP:%.*]] = alloc_stack $B
|
|
// CHECK-NEXT: store [[VALUE_COPY]] to [init] [[VALUE_TEMP]]
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[SET:%.*]] = function_ref @swift_setAtWritableKeyPath :
|
|
// CHECK-NEXT: apply [[SET]]<A, B>([[ACCESS]], [[KP_COPY]], [[VALUE_TEMP]])
|
|
// CHECK-NEXT: end_access [[ACCESS]]
|
|
// CHECK-NEXT: dealloc_stack [[VALUE_TEMP]]
|
|
// CHECK-NEXT: destroy_value [[KP_COPY]]
|
|
writable[keyPath: wkp] = value
|
|
|
|
// CHECK-NEXT: [[ROOT_COPY:%.*]] = copy_value [[READONLY]] :
|
|
// CHECK-NEXT: [[KP_COPY:%.*]] = copy_value [[RKP:%5]]
|
|
// CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]] : $B
|
|
// CHECK-NEXT: [[ROOT_TEMP:%.*]] = alloc_stack $A
|
|
// CHECK-NEXT: store [[ROOT_COPY]] to [init] [[ROOT_TEMP]]
|
|
// CHECK-NEXT: [[VALUE_TEMP:%.*]] = alloc_stack $B
|
|
// CHECK-NEXT: store [[VALUE_COPY]] to [init] [[VALUE_TEMP]]
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[SET:%.*]] = function_ref @swift_setAtReferenceWritableKeyPath :
|
|
// CHECK-NEXT: apply [[SET]]<A, B>([[ROOT_TEMP]], [[KP_COPY]], [[VALUE_TEMP]])
|
|
// CHECK-NEXT: dealloc_stack [[VALUE_TEMP]]
|
|
// CHECK-NEXT: destroy_addr [[ROOT_TEMP]]
|
|
// CHECK-NEXT: dealloc_stack [[ROOT_TEMP]]
|
|
// CHECK-NEXT: destroy_value [[KP_COPY]]
|
|
readonly[keyPath: rkp] = value
|
|
|
|
// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [read] [unknown] [[WRITABLE]] :
|
|
// CHECK-NEXT: [[ROOT_COPY:%.*]] = load [copy] [[ACCESS]] :
|
|
// CHECK-NEXT: end_access [[ACCESS]]
|
|
// CHECK-NEXT: [[KP_COPY:%.*]] = copy_value [[RKP:%5]]
|
|
// CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]] : $B
|
|
// CHECK-NEXT: [[ROOT_TEMP:%.*]] = alloc_stack $A
|
|
// CHECK-NEXT: store [[ROOT_COPY]] to [init] [[ROOT_TEMP]]
|
|
// CHECK-NEXT: [[VALUE_TEMP:%.*]] = alloc_stack $B
|
|
// CHECK-NEXT: store [[VALUE_COPY]] to [init] [[VALUE_TEMP]]
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: [[SET:%.*]] = function_ref @swift_setAtReferenceWritableKeyPath :
|
|
// CHECK-NEXT: apply [[SET]]<A, B>([[ROOT_TEMP]], [[KP_COPY]], [[VALUE_TEMP]])
|
|
// CHECK-NEXT: dealloc_stack [[VALUE_TEMP]]
|
|
// CHECK-NEXT: destroy_addr [[ROOT_TEMP]]
|
|
// CHECK-NEXT: dealloc_stack [[ROOT_TEMP]]
|
|
// CHECK-NEXT: destroy_value [[KP_COPY]]
|
|
writable[keyPath: rkp] = value
|
|
} // CHECK-LABEL: } // end sil function '{{.*}}loadable
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @{{.*}}addressOnly
|
|
func addressOnly(readonly: P, writable: inout P,
|
|
value: Q,
|
|
kp: KeyPath<P, Q>,
|
|
wkp: WritableKeyPath<P, Q>,
|
|
rkp: ReferenceWritableKeyPath<P, Q>) {
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = readonly[keyPath: kp]
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = writable[keyPath: kp]
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = readonly[keyPath: wkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = writable[keyPath: wkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = readonly[keyPath: rkp]
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = writable[keyPath: rkp]
|
|
|
|
// CHECK: function_ref @swift_setAtWritableKeyPath :
|
|
writable[keyPath: wkp] = value
|
|
// CHECK: function_ref @swift_setAtReferenceWritableKeyPath :
|
|
readonly[keyPath: rkp] = value
|
|
// CHECK: function_ref @swift_setAtReferenceWritableKeyPath :
|
|
writable[keyPath: rkp] = value
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @{{.*}}reabstracted
|
|
func reabstracted(readonly: @escaping () -> (),
|
|
writable: inout () -> (),
|
|
value: @escaping (A) -> B,
|
|
kp: KeyPath<() -> (), (A) -> B>,
|
|
wkp: WritableKeyPath<() -> (), (A) -> B>,
|
|
rkp: ReferenceWritableKeyPath<() -> (), (A) -> B>) {
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = readonly[keyPath: kp]
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = writable[keyPath: kp]
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = readonly[keyPath: wkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = writable[keyPath: wkp]
|
|
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = readonly[keyPath: rkp]
|
|
// CHECK: function_ref @swift_getAtKeyPath :
|
|
_ = writable[keyPath: rkp]
|
|
|
|
// CHECK: function_ref @swift_setAtWritableKeyPath :
|
|
writable[keyPath: wkp] = value
|
|
// CHECK: function_ref @swift_setAtReferenceWritableKeyPath :
|
|
readonly[keyPath: rkp] = value
|
|
// CHECK: function_ref @swift_setAtReferenceWritableKeyPath :
|
|
writable[keyPath: rkp] = value
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @{{.*}}partial
|
|
func partial<A>(valueA: A,
|
|
valueB: Int,
|
|
pkpA: PartialKeyPath<A>,
|
|
pkpB: PartialKeyPath<Int>,
|
|
akp: AnyKeyPath) {
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @swift_getAtAnyKeyPath :
|
|
// CHECK: apply [[PROJECT]]<A>
|
|
_ = valueA[keyPath: akp]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @swift_getAtPartialKeyPath :
|
|
// CHECK: apply [[PROJECT]]<A>
|
|
_ = valueA[keyPath: pkpA]
|
|
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @swift_getAtAnyKeyPath :
|
|
// CHECK: apply [[PROJECT]]<Int>
|
|
_ = valueB[keyPath: akp]
|
|
// CHECK: [[PROJECT:%.*]] = function_ref @swift_getAtPartialKeyPath :
|
|
// CHECK: apply [[PROJECT]]<Int>
|
|
_ = valueB[keyPath: pkpB]
|
|
}
|
|
|
|
extension Int {
|
|
var b: Int { get { return 0 } set { } }
|
|
var u: Int { get { return 0 } set { } }
|
|
var tt: Int { get { return 0 } set { } }
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @{{.*}}writebackNesting
|
|
func writebackNesting(x: inout Int,
|
|
y: WritableKeyPath<Int, Int>,
|
|
z: WritableKeyPath<Int, Int>,
|
|
w: Int) -> Int {
|
|
// -- get 'b'
|
|
// CHECK: function_ref @$sSi19keypath_applicationE1bSivg
|
|
// -- apply keypath y
|
|
// CHECK: [[PROJECT_FN:%.*]] = function_ref @swift_modifyAtWritableKeyPath : $@yield_once @convention(thin) <τ_0_0, τ_0_1> (@inout τ_0_0, @guaranteed WritableKeyPath<τ_0_0, τ_0_1>) -> @yields @inout τ_0_1
|
|
// CHECK: ([[Y_ADDR:%.*]], [[Y_TOKEN:%.*]]) = begin_apply [[PROJECT_FN]]<Int, Int>
|
|
// -- get 'u'
|
|
// CHECK: function_ref @$sSi19keypath_applicationE1uSivg
|
|
// -- apply keypath z
|
|
// CHECK: [[PROJECT_FN:%.*]] = function_ref @swift_modifyAtWritableKeyPath : $@yield_once @convention(thin) <τ_0_0, τ_0_1> (@inout τ_0_0, @guaranteed WritableKeyPath<τ_0_0, τ_0_1>) -> @yields @inout τ_0_1
|
|
// CHECK: ([[Z_ADDR:%.*]], [[Z_TOKEN:%.*]]) = begin_apply [[PROJECT_FN]]<Int, Int>
|
|
|
|
// -- set 'tt'
|
|
// CHECK: function_ref @$sSi19keypath_applicationE2ttSivs
|
|
// -- destroy owner for keypath projection z
|
|
// CHECK: end_apply [[Z_TOKEN]]
|
|
// -- set 'u'
|
|
// CHECK: function_ref @$sSi19keypath_applicationE1uSivs
|
|
// -- destroy owner for keypath projection y
|
|
// CHECK: end_apply [[Y_TOKEN]]
|
|
// -- set 'b'
|
|
// CHECK: function_ref @$sSi19keypath_applicationE1bSivs
|
|
|
|
x.b[keyPath: y].u[keyPath: z].tt = w
|
|
}
|