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
@@ -98,9 +104,9 @@ protocol ForwardingUseDefWalker {
98
104
99
105
extension ForwardingUseDefWalker {
100
106
mutating func walkUp( value: Value ) -> WalkResult {
101
- walkUpDefault ( value : value)
107
+ walkUpDefault ( forwarded : value)
102
108
}
103
- mutating func walkUpDefault( value: Value ) -> WalkResult {
109
+ mutating func walkUpDefault( forwarded value: Value ) -> WalkResult {
104
110
if let inst = value. forwardingInstruction {
105
111
return walkUp ( instruction: inst)
106
112
}
@@ -134,18 +140,30 @@ extension ForwardingUseDefWalker {
134
140
// This conveniently gathers all forward introducers and deinitializes
135
141
// visitedValues before the caller has a chance to recurse.
136
142
func gatherLifetimeIntroducers( for value: Value , _ context: Context ) -> [ Value ] {
137
- var gather = GatherLifetimeIntroducers ( context)
138
- defer { gather. visitedValues. deinitialize ( ) }
139
- let result = gather. walkUp ( value: value)
140
- assert ( result == . continueWalk)
141
- return gather. introducers
143
+ var introducers : [ Value ] = [ ]
144
+ var walker = VisitLifetimeIntroducers ( context) {
145
+ introducers. append ( $0)
146
+ return . continueWalk
147
+ }
148
+ defer { walker. visitedValues. deinitialize ( ) }
149
+ _ = walker. walkUp ( value: value)
150
+ return introducers
142
151
}
143
152
144
- private struct GatherLifetimeIntroducers : ForwardingUseDefWalker {
153
+ // TODO: visitor can be nonescaping when we have borrowed properties.
154
+ func visitLifetimeIntroducers( for value: Value , _ context: Context ,
155
+ visitor: @escaping ( Value ) -> WalkResult ) -> WalkResult {
156
+ var walker = VisitLifetimeIntroducers ( context, visitor: visitor)
157
+ defer { walker. visitedValues. deinitialize ( ) }
158
+ return walker. walkUp ( value: value)
159
+ }
160
+
161
+ private struct VisitLifetimeIntroducers : ForwardingUseDefWalker {
162
+ var visitor : ( Value ) -> WalkResult
145
163
var visitedValues : ValueSet
146
- var introducers : [ Value ] = [ ]
147
164
148
- init ( _ context: Context ) {
165
+ init ( _ context: Context , visitor: @escaping ( Value ) -> WalkResult ) {
166
+ self . visitor = visitor
149
167
self . visitedValues = ValueSet ( context)
150
168
}
151
169
@@ -154,8 +172,7 @@ private struct GatherLifetimeIntroducers : ForwardingUseDefWalker {
154
172
}
155
173
156
174
mutating func introducer( _ value: Value ) -> WalkResult {
157
- introducers. append ( value)
158
- return . continueWalk
175
+ visitor ( value)
159
176
}
160
177
}
161
178
@@ -177,7 +194,16 @@ enum ForwardingUseResult: CustomStringConvertible {
177
194
}
178
195
}
179
196
180
- /// Visit all the uses in a forward-extended lifetime (LifetimeIntroducer -> Operand).
197
+ /// Visit all the uses in a forward-extended lifetime
198
+ /// (LifetimeIntroducer -> Operand).
199
+ ///
200
+ /// Minimal requirements:
201
+ /// needWalk(for value: Value) -> Bool
202
+ /// leafUse(_ operand: Operand) -> WalkResult
203
+ /// deadValue(_ value: Value, using operand: Operand?) -> WalkResult
204
+ ///
205
+ /// Start walking:
206
+ /// walkDown(root: Value)
181
207
protocol ForwardingDefUseWalker {
182
208
// Minimally, check a ValueSet. This walker may traverse chains of
183
209
// aggregation and destructuring by default. Implementations may
@@ -194,24 +220,24 @@ protocol ForwardingDefUseWalker {
194
220
// \p operand is nil if \p value is the root.
195
221
mutating func deadValue( _ value: Value , using operand: Operand ? ) -> WalkResult
196
222
197
- mutating func walkDown( root: Value ) -> WalkResult
198
-
199
223
mutating func walkDownUses( of: Value , using: Operand ? ) -> WalkResult
200
224
201
225
mutating func walkDown( operand: Operand ) -> WalkResult
202
226
}
203
227
204
228
extension ForwardingDefUseWalker {
229
+ /// Start walking
205
230
mutating func walkDown( root: Value ) -> WalkResult {
206
231
walkDownUses ( of: root, using: nil )
207
232
}
208
233
209
234
mutating func walkDownUses( of value: Value , using operand: Operand ? )
210
235
-> WalkResult {
211
- return walkDownUsesDefault ( of : value, using: operand)
236
+ return walkDownUsesDefault ( forwarding : value, using: operand)
212
237
}
213
238
214
- mutating func walkDownUsesDefault( of value: Value , using operand: Operand ? )
239
+ mutating func walkDownUsesDefault( forwarding value: Value ,
240
+ using operand: Operand ? )
215
241
-> WalkResult {
216
242
if !needWalk( for: value) { return . continueWalk }
217
243
@@ -229,33 +255,27 @@ extension ForwardingDefUseWalker {
229
255
}
230
256
231
257
mutating func walkDown( operand: Operand ) -> WalkResult {
232
- walkDownDefault ( operand : operand)
258
+ walkDownDefault ( forwarding : operand)
233
259
}
234
260
235
- mutating func walkDownDefault( operand: Operand ) -> WalkResult {
261
+ mutating func walkDownDefault( forwarding operand: Operand ) -> WalkResult {
236
262
if let inst = operand. instruction as? ForwardingInstruction {
237
- return walkDownAllResults ( of: inst , using: operand)
263
+ return inst . forwardedResults . walk { walkDownUses ( of: $0 , using: operand) }
238
264
}
239
265
if let phi = Phi ( using: operand) {
240
266
return walkDownUses ( of: phi. value, using: operand)
241
267
}
242
268
return leafUse ( operand)
243
269
}
244
-
245
- private mutating func walkDownAllResults( of inst: ForwardingInstruction ,
246
- using operand: Operand ? ) -> WalkResult {
247
- for result in inst. forwardedResults {
248
- if walkDownUses ( of: result, using: operand) == . abortWalk {
249
- return . abortWalk
250
- }
251
- }
252
- return . continueWalk
253
- }
254
270
}
255
271
256
- /// 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().
272
+ /// This conveniently allows a closure to be called for each leaf use
273
+ /// of a forward-extended lifetime. It should be called on a forward
274
+ /// introducer provided by ForwardingDefUseWalker.introducer() or
275
+ /// gatherLifetimeIntroducers().
257
276
///
258
- /// TODO: make the visitor non-escaping once Swift supports stored non-escaping closues.
277
+ /// TODO: make the visitor non-escaping once Swift supports stored
278
+ /// non-escaping closues.
259
279
func visitForwardedUses( introducer: Value , _ context: Context ,
260
280
visitor: @escaping ( ForwardingUseResult ) -> WalkResult )
261
281
-> WalkResult {
0 commit comments