9
9
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
10
//
11
11
//===----------------------------------------------------------------------===//
12
+ ///
13
+ /// TODO: Once the hasPointerEscape flags are implemented for
14
+ /// BeginBorrowInst, MoveValueInst, and Allocation,
15
+ /// ForwardingUseDefWalker should be used to check whether any value
16
+ /// is part of a forward-extended lifetime that has a pointer escape.
17
+ //===----------------------------------------------------------------------===//
12
18
13
19
import SIL
14
20
@@ -84,9 +90,9 @@ protocol ForwardingUseDefWalker {
84
90
85
91
extension ForwardingUseDefWalker {
86
92
mutating func walkUp( value: Value ) -> WalkResult {
87
- walkUpDefault ( value : value)
93
+ walkUpDefault ( forwarded : value)
88
94
}
89
- mutating func walkUpDefault( value: Value ) -> WalkResult {
95
+ mutating func walkUpDefault( forwarded value: Value ) -> WalkResult {
90
96
if let inst = value. forwardingInstruction {
91
97
return walkUp ( instruction: inst)
92
98
}
@@ -120,18 +126,30 @@ extension ForwardingUseDefWalker {
120
126
// This conveniently gathers all forward introducers and deinitializes
121
127
// visitedValues before the caller has a chance to recurse.
122
128
func gatherLifetimeIntroducers( for value: Value , _ context: Context ) -> [ Value ] {
123
- var gather = GatherLifetimeIntroducers ( context)
124
- defer { gather. visitedValues. deinitialize ( ) }
125
- let result = gather. walkUp ( value: value)
126
- assert ( result == . continueWalk)
127
- return gather. introducers
129
+ var introducers : [ Value ] = [ ]
130
+ var walker = VisitLifetimeIntroducers ( context) {
131
+ introducers. append ( $0)
132
+ return . continueWalk
133
+ }
134
+ defer { walker. visitedValues. deinitialize ( ) }
135
+ _ = walker. walkUp ( value: value)
136
+ return introducers
128
137
}
129
138
130
- private struct GatherLifetimeIntroducers : ForwardingUseDefWalker {
139
+ // TODO: visitor can be nonescaping when we have borrowed properties.
140
+ func visitLifetimeIntroducers( for value: Value , _ context: Context ,
141
+ visitor: @escaping ( Value ) -> WalkResult ) -> WalkResult {
142
+ var walker = VisitLifetimeIntroducers ( context, visitor: visitor)
143
+ defer { walker. visitedValues. deinitialize ( ) }
144
+ return walker. walkUp ( value: value)
145
+ }
146
+
147
+ private struct VisitLifetimeIntroducers : ForwardingUseDefWalker {
148
+ var visitor : ( Value ) -> WalkResult
131
149
var visitedValues : ValueSet
132
- var introducers : [ Value ] = [ ]
133
150
134
- init ( _ context: Context ) {
151
+ init ( _ context: Context , visitor: @escaping ( Value ) -> WalkResult ) {
152
+ self . visitor = visitor
135
153
self . visitedValues = ValueSet ( context)
136
154
}
137
155
@@ -140,8 +158,7 @@ private struct GatherLifetimeIntroducers : ForwardingUseDefWalker {
140
158
}
141
159
142
160
mutating func introducer( _ value: Value ) -> WalkResult {
143
- introducers. append ( value)
144
- return . continueWalk
161
+ visitor ( value)
145
162
}
146
163
}
147
164
@@ -163,7 +180,16 @@ enum ForwardingUseResult: CustomStringConvertible {
163
180
}
164
181
}
165
182
166
- /// Visit all the uses in a forward-extended lifetime (LifetimeIntroducer -> Operand).
183
+ /// Visit all the uses in a forward-extended lifetime
184
+ /// (LifetimeIntroducer -> Operand).
185
+ ///
186
+ /// Minimal requirements:
187
+ /// needWalk(for value: Value) -> Bool
188
+ /// leafUse(_ operand: Operand) -> WalkResult
189
+ /// deadValue(_ value: Value, using operand: Operand?) -> WalkResult
190
+ ///
191
+ /// Start walking:
192
+ /// walkDown(root: Value)
167
193
protocol ForwardingDefUseWalker {
168
194
// Minimally, check a ValueSet. This walker may traverse chains of
169
195
// aggregation and destructuring by default. Implementations may
@@ -180,24 +206,24 @@ protocol ForwardingDefUseWalker {
180
206
// \p operand is nil if \p value is the root.
181
207
mutating func deadValue( _ value: Value , using operand: Operand ? ) -> WalkResult
182
208
183
- mutating func walkDown( root: Value ) -> WalkResult
184
-
185
209
mutating func walkDownUses( of: Value , using: Operand ? ) -> WalkResult
186
210
187
211
mutating func walkDown( operand: Operand ) -> WalkResult
188
212
}
189
213
190
214
extension ForwardingDefUseWalker {
215
+ /// Start walking
191
216
mutating func walkDown( root: Value ) -> WalkResult {
192
217
walkDownUses ( of: root, using: nil )
193
218
}
194
219
195
220
mutating func walkDownUses( of value: Value , using operand: Operand ? )
196
221
-> WalkResult {
197
- return walkDownUsesDefault ( of : value, using: operand)
222
+ return walkDownUsesDefault ( forwarding : value, using: operand)
198
223
}
199
224
200
- mutating func walkDownUsesDefault( of value: Value , using operand: Operand ? )
225
+ mutating func walkDownUsesDefault( forwarding value: Value ,
226
+ using operand: Operand ? )
201
227
-> WalkResult {
202
228
if !needWalk( for: value) { return . continueWalk }
203
229
@@ -215,33 +241,27 @@ extension ForwardingDefUseWalker {
215
241
}
216
242
217
243
mutating func walkDown( operand: Operand ) -> WalkResult {
218
- walkDownDefault ( operand : operand)
244
+ walkDownDefault ( forwarding : operand)
219
245
}
220
246
221
- mutating func walkDownDefault( operand: Operand ) -> WalkResult {
247
+ mutating func walkDownDefault( forwarding operand: Operand ) -> WalkResult {
222
248
if let inst = operand. instruction as? ForwardingInstruction {
223
- return walkDownAllResults ( of: inst , using: operand)
249
+ return inst . forwardedResults . walk { walkDownUses ( of: $0 , using: operand) }
224
250
}
225
251
if let phi = Phi ( using: operand) {
226
252
return walkDownUses ( of: phi. value, using: operand)
227
253
}
228
254
return leafUse ( operand)
229
255
}
230
-
231
- private mutating func walkDownAllResults( of inst: ForwardingInstruction ,
232
- using operand: Operand ? ) -> WalkResult {
233
- for result in inst. forwardedResults {
234
- if walkDownUses ( of: result, using: operand) == . abortWalk {
235
- return . abortWalk
236
- }
237
- }
238
- return . continueWalk
239
- }
240
256
}
241
257
242
- /// This conveniently allows a closure to be called for each leaf use of a forward-extended lifetime. It should be called on a forward introducer provided by ForwardingDefUseWalker.introducer() or gatherLifetimeIntroducers().
258
+ /// This conveniently allows a closure to be called for each leaf use
259
+ /// of a forward-extended lifetime. It should be called on a forward
260
+ /// introducer provided by ForwardingDefUseWalker.introducer() or
261
+ /// gatherLifetimeIntroducers().
243
262
///
244
- /// TODO: make the visitor non-escaping once Swift supports stored non-escaping closues.
263
+ /// TODO: make the visitor non-escaping once Swift supports stored
264
+ /// non-escaping closues.
245
265
func visitForwardedUses( introducer: Value , _ context: Context ,
246
266
visitor: @escaping ( ForwardingUseResult ) -> WalkResult )
247
267
-> WalkResult {
0 commit comments