blob: 4cb40742c154b2c69037f151e2e30ab32026f21c [file] [log] [blame]
// RUN: rm -rf %t && mkdir -p %t
// -- Convert <i32 0x...> constants to decimal constants that LLVM will print
// RUN: %utils/chex.py < %s > %t/keypaths.sil
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %t/keypaths.sil --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-os
sil_stage canonical
import Swift
struct S {
var x: Int
let y: String
var z: C
var reabstracted: () -> ()
}
class C {
final var x: Int
final let y: String
final var z: S
var w: Int { get set }
init()
}
sil_vtable C {}
// CHECK: %TSi = type <{ [[WORD:i.*]] }>
// -- %a: S.x
// CHECK: [[KP_A:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 4
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- offset of S.x
// CHECK-SAME: i32 0 }>
// -- %b: S.y
// CHECK: [[KP_B:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 4
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- offset of S.y
// CHECK-32-SAME: i32 4 }>
// CHECK-64-SAME: i32 8 }>
// -- %c: S.z
// CHECK: [[KP_C:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 4
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- offset of S.z
// CHECK-32-SAME: i32 16 }>
// CHECK-64-SAME: i32 32 }>
// -- %d: C.x
// CHECK: [[KP_D:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 4
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.x
// CHECK-32-SAME: <i32 0x4000_000c> }>
// CHECK-64-SAME: <i32 0x4000_0010> }>
// -- %e: C.y
// CHECK: [[KP_E:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 4
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.y
// CHECK-32-SAME: <i32 0x4000_0010> }>
// CHECK-64-SAME: <i32 0x4000_0018> }>
// -- %f: C.z
// CHECK: [[KP_F:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 4
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.z
// CHECK-32-SAME: <i32 0x4000_001c> }>
// CHECK-64-SAME: <i32 0x4000_0030> }>
// -- %g: S.z.x
// CHECK: [[KP_G:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 12
// CHECK-32-SAME: <i32 0x8000_000c>,
// -- instantiable in-line, size 20
// CHECK-64-SAME: <i32 0x8000_0014>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- offset of S.z
// CHECK-32-SAME: i32 16,
// CHECK-64-SAME: i32 32,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK: %swift.type* (i8*)*
// -- 0x4000_0000 (class) + offset of C.x
// CHECK-32-SAME: <i32 0x4000_000c> }>
// CHECK-64-SAME: <i32 0x4000_0010> }>
// -- %h: C.z.x
// CHECK: [[KP_H:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 12
// CHECK-32-SAME: <i32 0x8000_000c>,
// -- instantiable in-line, size 20
// CHECK-64-SAME: <i32 0x8000_0014>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.z
// CHECK-32-SAME: <i32 0x4000_001c>,
// CHECK-64-SAME: <i32 0x4000_0030>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK: %swift.type* (i8*)*
// -- offset of S.x
// CHECK-SAME: i32 0 }>
// -- %k: computed
// CHECK: [[KP_K:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 24
// CHECK-64-SAME: <i32 0x8000_0018>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- instantiable in-line, size 12
// CHECK-32-SAME: <i32 0x8000_000c>,
// -- computed, get-only, identified by function pointer, no args
// CHECK-SAME: <i32 0x2000_0000>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK-SAME: void ()* @k_id,
// CHECK-SAME: void (%TSi*, %T8keypaths1SV*)* @k_get }>
// -- %l: computed
// CHECK: [[KP_L:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 32
// CHECK-64-SAME: <i32 0x8000_0020>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- instantiable in-line, size 16
// CHECK-32-SAME: <i32 0x8000_0010>,
// -- computed, settable, nonmutating, identified by vtable, no args
// CHECK-SAME: <i32 0x2a00_0000>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK-SAME: [[WORD]]
// CHECK-SAME: void (%TSi*, %T8keypaths1CC**)* @l_get,
// CHECK-SAME: void (%TSi*, %T8keypaths1CC**)* @l_set }>
// -- %m: computed
// CHECK: [[KP_M:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)*
// CHECK-SAME: %swift.type* (i8*)*
// -- instantiable in-line, size 32
// CHECK-64-SAME: <i32 0x8000_0020>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- instantiable in-line, size 16
// CHECK-32-SAME: <i32 0x8000_0010>,
// -- computed, settable, nonmutating, identified by property offset, no args
// CHECK-SAME: <i32 0x3c00_0000>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK-SAME: [[WORD]]
// CHECK-SAME: void (%swift.function*, %T8keypaths1SV*)* @m_get,
// CHECK-SAME: void (%swift.function*, %T8keypaths1SV*)* @m_set }>
// -- %i: Gen<A>.x
// CHECK: [[KP_I:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)* [[I_GET_GEN_A_A:@[a-z_.0-9]+]],
// CHECK-SAME: %swift.type* (i8*)* [[I_GET_A:@[a-z_.0-9]+]],
// -- size 8
// CHECK-SAME: i32 8,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- struct with runtime-resolved offset
// CHECK-SAME: <i32 0x1ffffffe>,
// CHECK-32-SAME: i32 12 }>
// CHECK-64-SAME: i32 24 }>
// -- %j: Gen<A>.y
// CHECK: [[KP_J:@keypath.*]] = private global <{ {{.*}} }> <{
// CHECK-SAME: [[WORD]] 0,
// CHECK-SAME: %swift.type* (i8*)* [[J_GET_GEN_A_A:@[a-z_.0-9]+]],
// CHECK-SAME: %swift.type* (i8*)* [[J_GET_A:@[a-z_.0-9]+]],
// -- size 8
// CHECK-SAME: i32 8,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- struct with runtime-resolved offset
// CHECK-SAME: <i32 0x1ffffffe>,
// CHECK-32-SAME: i32 16 }>
// CHECK-64-SAME: i32 32 }>
// CHECK-LABEL: define{{( protected)?}} swiftcc void @stored_property_fixed_offsets()
sil @stored_property_fixed_offsets : $@convention(thin) () -> () {
entry:
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_A]] to i8*), i8* undef)
%a = keypath $KeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_B]] to i8*), i8* undef)
%b = keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_C]] to i8*), i8* undef)
%c = keypath $KeyPath<S, C>, (root $S; stored_property #S.z : $C)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_D]] to i8*), i8* undef)
%d = keypath $KeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_E]] to i8*), i8* undef)
%e = keypath $KeyPath<C, String>, (root $C; stored_property #C.y : $String)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_F]] to i8*), i8* undef)
%f = keypath $KeyPath<C, S>, (root $C; stored_property #C.z : $S)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_G]] to i8*), i8* undef)
%g = keypath $KeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_H]] to i8*), i8* undef)
%h = keypath $KeyPath<C, Int>, (root $C; stored_property #C.z : $S; stored_property #S.x : $Int)
%k = keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @k_id : $@convention(thin) () -> (), getter @k_get : $@convention(thin) (@in S) -> @out Int)
%l = keypath $KeyPath<C, Int>, (root $C; settable_property $Int, id #C.w!getter.1, getter @l_get : $@convention(thin) (@in C) -> @out Int, setter @l_set : $@convention(thin) (@in Int, @in C) -> ())
%m = keypath $KeyPath<S, () -> ()>, (root $S; settable_property $() -> (), id ##S.reabstracted, getter @m_get : $@convention(thin) (@in S) -> @out @callee_owned (@in ()) -> @out (), setter @m_set : $@convention(thin) (@in @callee_owned (@in ()) -> @out (), @inout S) -> ())
return undef : $()
}
sil @k_id : $@convention(thin) () -> ()
sil @k_get : $@convention(thin) (@in S) -> @out Int
sil @l_get : $@convention(thin) (@in C) -> @out Int
sil @l_set : $@convention(thin) (@in Int, @in C) -> ()
sil @m_get : $@convention(thin) (@in S) -> @out @callee_owned (@in ()) -> @out ()
sil @m_set : $@convention(thin) (@in @callee_owned (@in ()) -> @out (), @inout S) -> ()
struct Gen<T, U> {
var x: T
var y: U
}
struct Foo<T> {
var foo: T
}
// CHECK-LABEL: define{{( protected)?}} swiftcc void @stored_property_generics(%swift.type* %T, %swift.type* %U)
sil @stored_property_generics : $@convention(thin) <T, U> () -> () {
entry:
// CHECK: [[PTR:%.*]] = bitcast [1 x %swift.type*]* [[ARGS:%.*]] to
// CHECK: store %swift.type* %T, %swift.type** [[PTR]]
// CHECK: [[ARGS_I8:%.*]] = bitcast [1 x %swift.type*]* [[ARGS]] to
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_I]] to i8*), i8* [[ARGS_I8]])
%i = keypath $KeyPath<Gen<T,T>, T>, <A> (root $Gen<A, A>; stored_property #Gen.x : $A) <T>
// CHECK: [[PTR:%.*]] = bitcast [1 x %swift.type*]* [[ARGS:%.*]] to
// CHECK: store %swift.type* %U, %swift.type** [[PTR]]
// CHECK: [[ARGS_I8:%.*]] = bitcast [1 x %swift.type*]* [[ARGS]] to
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_J]] to i8*), i8* [[ARGS_I8]])
%j = keypath $KeyPath<Gen<U,U>, U>, <A> (root $Gen<A, A>; stored_property #Gen.y : $A) <U>
// CHECK: [[PTR:%.*]] = bitcast [1 x %swift.type*]* [[ARGS:%.*]] to
// CHECK: [[FOO_T:%.*]] = call %swift.type* @_T08keypaths3FooVMa(%swift.type* %T)
// CHECK: store %swift.type* [[FOO_T]], %swift.type** [[PTR]]
// CHECK: [[ARGS_I8:%.*]] = bitcast [1 x %swift.type*]* [[ARGS]] to
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_I]] to i8*), i8* [[ARGS_I8]])
%i2 = keypath $KeyPath<Gen<Foo<T>,Foo<T>>, Foo<T>>, <A> (root $Gen<A, A>; stored_property #Gen.x : $A) <Foo<T>>
return undef : $()
}
// CHECK: define private %swift.type* [[I_GET_GEN_A_A]](i8*)
// CHECK: [[BUF:%.*]] = bitcast i8* %0
// CHECK: [[A:%.*]] = load %swift.type*, %swift.type** [[BUF]]
// CHECK: [[GEN:%.*]] = call %swift.type* @_T08keypaths3GenVMa(%swift.type* [[A]], %swift.type* [[A]])
// CHECK: ret %swift.type* [[GEN]]
// CHECK: define private %swift.type* [[I_GET_A]](i8*)
// CHECK: [[BUF:%.*]] = bitcast i8* %0
// CHECK: [[A:%.*]] = load %swift.type*, %swift.type** [[BUF]]
// CHECK: ret %swift.type* [[A]]
// CHECK-LABEL: define{{( protected)?}} swiftcc void @computed_property_generics
sil @computed_property_generics : $@convention(thin) <T, U> () -> () {
entry:
%n = keypath $WritableKeyPath<T, U>, <UUU, TTT> (root $TTT; settable_property $UUU, id @n_get : $@convention(thin) <UU, TT> (@in TT) -> @out UU, getter @n_get : $@convention(thin) <UU, TT> (@in TT) -> @out UU, setter @n_set : $@convention(thin) <UU, TT> (@in UU, @in TT) -> ()) <U, T>
return undef : $()
}
sil @n_get : $@convention(thin) <UU, TT> (@in TT) -> @out UU
sil @n_set : $@convention(thin) <UU, TT> (@in UU, @in TT) -> ()