mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
608 lines
27 KiB
Plaintext
608 lines
27 KiB
Plaintext
|
|
// RUN: %empty-directory(%t)
|
|
// -- Convert <i32 0x...> constants to decimal constants that LLVM will print
|
|
// RUN: %{python} %utils/chex.py < %s > %t/keypaths.sil
|
|
// RUN: %target-swift-frontend -module-name keypaths -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
|
|
|
|
public struct S: Hashable {
|
|
public var x: Int
|
|
public let y: String
|
|
public var z: C
|
|
public var reabstracted: () -> ()
|
|
|
|
public func hash(into hasher: inout Hasher)
|
|
public static func ==(_: S, _: S) -> Bool
|
|
}
|
|
public class C: Hashable {
|
|
public final var x: Int
|
|
public final let y: String
|
|
public final var z: S
|
|
public var w: Int { get set }
|
|
|
|
public init()
|
|
|
|
public func hash(into hasher: inout Hasher)
|
|
public static func ==(_: C, _: C) -> Bool
|
|
}
|
|
public class GC<T> {
|
|
public final var x: T
|
|
}
|
|
|
|
public struct G<T> {
|
|
public var x: T { get set }
|
|
public subscript<U: Hashable>(x: U) -> T { get set }
|
|
}
|
|
|
|
public class C1: C { }
|
|
public class C2: C1 {
|
|
public var reabstracted: () -> ()
|
|
}
|
|
|
|
public struct T {
|
|
public var a: (Int, String)
|
|
public let b: (f: String, g: Int)
|
|
}
|
|
|
|
public struct TG<T, U, V> {
|
|
public var a: (T, U, V)
|
|
}
|
|
|
|
typealias TGA<T, U> = (a: T, b: U)
|
|
|
|
sil_vtable C {}
|
|
sil_vtable C1 {}
|
|
sil_vtable C2 {}
|
|
|
|
// CHECK: %TSi = type <{ [[WORD:i.*]] }>
|
|
|
|
// -- %a: S.x
|
|
// CHECK: [[KP_A:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic{{.*}}8keypaths1SV"
|
|
// CHECK-SAME: @"symbolic Si
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- offset of S.x, mutable
|
|
// CHECK-SAME: <i32 0x0180_0000> }>
|
|
|
|
// -- %b: S.y
|
|
// CHECK: [[KP_B:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic{{.*}}8keypaths1SV
|
|
// CHECK-SAME: @"symbolic SS
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- offset of S.y, immutable
|
|
// CHECK-32-SAME: <i32 0x0100_0004> }>
|
|
// CHECK-64-SAME: <i32 0x0100_0008> }>
|
|
|
|
// -- %c: S.z
|
|
// CHECK: [[KP_C:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic{{.*}}8keypaths1SV
|
|
// CHECK-SAME: @"symbolic{{.*}}8keypaths1CC
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- offset of S.z, mutable
|
|
// CHECK-32-SAME: <i32 0x0180_0010> }>
|
|
// CHECK-64-SAME: <i32 0x0180_0018> }>
|
|
|
|
// -- %d: C.x
|
|
// CHECK: [[KP_D:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- 0x0300_0000 (class) + mutable + offset of C.x
|
|
// CHECK-32-SAME: <i32 0x0380_0008> }>
|
|
// CHECK-64-SAME: <i32 0x0380_0010> }>
|
|
|
|
// -- %d1: C1.x
|
|
// CHECK: [[KP_D1:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- 0x0300_0000 (class) + mutable + offset of C.x
|
|
// CHECK-32-SAME: <i32 0x0380_0008> }>
|
|
// CHECK-64-SAME: <i32 0x0380_0010> }>
|
|
|
|
// -- %e: C.y
|
|
// CHECK: [[KP_E:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- 0x0300_0000 (class) + immutable + offset of C.y
|
|
// CHECK-32-SAME: <i32 0x0300_000c> }>
|
|
// CHECK-64-SAME: <i32 0x0300_0018> }>
|
|
|
|
// -- %f: C.z
|
|
// CHECK: [[KP_F:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 4
|
|
// CHECK-SAME: <i32 0x8000_0004>,
|
|
// -- 0x0300_0000 (class) + mutable offset of C.z
|
|
// CHECK-32-SAME: <i32 0x0380_0018> }>
|
|
// CHECK-64-SAME: <i32 0x0380_0028> }>
|
|
|
|
// -- %g: S.z.x
|
|
// CHECK: [[KP_G:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 12
|
|
// CHECK-SAME: <i32 0x8000_000c>,
|
|
// -- offset of S.z
|
|
// CHECK-32-SAME: <i32 0x0180_0010>,
|
|
// CHECK-64-SAME: <i32 0x0180_0018>,
|
|
// CHECK: @"symbolic
|
|
// -- 0x0300_0000 (class) + offset of C.x
|
|
// CHECK-32-SAME: <i32 0x0380_0008> }>
|
|
// CHECK-64-SAME: <i32 0x0380_0010> }>
|
|
|
|
// -- %h: C.z.x
|
|
// CHECK: [[KP_H:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: <i32 0x8000_000c>,
|
|
// -- 0x0300_0000 (class) + offset of C.z
|
|
// CHECK-32-SAME: <i32 0x0380_0018>,
|
|
// CHECK-64-SAME: <i32 0x0380_0028>,
|
|
// CHECK: @"symbolic
|
|
// -- offset of S.x
|
|
// CHECK-SAME: <i32 0x0180_0000> }>
|
|
|
|
// -- %k: computed
|
|
// CHECK: [[KP_K:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 12
|
|
// CHECK-SAME: <i32 0x8000_000c>,
|
|
// -- computed, get-only, identified by (indirected) function pointer, no args
|
|
// CHECK-SAME: <i32 0x0200_0002>,
|
|
// CHECK-SAME: @{{got.|"\\01__imp__?}}k_id
|
|
// CHECK-SAME: ptr {{.*}}@k_get{{.*}}
|
|
|
|
// -- %l: computed
|
|
// CHECK: [[KP_L:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 16
|
|
// CHECK-SAME: <i32 0x8000_0010>,
|
|
// -- computed, settable, nonmutating, identified by direct pointer, no args
|
|
// CHECK-SAME: <i32 0x0240_0000>,
|
|
// CHECK-SAME: @"$s8keypaths1CCMn"
|
|
// CHECK-SAME: ptr @l_get
|
|
// CHECK-SAME: ptr @l_set{{.*}}
|
|
|
|
// -- %m: computed
|
|
// CHECK: [[KP_M:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 16
|
|
// CHECK-SAME: <i32 0x8000_0010>,
|
|
// -- computed, settable, nonmutating, identified by property offset, no args
|
|
// CHECK-SAME: <i32 0x02e0_0000>,
|
|
// CHECK-SAME: [[WORD]]
|
|
// CHECK-SAME: ptr {{.*}}@m_get
|
|
// CHECK-SAME: ptr {{.*}}@m_set{{.*}}
|
|
|
|
// -- %m2: reabstracted
|
|
// Note: the contents here aren't interesting. The test triggered infinite
|
|
// looping in the compiler at one point.
|
|
// CHECK: [[KP_M:@keypath.*]] = private global <{ {{.*}} }> <{
|
|
|
|
// -- %t0: T.a.0
|
|
// CHECK: [[KP_T0:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 12
|
|
// CHECK-SAME: <i32 0x8000_000c>,
|
|
// -- offset of T.a, mutable
|
|
// CHECK-SAME: <i32 0x0180_0000>,
|
|
// CHECK: @"symbolic
|
|
// -- tuple element #0 of T.a
|
|
// CHECK-SAME: <i32 0x0180_0000> }>
|
|
|
|
// -- %t1: T.b.g
|
|
// CHECK: [[KP_T1:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @keypath_once
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- instantiable in-line, size 12
|
|
// CHECK-SAME: <i32 0x8000_000c>,
|
|
// -- offset of T.b
|
|
// CHECK-32-SAME: <i32 0x0100_0010>,
|
|
// CHECK-64-SAME: <i32 0x0100_0018>,
|
|
// CHECK: @"symbolic
|
|
// -- tuple element #1 of T.b
|
|
// CHECK-32-SAME: <i32 0x0180_000c> }>
|
|
// CHECK-64-SAME: <i32 0x0180_0010> }>
|
|
|
|
// -- %i: Gen<A>.x
|
|
// CHECK: [[KP_I:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: i32 0
|
|
// CHECK-SAME: @"generic environment l"
|
|
// CHECK-SAME: @"symbolic{{[^"]*}}8keypaths3GenV{{[^"]*}}"
|
|
// CHECK-SAME: @"symbolic x"
|
|
// -- size 8
|
|
// CHECK-SAME: i32 8,
|
|
// -- struct with runtime-resolved offset, mutable
|
|
// CHECK-SAME: <i32 0x01fffffe>,
|
|
// CHECK-32-SAME: i32 16 }>
|
|
// CHECK-64-SAME: i32 32 }>
|
|
|
|
// -- %j: Gen<A>.y
|
|
// CHECK: [[KP_J:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: i32 0
|
|
// CHECK-SAME: @"generic environment l"
|
|
// CHECK-SAME: @"symbolic{{[^"]*}}8keypaths3GenV{{[^"]*}}"
|
|
// CHECK-SAME: @"symbolic x"
|
|
// -- size 8
|
|
// CHECK-SAME: i32 8,
|
|
// -- struct with runtime-resolved offset
|
|
// CHECK-SAME: <i32 0x01fffffe>,
|
|
// CHECK-32-SAME: i32 20 }>
|
|
// CHECK-64-SAME: i32 36 }>
|
|
|
|
// -- %tg0: TG<T,U,V>.a.0
|
|
// CHECK: [[KP_TG0:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: @"generic environment r1_l"
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- struct with runtime-resolved offset, mutable
|
|
// CHECK-SAME: <i32 0x01ff_fffe>,
|
|
// -- offset of TG.a
|
|
// CHECK-32-SAME: i32 20
|
|
// CHECK-64-SAME: i32 40
|
|
// CHECK-SAME: @"symbolic
|
|
// -- tuple element with compile-time known offset, mutable
|
|
// -- tuple element #0 of TG.a
|
|
// CHECK-SAME: <i32 0x0180_0000> }>
|
|
|
|
// -- %tg1: TG<T,U,V>.a.2
|
|
// CHECK: [[KP_TG1:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: @"generic environment r1_l"
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- struct with runtime-resolved offset, mutable
|
|
// CHECK-SAME: <i32 0x01ff_fffe>,
|
|
// -- offset of TG.a
|
|
// CHECK-32-SAME: i32 20
|
|
// CHECK-64-SAME: i32 40
|
|
// CHECK-SAME: @"symbolic
|
|
// -- tuple element with runtime-resolved offset, mutable
|
|
// CHECK-SAME: <i32 0x01ff_fffe>,
|
|
// -- tuple element #2 of TG.a
|
|
// CHECK-32-SAME: i32 32 }>
|
|
// CHECK-64-SAME: i32 64 }>
|
|
|
|
// -- %tg2: TGA<T,U>.1
|
|
// CHECK: [[KP_TG2:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: @"generic environment r0_l"
|
|
// CHECK-SAME: @"symbolic
|
|
// CHECK-SAME: @"symbolic
|
|
// -- tuple element with runtime-resolved offset, mutable
|
|
// CHECK-SAME: <i32 0x01ff_fffe>,
|
|
// -- tuple element #1 of TGA
|
|
// CHECK-32-SAME: i32 24 }>
|
|
// CHECK-64-SAME: i32 48 }>
|
|
|
|
// -- %gcx: GC<T>.x
|
|
// CHECK: [[KP_GCX:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
|
|
// CHECK-SAME: @"generic environment l"
|
|
// CHECK-SAME: @"symbolic{{[^"]*}}8keypaths2GCC{{[^"]*}}"
|
|
// CHECK-SAME: @"symbolic x"
|
|
// -- class with runtime-resolved offset, mutable
|
|
// CHECK-SAME: <i32 0x3fffffe>
|
|
|
|
// CHECK-LABEL: @"generic environment SHRzSHR_r0_l" = linkonce_odr hidden constant
|
|
// CHECK-SAME: i32 8193, i16 2, i8 -128, i8 -128, i32 128
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @stored_property_fixed_offsets()
|
|
sil @stored_property_fixed_offsets : $@convention(thin) () -> () {
|
|
entry:
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_A]], ptr undef)
|
|
%a = keypath $KeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
|
|
strong_retain %a : $KeyPath<S, Int>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_B]], ptr undef)
|
|
%b = keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
|
|
strong_retain %b : $KeyPath<S, String>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_C]], ptr undef)
|
|
%c = keypath $KeyPath<S, C>, (root $S; stored_property #S.z : $C)
|
|
strong_retain %c : $KeyPath<S, C>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_D]], ptr undef)
|
|
%d = keypath $KeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
|
|
strong_retain %d : $KeyPath<C, Int>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_D1]], ptr undef)
|
|
%d1 = keypath $KeyPath<C1, Int>, (root $C1; stored_property #C.x : $Int)
|
|
strong_retain %d1 : $KeyPath<C1, Int>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_E]], ptr undef)
|
|
%e = keypath $KeyPath<C, String>, (root $C; stored_property #C.y : $String)
|
|
strong_retain %e : $KeyPath<C, String>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_F]], ptr undef)
|
|
%f = keypath $KeyPath<C, S>, (root $C; stored_property #C.z : $S)
|
|
strong_retain %f : $KeyPath<C, S>
|
|
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_G]], ptr undef)
|
|
%g = keypath $KeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
|
|
strong_retain %g : $KeyPath<S, Int>
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_H]], ptr undef)
|
|
%h = keypath $KeyPath<C, Int>, (root $C; stored_property #C.z : $S; stored_property #S.x : $Int)
|
|
strong_retain %h : $KeyPath<C, Int>
|
|
|
|
%k = keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @k_id : $@convention(thin) () -> (), getter @k_get : $@convention(keypath_accessor_getter) (@in_guaranteed S) -> @out Int)
|
|
strong_retain %k : $KeyPath<S, Int>
|
|
%l = keypath $KeyPath<C, Int>, (root $C; settable_property $Int, id #C.w!getter, getter @l_get : $@convention(keypath_accessor_getter) (@in_guaranteed C) -> @out Int, setter @l_set : $@convention(keypath_accessor_setter) (@in_guaranteed Int, @in_guaranteed C) -> ())
|
|
strong_retain %l : $KeyPath<C, Int>
|
|
%m = keypath $KeyPath<S, () -> ()>, (root $S; settable_property $() -> (), id ##S.reabstracted, getter @m_get : $@convention(keypath_accessor_getter) (@in_guaranteed S) -> @out @callee_guaranteed @substituted <A> () -> @out A for <()>, setter @m_set : $@convention(keypath_accessor_setter) (@in_guaranteed @callee_guaranteed @substituted <A> () -> @out A for <()>, @inout S) -> ())
|
|
strong_retain %m : $KeyPath<S, () -> ()>
|
|
%m2 = keypath $KeyPath<C2, () -> ()>, (root $C2; settable_property $() -> (), id ##C2.reabstracted, getter @m2_get : $@convention(keypath_accessor_getter) (@in_guaranteed C2) -> @out @callee_guaranteed @substituted <A> () -> @out A for <()>, setter @m2_set : $@convention(keypath_accessor_setter) (@in_guaranteed @callee_guaranteed @substituted <A> () -> @out A for <()>, @inout C2) -> ())
|
|
strong_retain %m2 : $KeyPath<C2, () -> ()>
|
|
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_T0]], ptr undef)
|
|
%t0 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.a : $(Int, String); tuple_element #0 : $Int)
|
|
strong_retain %t0 : $KeyPath<T, Int>
|
|
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_T1]], ptr undef)
|
|
%t1 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.b : $(f: String, g: Int); tuple_element #1 : $Int)
|
|
strong_retain %t1 : $KeyPath<T, Int>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
sil @k_id : $@convention(thin) () -> ()
|
|
sil @k_get : $@convention(keypath_accessor_getter) (@in_guaranteed S) -> @out Int {
|
|
bb0(%0 : $*Int, %1 : $*S):
|
|
unreachable
|
|
}
|
|
|
|
sil @l_get : $@convention(keypath_accessor_getter) (@in_guaranteed C) -> @out Int {
|
|
bb0(%0 : $*Int, %1 : $*C):
|
|
unreachable
|
|
}
|
|
|
|
sil @l_set : $@convention(keypath_accessor_setter) (@in_guaranteed Int, @in_guaranteed C) -> () {
|
|
bb0(%0 : $*Int, %1 : $*C):
|
|
unreachable
|
|
}
|
|
|
|
sil @m_get : $@convention(keypath_accessor_getter) (@in_guaranteed S) -> @out @callee_guaranteed @substituted <A> () -> @out A for <()> {
|
|
bb0(%0 : $*@callee_guaranteed @substituted <A> () -> @out A for <()>, %1 : $*S):
|
|
unreachable
|
|
}
|
|
|
|
sil @m_set : $@convention(keypath_accessor_setter) (@in_guaranteed @callee_guaranteed @substituted <A> () -> @out A for <()>, @inout S) -> () {
|
|
bb0(%0 : $*@callee_guaranteed @substituted <A> () -> @out A for <()>, %1 : $*S):
|
|
unreachable
|
|
}
|
|
|
|
sil @m2_get : $@convention(keypath_accessor_getter) (@in_guaranteed C2) -> @out @callee_guaranteed @substituted <A> () -> @out A for <()>
|
|
sil @m2_set : $@convention(keypath_accessor_setter) (@in_guaranteed @callee_guaranteed @substituted <A> () -> @out A for <()>, @inout C2) -> ()
|
|
|
|
struct Gen<T, U> {
|
|
var x: T
|
|
var y: U
|
|
}
|
|
|
|
struct Foo<T> {
|
|
var foo: T
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @stored_property_generics(ptr %T, ptr %U)
|
|
sil @stored_property_generics : $@convention(thin) <T, U> () -> () {
|
|
entry:
|
|
// CHECK: [[ARGS:%.*]] = alloca i{{.*}}
|
|
// CHECK: store ptr %T, ptr [[ARGS]]
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_I]], ptr [[ARGS]])
|
|
%i = keypath $KeyPath<Gen<T,T>, T>, <A> (root $Gen<A, A>; stored_property #Gen.x : $A) <T>
|
|
strong_retain %i : $KeyPath<Gen<T,T>, T>
|
|
|
|
// CHECK: [[ARGS:%.*]] = alloca i{{.*}}
|
|
// CHECK: store ptr %U, ptr [[ARGS]]
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_J]], ptr [[ARGS]])
|
|
%j = keypath $KeyPath<Gen<U,U>, U>, <A> (root $Gen<A, A>; stored_property #Gen.y : $A) <U>
|
|
strong_retain %j : $KeyPath<Gen<U,U>, U>
|
|
|
|
// CHECK: [[ARGS:%.*]] = alloca i{{.*}}
|
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s8keypaths3FooVMa"([[WORD]] 0, ptr %T)
|
|
// CHECK: [[FOO_T:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK: store ptr [[FOO_T]], ptr [[ARGS]]
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_I]], ptr [[ARGS]])
|
|
%i2 = keypath $KeyPath<Gen<Foo<T>,Foo<T>>, Foo<T>>, <A> (root $Gen<A, A>; stored_property #Gen.x : $A) <Foo<T>>
|
|
strong_retain %i2 : $KeyPath<Gen<Foo<T>,Foo<T>>, Foo<T>>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @tuple_generics(ptr %T, ptr %U, ptr %V)
|
|
sil @tuple_generics : $@convention(thin) <T, U, V> () -> () {
|
|
entry:
|
|
// CHECK: [[ARGS:%.*]] = alloca i{{.*}}
|
|
// CHECK: store ptr %T, ptr [[ARGS]]
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_TG0]], ptr [[ARGS]])
|
|
%tg0 = keypath $KeyPath<TG<T,U,V>, T>, <A,B,C> (root $TG<A,B,C>; stored_property #TG.a : $(A,B,C); tuple_element #0 : $A) <T,U,V>
|
|
strong_retain %tg0 : $KeyPath<TG<T,U,V>, T>
|
|
|
|
// CHECK: [[ARGS:%.*]] = alloca i{{.*}}
|
|
// CHECK: store ptr %T, ptr [[ARGS]]
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_TG1]], ptr [[ARGS]])
|
|
%tg1 = keypath $KeyPath<TG<T,U,V>, V>, <A,B,C> (root $TG<A,B,C>; stored_property #TG.a : $(A,B,C); tuple_element #2 : $C) <T,U,V>
|
|
strong_retain %tg1 : $KeyPath<TG<T,U,V>, V>
|
|
|
|
// CHECK: [[ARGS:%.*]] = alloca i{{.*}}
|
|
// CHECK: store ptr %T, ptr [[ARGS]]
|
|
// CHECK: call ptr @swift_getKeyPath(ptr [[KP_TG2]], ptr [[ARGS]])
|
|
%tg2 = keypath $KeyPath<TGA<T,U>, U>, <A,B> (root $TGA<A,B>; tuple_element #1 : $B) <T,U>
|
|
strong_retain %tg2 : $KeyPath<TGA<T,U>, U>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
sil @generic_class_stored_final : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
%gcx = keypath $ReferenceWritableKeyPath<GC<T>, T>, <T> (root $GC<T>; stored_property #GC.x: $T) <T>
|
|
strong_retain %gcx : $ReferenceWritableKeyPath<GC<T>, T>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( 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(keypath_accessor_getter) <UU, TT> (@in_guaranteed TT) -> @out UU, getter @n_get : $@convention(keypath_accessor_getter) <UU, TT> (@in_guaranteed TT) -> @out UU, setter @n_set : $@convention(keypath_accessor_setter) <UU, TT> (@in_guaranteed UU, @in_guaranteed TT) -> ()) <U, T>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
sil @n_get : $@convention(keypath_accessor_getter) <UU, TT> (@in_guaranteed TT) -> @out UU
|
|
sil @n_set : $@convention(keypath_accessor_setter) <UU, TT> (@in_guaranteed UU, @in_guaranteed TT) -> ()
|
|
|
|
sil @computed_property_indices : $@convention(thin) (C, S, C, S, C, S) -> () {
|
|
entry(%0 : $C, %1 : $S, %2 : $C, %3 : $S, %4 : $C, %5 : $S):
|
|
%o = keypath $WritableKeyPath<S, C>, (
|
|
root $S;
|
|
settable_property $C,
|
|
id @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C,
|
|
getter @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C,
|
|
setter @o_set : $@convention(keypath_accessor_setter) (@in_guaranteed C, @in_guaranteed S, @in_guaranteed Int) -> (),
|
|
indices [%$0 : $C : $C],
|
|
indices_equals @o_equals : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @o_hash : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int
|
|
) (%0)
|
|
%p = keypath $WritableKeyPath<S, C>, (
|
|
root $S;
|
|
settable_property $C,
|
|
id @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C,
|
|
getter @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C,
|
|
setter @o_set : $@convention(keypath_accessor_setter) (@in_guaranteed C, @in_guaranteed S, @in_guaranteed Int) -> (),
|
|
indices [%$0 : $S : $S, %$1 : $C : $C],
|
|
indices_equals @o_equals : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @o_hash : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int
|
|
) (%1, %2)
|
|
%r = keypath $WritableKeyPath<S, S>, (
|
|
root $S;
|
|
settable_property $C,
|
|
id @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C,
|
|
getter @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C,
|
|
setter @o_set : $@convention(keypath_accessor_setter) (@in_guaranteed C, @in_guaranteed S, @in_guaranteed Int) -> (),
|
|
indices [%$0 : $S : $S, %$1 : $C : $C],
|
|
indices_equals @o_equals : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @o_hash : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int;
|
|
settable_property $S,
|
|
id @r_get : $@convention(keypath_accessor_getter) (@in_guaranteed C, @in_guaranteed Int) -> @out S,
|
|
getter @r_get : $@convention(keypath_accessor_getter) (@in_guaranteed C, @in_guaranteed Int) -> @out S,
|
|
setter @r_set : $@convention(keypath_accessor_setter) (@in_guaranteed S, @in_guaranteed C, @in_guaranteed Int) -> (),
|
|
indices [%$2 : $S : $S],
|
|
indices_equals @o_equals : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @o_hash : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int
|
|
) (%3, %4, %5)
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
sil @o_get : $@convention(keypath_accessor_getter) (@in_guaranteed S, @in_guaranteed Int) -> @out C
|
|
sil @o_set : $@convention(keypath_accessor_setter) (@in_guaranteed C, @in_guaranteed S, @in_guaranteed Int) -> ()
|
|
sil @o_equals : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool
|
|
sil @o_hash : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int
|
|
|
|
sil @r_get : $@convention(keypath_accessor_getter) (@in_guaranteed C, @in_guaranteed Int) -> @out S
|
|
sil @r_set : $@convention(keypath_accessor_setter) (@in_guaranteed S, @in_guaranteed C, @in_guaranteed Int) -> ()
|
|
|
|
sil @generic_computed_property_indices : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B) -> () {
|
|
entry(%0 : $*A, %1 : $*B, %2 : $*A, %3 : $*B, %4 : $*A, %5 : $*B):
|
|
%s = keypath $WritableKeyPath<A, B>, <X: Hashable, Y: Hashable> (
|
|
root $X;
|
|
settable_property $Y,
|
|
id @s_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed Int) -> @out U,
|
|
getter @s_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed Int) -> @out U,
|
|
setter @s_set : $@convention(keypath_accessor_setter) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed T, @in_guaranteed Int) -> (),
|
|
indices [%$0 : $X : $*X],
|
|
indices_equals @s_equals : $@convention(keypath_accessor_equals) <T: Hashable, U: Hashable> (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @s_hash : $@convention(keypath_accessor_hash) <T: Hashable, U: Hashable> (@in_guaranteed Int) -> Int
|
|
) <A, B> (%0)
|
|
%t = keypath $WritableKeyPath<A, B>, <X: Hashable, Y: Hashable> (
|
|
root $X;
|
|
settable_property $Y,
|
|
id @s_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed Int) -> @out U,
|
|
getter @s_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed Int) -> @out U,
|
|
setter @s_set : $@convention(keypath_accessor_setter) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed T, @in_guaranteed Int) -> (),
|
|
indices [%$0 : $Y : $*Y, %$1 : $X : $*X],
|
|
indices_equals @s_equals : $@convention(keypath_accessor_equals) <T: Hashable, U: Hashable> (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @s_hash : $@convention(keypath_accessor_hash) <T: Hashable, U: Hashable> (@in_guaranteed Int) -> Int
|
|
) <A, B> (%1, %2)
|
|
%v = keypath $WritableKeyPath<A, A>, <X: Hashable, Y: Hashable> (
|
|
root $X;
|
|
settable_property $Y,
|
|
id @s_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed Int) -> @out U,
|
|
getter @s_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed Int) -> @out U,
|
|
setter @s_set : $@convention(keypath_accessor_setter) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed T, @in_guaranteed Int) -> (),
|
|
indices [%$0 : $Y : $*Y, %$1 : $X : $*X],
|
|
indices_equals @s_equals : $@convention(keypath_accessor_equals) <T: Hashable, U: Hashable> (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @s_hash : $@convention(keypath_accessor_hash) <T: Hashable, U: Hashable> (@in_guaranteed Int) -> Int;
|
|
settable_property $X,
|
|
id @v_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed Int) -> @out T,
|
|
getter @v_get : $@convention(keypath_accessor_getter) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed Int) -> @out T,
|
|
setter @v_set : $@convention(keypath_accessor_setter) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed U, @in_guaranteed Int) -> (),
|
|
indices [%$2 : $Y : $*Y],
|
|
indices_equals @s_equals : $@convention(keypath_accessor_equals) <T: Hashable, U: Hashable> (@in_guaranteed Int, @in_guaranteed Int) -> Bool,
|
|
indices_hash @s_hash : $@convention(keypath_accessor_hash) <T: Hashable, U: Hashable> (@in_guaranteed Int) -> Int
|
|
) <A, B> (%3, %4, %5)
|
|
|
|
strong_retain %s : $WritableKeyPath<A, B>
|
|
strong_retain %t : $WritableKeyPath<A, B>
|
|
strong_retain %v : $WritableKeyPath<A, A>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
sil @identity : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
%v = keypath $WritableKeyPath<T, T>, <A> (root $A; objc "self") <T>
|
|
%w = keypath $WritableKeyPath<Int, Int>, (root $Int; objc "self")
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
public class GC2<T> {
|
|
public final var x: T
|
|
public var y: String
|
|
}
|
|
|
|
sil @class_constrained : $@convention(thin) <V where V : C> () -> () {
|
|
bb0:
|
|
%k = keypath $KeyPath<V, String>, <τ_0_0 where τ_0_0 : C> (root $τ_0_0; stored_property #C.y : $String) <V>
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
sil @generic_class_constrained : $@convention(thin) <U, V where V : GC2<U>> () -> () {
|
|
bb0:
|
|
%k = keypath $KeyPath<V, String>, <τ_0_0, τ_0_1 where τ_0_1 : GC2<τ_0_0>> (root $τ_0_1; stored_property #GC2.y : $String) <U, V>
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
sil @s_get : $@convention(keypath_accessor_getter) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed Int) -> @out B
|
|
sil @s_set : $@convention(keypath_accessor_setter) <A: Hashable, B: Hashable> (@in_guaranteed B, @in_guaranteed A, @in_guaranteed Int) -> ()
|
|
sil @s_equals : $@convention(keypath_accessor_equals) <A: Hashable, B: Hashable> (@in_guaranteed Int, @in_guaranteed Int) -> Bool
|
|
sil @s_hash : $@convention(keypath_accessor_hash) <A: Hashable, B: Hashable> (@in_guaranteed Int) -> Int
|
|
|
|
sil @v_get : $@convention(keypath_accessor_getter) <A: Hashable, B: Hashable> (@in_guaranteed B, @in_guaranteed Int) -> @out A
|
|
sil @v_set : $@convention(keypath_accessor_setter) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed B, @in_guaranteed Int) -> ()
|