Skip to content

Commit 2cac9fb

Browse files
committed
ForwardingUtils.swift cleanup. Make the API easier to extend.
1 parent 5759d42 commit 2cac9fb

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/ForwardingUtils.swift

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
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+
//===----------------------------------------------------------------------===//
1218

1319
import SIL
1420

@@ -98,9 +104,9 @@ protocol ForwardingUseDefWalker {
98104

99105
extension ForwardingUseDefWalker {
100106
mutating func walkUp(value: Value) -> WalkResult {
101-
walkUpDefault(value: value)
107+
walkUpDefault(forwarded: value)
102108
}
103-
mutating func walkUpDefault(value: Value) -> WalkResult {
109+
mutating func walkUpDefault(forwarded value: Value) -> WalkResult {
104110
if let inst = value.forwardingInstruction {
105111
return walkUp(instruction: inst)
106112
}
@@ -134,18 +140,30 @@ extension ForwardingUseDefWalker {
134140
// This conveniently gathers all forward introducers and deinitializes
135141
// visitedValues before the caller has a chance to recurse.
136142
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
142151
}
143152

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
145163
var visitedValues: ValueSet
146-
var introducers: [Value] = []
147164

148-
init(_ context: Context) {
165+
init(_ context: Context, visitor: @escaping (Value) -> WalkResult) {
166+
self.visitor = visitor
149167
self.visitedValues = ValueSet(context)
150168
}
151169

@@ -154,8 +172,7 @@ private struct GatherLifetimeIntroducers : ForwardingUseDefWalker {
154172
}
155173

156174
mutating func introducer(_ value: Value) -> WalkResult {
157-
introducers.append(value)
158-
return .continueWalk
175+
visitor(value)
159176
}
160177
}
161178

@@ -177,7 +194,16 @@ enum ForwardingUseResult: CustomStringConvertible {
177194
}
178195
}
179196

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)
181207
protocol ForwardingDefUseWalker {
182208
// Minimally, check a ValueSet. This walker may traverse chains of
183209
// aggregation and destructuring by default. Implementations may
@@ -194,24 +220,24 @@ protocol ForwardingDefUseWalker {
194220
// \p operand is nil if \p value is the root.
195221
mutating func deadValue(_ value: Value, using operand: Operand?) -> WalkResult
196222

197-
mutating func walkDown(root: Value) -> WalkResult
198-
199223
mutating func walkDownUses(of: Value, using: Operand?) -> WalkResult
200224

201225
mutating func walkDown(operand: Operand) -> WalkResult
202226
}
203227

204228
extension ForwardingDefUseWalker {
229+
/// Start walking
205230
mutating func walkDown(root: Value) -> WalkResult {
206231
walkDownUses(of: root, using: nil)
207232
}
208233

209234
mutating func walkDownUses(of value: Value, using operand: Operand?)
210235
-> WalkResult {
211-
return walkDownUsesDefault(of: value, using: operand)
236+
return walkDownUsesDefault(forwarding: value, using: operand)
212237
}
213238

214-
mutating func walkDownUsesDefault(of value: Value, using operand: Operand?)
239+
mutating func walkDownUsesDefault(forwarding value: Value,
240+
using operand: Operand?)
215241
-> WalkResult {
216242
if !needWalk(for: value) { return .continueWalk }
217243

@@ -229,33 +255,27 @@ extension ForwardingDefUseWalker {
229255
}
230256

231257
mutating func walkDown(operand: Operand) -> WalkResult {
232-
walkDownDefault(operand: operand)
258+
walkDownDefault(forwarding: operand)
233259
}
234260

235-
mutating func walkDownDefault(operand: Operand) -> WalkResult {
261+
mutating func walkDownDefault(forwarding operand: Operand) -> WalkResult {
236262
if let inst = operand.instruction as? ForwardingInstruction {
237-
return walkDownAllResults(of: inst, using: operand)
263+
return inst.forwardedResults.walk { walkDownUses(of: $0, using: operand) }
238264
}
239265
if let phi = Phi(using: operand) {
240266
return walkDownUses(of: phi.value, using: operand)
241267
}
242268
return leafUse(operand)
243269
}
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-
}
254270
}
255271

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().
257276
///
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.
259279
func visitForwardedUses(introducer: Value, _ context: Context,
260280
visitor: @escaping (ForwardingUseResult) -> WalkResult)
261281
-> WalkResult {

0 commit comments

Comments
 (0)