Skip to content

Commit 6f05d80

Browse files
committed
LifetimeDependenceDefUseAddressWalker: avoid infinite recursion.
This utility is used by DependentAddressUseDefWalker which now conservatively follows all possible uses. This could result in the same address being reached multiple times during a def-use walk. Ensure that we don't infinitely recurse. There is no small test case for this, but the fix is trivial and standard practice for such walkers, and this is hit quickly in real usage, so there is no danger of it regressing. Fixes rdar://150403948 ([nonescapable] Infinite recursion compiler crash in lifetime dependence checking) (cherry picked from commit 4512927)
1 parent f6a864a commit 6f05d80

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceInsertion.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefValueWalker, Lif
424424
visitedValues.insert(value)
425425
}
426426

427+
mutating func needWalk(for address: Value) -> Bool {
428+
visitedValues.insert(address)
429+
}
430+
427431
mutating func walkUp(newLifetime: Value) -> WalkResult {
428432
if newLifetime.type.isAddress {
429433
return walkUp(address: newLifetime)

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,10 @@ extension LifetimeDependenceDefUseWalker {
817817
}
818818

819819
private mutating func walkDownAddressUses(of address: Value) -> WalkResult {
820-
address.uses.ignoreTypeDependence.walk {
820+
if !needWalk(for: address) {
821+
return .continueWalk
822+
}
823+
return address.uses.ignoreTypeDependence.walk {
821824
return classifyAddress(operand: $0)
822825
}
823826
}
@@ -1199,6 +1202,8 @@ protocol LifetimeDependenceUseDefAddressWalker {
11991202
// ignored.
12001203
var isTrivialScope: Bool { get }
12011204

1205+
mutating func needWalk(for address: Value) -> Bool
1206+
12021207
mutating func addressIntroducer(_ address: Value, access: AccessBaseAndScopes) -> WalkResult
12031208

12041209
// The 'newLifetime' value is not forwarded to its uses. It may be a non-address or an address.
@@ -1221,6 +1226,9 @@ extension LifetimeDependenceUseDefAddressWalker {
12211226
}
12221227

12231228
mutating func walkUpDefault(address: Value, access: AccessBaseAndScopes) -> WalkResult {
1229+
if !needWalk(for: address) {
1230+
return .continueWalk
1231+
}
12241232
if let beginAccess = access.innermostAccess {
12251233
// Skip the access scope for unsafe[Mutable]Address. Treat it like a projection of 'self' rather than a separate
12261234
// variable access.
@@ -1333,6 +1341,10 @@ struct LifetimeDependenceRootWalker : LifetimeDependenceUseDefValueWalker, Lifet
13331341
visitedValues.insert(value)
13341342
}
13351343

1344+
mutating func needWalk(for address: Value) -> Bool {
1345+
visitedValues.insert(address)
1346+
}
1347+
13361348
mutating func walkUp(newLifetime: Value) -> WalkResult {
13371349
if newLifetime.type.isAddress {
13381350
return walkUp(address: newLifetime)

0 commit comments

Comments
 (0)