1
+ // RUN: %target-sil-opt -enable-sil-verify-all %s -raw-sil-inst-lowering -enable-experimental-type-wrappers | %FileCheck %s
2
+
3
+ sil_stage raw
4
+
5
+ import Builtin
6
+ import Swift
7
+ import SwiftShims
8
+
9
+ @typeWrapper class MyWrapper<S> {
10
+ @_hasStorage var underlying: S { get set }
11
+ init(memberwise s: S)
12
+ subscript<V>(storageKeyPath path: WritableKeyPath<S, V>) -> V { get set }
13
+ deinit
14
+ }
15
+
16
+ @MyWrapper struct Test1<T> {
17
+ var a: Int
18
+ var b: T
19
+ init(a: Int, b: T)
20
+ init(a: Int, b: T, otherB: T)
21
+ }
22
+
23
+ // Test1.a.setter
24
+ sil hidden [ossa] @$s4main5Test1V1aSivs : $@convention(method) <T> (Int, @inout Test1<T>) -> () {
25
+ bb0(%0 : $Int, %1 : $*Test1<T>):
26
+ %2 = tuple ()
27
+ return %2 : $()
28
+ }
29
+
30
+ // Test1.b.setter
31
+ sil hidden [ossa] @$s4main5Test1V1bxvs : $@convention(method) <T> (@in T, @inout Test1<T>) -> () {
32
+ bb0(%0 : $*T, %1 : $*Test1<T>):
33
+ destroy_addr %0 : $*T
34
+ %2 = tuple ()
35
+ return %2 : $()
36
+ }
37
+
38
+ // Test1.init(a:b:)
39
+ //
40
+ // CHECK-LABEL: sil hidden [ossa] @$s4main5Test1V1a1bACyxGSi_xtcfC
41
+ // CHECK: [[LOCAL_STORAGE:%.*]] = project_box %7 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>, 0
42
+ // CHECK: [[A_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE]] : $*(a: Int, b: T), 0
43
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
44
+ // CHECK: store [[ARG_0:%.*]] to [trivial] [[A_REF]] : $*Int
45
+ //
46
+ // CHECK: [[T:%.*]] = alloc_stack $T
47
+ // CHECK: copy_addr [[ARG_1:%.*]] to [initialization] [[T]] : $*T
48
+ // CHECK: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE]] : $*(a: Int, b: T), 1
49
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
50
+ // CHECK: copy_addr [take] [[T]] to [initialization] [[B_REF]] : $*T
51
+ sil hidden [ossa] @$s4main5Test1V1a1bACyxGSi_xtcfC : $@convention(method) <T> (Int, @in T, @thin Test1<T>.Type) -> @owned Test1<T> {
52
+ bb0(%0 : $Int, %1 : $*T, %2 : $@thin Test1<T>.Type):
53
+ %3 = alloc_box $<τ_0_0> { var Test1<τ_0_0> } <T>, var, name "self"
54
+ %4 = mark_uninitialized [rootself] %3 : $<τ_0_0> { var Test1<τ_0_0> } <T>
55
+ %5 = begin_borrow [lexical] %4 : $<τ_0_0> { var Test1<τ_0_0> } <T>
56
+ %6 = project_box %5 : $<τ_0_0> { var Test1<τ_0_0> } <T>, 0
57
+ %9 = alloc_box $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>, var, name "_storage"
58
+ %10 = mark_uninitialized [var] %9 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
59
+ %11 = begin_borrow [lexical] %10 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
60
+ %12 = project_box %11 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>, 0
61
+ %13 = begin_access [modify] [unknown] %6 : $*Test1<T>
62
+ %14 = tuple_element_addr %12 : $*(a: Int, b: T), 0
63
+ // function_ref Test1.a.setter
64
+ %15 = function_ref @$s4main5Test1V1aSivs : $@convention(method) <τ_0_0> (Int, @inout Test1<τ_0_0>) -> ()
65
+ %16 = partial_apply [callee_guaranteed] %15<T>(%13) : $@convention(method) <τ_0_0> (Int, @inout Test1<τ_0_0>) -> ()
66
+ assign_by_wrapper origin type_wrapper, %0 : $Int to [initialization] %14 : $*Int, set %16 : $@callee_guaranteed (Int) -> ()
67
+ end_access %13 : $*Test1<T>
68
+ destroy_value %16 : $@callee_guaranteed (Int) -> ()
69
+ %20 = alloc_stack $T
70
+ copy_addr %1 to [initialization] %20 : $*T
71
+ %22 = begin_access [modify] [unknown] %6 : $*Test1<T>
72
+ %23 = tuple_element_addr %12 : $*(a: Int, b: T), 1
73
+ // function_ref Test1.b.setter
74
+ %24 = function_ref @$s4main5Test1V1bxvs : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
75
+ %25 = partial_apply [callee_guaranteed] %24<T>(%22) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
76
+ assign_by_wrapper origin type_wrapper, %20 : $*T to [initialization] %23 : $*T, set %25 : $@callee_guaranteed (@in T) -> ()
77
+ end_access %22 : $*Test1<T>
78
+ destroy_value %25 : $@callee_guaranteed (@in T) -> ()
79
+ dealloc_stack %20 : $*T
80
+ end_borrow %11 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
81
+ destroy_value %10 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
82
+ %32 = load [copy] %6 : $*Test1<T>
83
+ destroy_addr %1 : $*T
84
+ end_borrow %5 : $<τ_0_0> { var Test1<τ_0_0> } <T>
85
+ destroy_value %4 : $<τ_0_0> { var Test1<τ_0_0> } <T>
86
+ return %32 : $Test1<T>
87
+ }
88
+
89
+ // Test1.init(a:b:otherB:)
90
+ //
91
+ // CHECK-LABEL: sil hidden [ossa] @$s4main5Test1V1a1b6otherBACyxGSi_xxtcfC
92
+ // CHECK: [[LOCAL_STORAGE:%.*]] = project_box %8 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>, 0
93
+ //
94
+ // CHECK: [[A_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE]] : $*(a: Int, b: T), 0
95
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
96
+ // CHECK: store [[ARG_0:%.*]] to [trivial] [[A_REF]] : $*Int
97
+ //
98
+ // CHECK: [[T:%.*]] = alloc_stack $T
99
+ // CHECK-NEXT: copy_addr [[ARG_1:%.*]] to [initialization] [[T]] : $*T
100
+ // CHECK: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE]] : $*(a: Int, b: T), 1
101
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
102
+ // CHECK: copy_addr [take] [[T]] to [initialization] [[B_REF]] : $*T
103
+ //
104
+ // CHECK: [[OTHER_T:%.*]] = alloc_stack $T
105
+ // CHECK-NEXT: copy_addr [[ARG_2:%.*]] to [initialization] %19 : $*T
106
+ // CHECK: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE]] : $*(a: Int, b: T), 1
107
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
108
+ // CHECK: copy_addr [take] [[OTHER_T]] to [[B_REF]] : $*T
109
+ //
110
+ // CHECK: [[T:%.*]] = alloc_stack $T
111
+ // copy_addr [[ARG_1]] to [initialization] [[T]] : $*T
112
+ // CHECK: [[B_SETTER:%.*]] = function_ref @$s4main5Test1V1bxvs : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
113
+ // CHECK-NEXT: [[PARTIALY_APPLIED_SETTER:%.*]] = partial_apply [callee_guaranteed] [[B_SETTER]]<T>({{.*}}) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
114
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
115
+ // CHECK-NEXT: apply [[PARTIALY_APPLIED_SETTER]]([[T]]) : $@callee_guaranteed (@in T) -> ()
116
+ sil hidden [ossa] @$s4main5Test1V1a1b6otherBACyxGSi_xxtcfC : $@convention(method) <T> (Int, @in T, @in T, @thin Test1<T>.Type) -> @owned Test1<T> {
117
+ bb0(%0 : $Int, %1 : $*T, %2 : $*T, %3 : $@thin Test1<T>.Type):
118
+ %4 = alloc_box $<τ_0_0> { var Test1<τ_0_0> } <T>, var, name "self"
119
+ %5 = mark_uninitialized [rootself] %4 : $<τ_0_0> { var Test1<τ_0_0> } <T>
120
+ %6 = begin_borrow [lexical] %5 : $<τ_0_0> { var Test1<τ_0_0> } <T>
121
+ %7 = project_box %6 : $<τ_0_0> { var Test1<τ_0_0> } <T>, 0
122
+ %11 = alloc_box $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>, var, name "_storage"
123
+ %12 = mark_uninitialized [var] %11 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
124
+ %13 = begin_borrow [lexical] %12 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
125
+ %14 = project_box %13 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>, 0
126
+ %15 = begin_access [modify] [unknown] %7 : $*Test1<T>
127
+ %16 = tuple_element_addr %14 : $*(a: Int, b: T), 0
128
+ // function_ref Test1.a.setter
129
+ %17 = function_ref @$s4main5Test1V1aSivs : $@convention(method) <τ_0_0> (Int, @inout Test1<τ_0_0>) -> ()
130
+ %18 = partial_apply [callee_guaranteed] %17<T>(%15) : $@convention(method) <τ_0_0> (Int, @inout Test1<τ_0_0>) -> ()
131
+ assign_by_wrapper origin type_wrapper, %0 : $Int to [initialization] %16 : $*Int, set %18 : $@callee_guaranteed (Int) -> ()
132
+ end_access %15 : $*Test1<T>
133
+ destroy_value %18 : $@callee_guaranteed (Int) -> ()
134
+ %22 = alloc_stack $T
135
+ copy_addr %1 to [initialization] %22 : $*T
136
+ %24 = begin_access [modify] [unknown] %7 : $*Test1<T>
137
+ %25 = tuple_element_addr %14 : $*(a: Int, b: T), 1
138
+ // function_ref Test1.b.setter
139
+ %26 = function_ref @$s4main5Test1V1bxvs : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
140
+ %27 = partial_apply [callee_guaranteed] %26<T>(%24) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
141
+ assign_by_wrapper origin type_wrapper, %22 : $*T to [initialization] %25 : $*T, set %27 : $@callee_guaranteed (@in T) -> ()
142
+ end_access %24 : $*Test1<T>
143
+ destroy_value %27 : $@callee_guaranteed (@in T) -> ()
144
+ dealloc_stack %22 : $*T
145
+ %32 = alloc_stack $T
146
+ copy_addr %2 to [initialization] %32 : $*T
147
+ %34 = begin_access [modify] [unknown] %7 : $*Test1<T>
148
+ %35 = tuple_element_addr %14 : $*(a: Int, b: T), 1
149
+ // function_ref Test1.b.setter
150
+ %36 = function_ref @$s4main5Test1V1bxvs : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
151
+ %37 = partial_apply [callee_guaranteed] %36<T>(%34) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
152
+ assign_by_wrapper origin type_wrapper, %32 : $*T to [assign] %35 : $*T, set %37 : $@callee_guaranteed (@in T) -> ()
153
+ end_access %34 : $*Test1<T>
154
+ destroy_value %37 : $@callee_guaranteed (@in T) -> ()
155
+ dealloc_stack %32 : $*T
156
+ %42 = alloc_stack $T
157
+ copy_addr %1 to [initialization] %42 : $*T
158
+ %44 = begin_access [modify] [unknown] %7 : $*Test1<T>
159
+ %45 = tuple_element_addr %14 : $*(a: Int, b: T), 1
160
+ // function_ref Test1.b.setter
161
+ %46 = function_ref @$s4main5Test1V1bxvs : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
162
+ %47 = partial_apply [callee_guaranteed] %46<T>(%44) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Test1<τ_0_0>) -> ()
163
+ assign_by_wrapper origin type_wrapper, %42 : $*T to [assign_wrapped_value] %45 : $*T, set %47 : $@callee_guaranteed (@in T) -> ()
164
+ end_access %44 : $*Test1<T>
165
+ destroy_value %47 : $@callee_guaranteed (@in T) -> ()
166
+ dealloc_stack %42 : $*T
167
+ end_borrow %13 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
168
+ destroy_value %12 : $<τ_0_0> { var (a: Int, b: τ_0_0) } <T>
169
+ %54 = load [copy] %7 : $*Test1<T>
170
+ destroy_addr %2 : $*T
171
+ destroy_addr %1 : $*T
172
+ end_borrow %6 : $<τ_0_0> { var Test1<τ_0_0> } <T>
173
+ destroy_value %5 : $<τ_0_0> { var Test1<τ_0_0> } <T>
174
+ return %54 : $Test1<T>
175
+ }
0 commit comments