Skip to content

Commit 6072683

Browse files
committed
Swift AccessUtils: add an AccessBase.unidentified case
Now that `AccessBase` is an enum, it makes sense to add an `unidentified` case. This avoids dealing with optional AccessBases in several place. Clients don't need to make both, an optional check and a switch, but can check for unidentified access bases just in a single switch statement.
1 parent 082aec0 commit 6072683

File tree

2 files changed

+46
-49
lines changed

2 files changed

+46
-49
lines changed

SwiftCompilerSources/Sources/Optimizer/TestPasses/AccessDumper.swift

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,34 +61,29 @@ private func printAccessInfo(address: Value) {
6161

6262
var apw = AccessPathWalker()
6363
let (ap, scope) = apw.getAccessPathWithScope(of: address)
64-
if let scope = scope {
65-
switch scope {
66-
case let .scope(ba):
67-
print(" Scope: \(ba)")
68-
case .base(_):
69-
print(" Scope: base")
70-
}
64+
switch scope {
65+
case let .scope(ba):
66+
print(" Scope: \(ba)")
67+
case .base(_):
68+
print(" Scope: base")
7169
}
7270

73-
if let ap = ap {
74-
print(" Base: \(ap.base)")
75-
print(" Path: \"\(ap.projectionPath)\"")
71+
print(" Base: \(ap.base)")
72+
print(" Path: \"\(ap.projectionPath)\"")
7673

77-
var arw = AccessStoragePathVisitor()
78-
if !arw.visitAccessStorageRoots(of: ap) {
79-
print(" no Storage paths")
80-
}
74+
var arw = AccessStoragePathVisitor()
75+
if !arw.visitAccessStorageRoots(of: ap) {
76+
print(" no Storage paths")
8177
}
8278
}
8379

8480
private func checkAliasInfo(forArgumentsOf apply: ApplyInst, expectDistinct: Bool) {
8581
let address1 = apply.arguments[0]
8682
let address2 = apply.arguments[1]
8783
var apw = AccessPathWalker()
88-
guard let path1 = apw.getAccessPath(of: address1),
89-
let path2 = apw.getAccessPath(of: address2) else {
90-
return
91-
}
84+
let path1 = apw.getAccessPath(of: address1)
85+
let path2 = apw.getAccessPath(of: address2)
86+
9287
if path1.isDistinct(from: path2) != expectDistinct {
9388
print("wrong isDistinct result of \(apply)")
9489
} else if path2.isDistinct(from: path1) != expectDistinct {

SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ enum AccessBase : CustomStringConvertible, Hashable {
7373
/// An address which is derived from a `Builtin.RawPointer`.
7474
case pointer(PointerToAddressInst)
7575

76-
init?(baseAddress: Value) {
76+
/// The access base is some SIL pattern which does not fit into any other case.
77+
/// This should be a very rare situation.
78+
case unidentified
79+
80+
init(baseAddress: Value) {
7781
switch baseAddress {
7882
case let rea as RefElementAddrInst : self = .class(rea)
7983
case let rta as RefTailAddrInst : self = .tail(rta)
@@ -85,15 +89,16 @@ enum AccessBase : CustomStringConvertible, Hashable {
8589
if let ba = mvr.instruction as? BeginApplyInst, baseAddress.type.isAddress {
8690
self = .yield(ba)
8791
} else {
88-
return nil
92+
self = .unidentified
8993
}
9094
default:
91-
return nil
95+
self = .unidentified
9296
}
9397
}
9498

9599
var description: String {
96100
switch self {
101+
case .unidentified: return "?"
97102
case .box(let pbi): return "box - \(pbi)"
98103
case .stack(let asi): return "stack - \(asi)"
99104
case .global(let gl): return "global - @\(gl.name)"
@@ -110,7 +115,7 @@ enum AccessBase : CustomStringConvertible, Hashable {
110115
switch self {
111116
case .class, .tail:
112117
return true
113-
case .box, .stack, .global, .argument, .yield, .pointer:
118+
case .box, .stack, .global, .argument, .yield, .pointer, .unidentified:
114119
return false
115120
}
116121
}
@@ -121,7 +126,7 @@ enum AccessBase : CustomStringConvertible, Hashable {
121126
case .box(let pbi): return pbi.operand
122127
case .class(let rea): return rea.operand
123128
case .tail(let rta): return rta.operand
124-
case .stack, .global, .argument, .yield, .pointer:
129+
case .stack, .global, .argument, .yield, .pointer, .unidentified:
125130
return nil
126131
}
127132
}
@@ -130,7 +135,7 @@ enum AccessBase : CustomStringConvertible, Hashable {
130135
switch self {
131136
case .class(let rea): return rea.fieldIsLet
132137
case .global(let g): return g.isLet
133-
case .box, .stack, .tail, .argument, .yield, .pointer:
138+
case .box, .stack, .tail, .argument, .yield, .pointer, .unidentified:
134139
return false
135140
}
136141
}
@@ -142,7 +147,7 @@ enum AccessBase : CustomStringConvertible, Hashable {
142147
case .class(let rea): return rea.operand is AllocRefInstBase
143148
case .tail(let rta): return rta.operand is AllocRefInstBase
144149
case .stack: return true
145-
case .global, .argument, .yield, .pointer:
150+
case .global, .argument, .yield, .pointer, .unidentified:
146151
return false
147152
}
148153
}
@@ -152,7 +157,7 @@ enum AccessBase : CustomStringConvertible, Hashable {
152157
switch self {
153158
case .box, .class, .tail, .stack, .global:
154159
return true
155-
case .argument, .yield, .pointer:
160+
case .argument, .yield, .pointer, .unidentified:
156161
return false
157162
}
158163
}
@@ -224,6 +229,10 @@ struct AccessPath : CustomStringConvertible {
224229
/// address projections only
225230
let projectionPath: SmallProjectionPath
226231

232+
static func unidentified() -> AccessPath {
233+
return AccessPath(base: .unidentified, projectionPath: SmallProjectionPath())
234+
}
235+
227236
var description: String {
228237
"\(projectionPath): \(base)"
229238
}
@@ -362,46 +371,46 @@ enum EnclosingScope {
362371
/// of the access (the base address and the address projections to the accessed fields) and
363372
/// the innermost enclosing scope (`begin_access`).
364373
struct AccessPathWalker {
365-
mutating func getAccessPath(of address: Value) -> AccessPath? {
374+
mutating func getAccessPath(of address: Value) -> AccessPath {
366375
assert(address.type.isAddress, "Expected address")
367376
walker.start()
368377
if walker.walkUp(address: address, path: Walker.Path()) == .abortWalk {
369-
return nil
378+
assert(walker.result.base == .unidentified,
379+
"shouldn't have set an access base in an aborted walk")
370380
}
371381
return walker.result
372382
}
373383

374-
mutating func getAccessPathWithScope(of address: Value) -> (AccessPath?, EnclosingScope?) {
384+
mutating func getAccessPathWithScope(of address: Value) -> (AccessPath, EnclosingScope) {
375385
let ap = getAccessPath(of: address)
376386
return (ap, walker.scope)
377387
}
378388

379-
mutating func getAccessBase(of address: Value) -> AccessBase? {
380-
getAccessPath(of: address)?.base
389+
mutating func getAccessBase(of address: Value) -> AccessBase {
390+
getAccessPath(of: address).base
381391
}
382392

383-
mutating func getAccessScope(of address: Value) -> EnclosingScope? {
393+
mutating func getAccessScope(of address: Value) -> EnclosingScope {
384394
getAccessPathWithScope(of: address).1
385395
}
386396

387397
private var walker = Walker()
388398

389399
private struct Walker : AddressUseDefWalker {
390-
private(set) var result: AccessPath? = nil
400+
private(set) var result = AccessPath.unidentified()
391401
private var foundBeginAccess: BeginAccessInst? = nil
392402
private var pointerId = PointerIdentification()
393403

394-
var scope: EnclosingScope? {
404+
var scope: EnclosingScope {
395405
if let ba = foundBeginAccess {
396406
return .scope(ba)
397407
} else {
398-
guard let accessPath = result else { return nil }
399-
return .base(accessPath.base)
408+
return .base(result.base)
400409
}
401410
}
402411

403412
mutating func start() {
404-
result = nil
413+
result = .unidentified()
405414
foundBeginAccess = nil
406415
}
407416

@@ -435,7 +444,7 @@ struct AccessPathWalker {
435444
}
436445

437446
mutating func rootDef(address: Value, path: Path) -> WalkResult {
438-
assert(result == nil, "rootDef should only called once")
447+
assert(result.base == .unidentified, "rootDef should only called once")
439448
// Try identifying the address a pointer originates from
440449
if let p2ai = address as? PointerToAddressInst {
441450
if let originatingAddr = pointerId.getOriginatingAddress(of: p2ai) {
@@ -446,15 +455,9 @@ struct AccessPathWalker {
446455
}
447456
}
448457

449-
// If this is a base then we're done
450-
if let base = AccessBase(baseAddress: address) {
451-
self.result = AccessPath(base: base, projectionPath: path.projectionPath)
452-
return .continueWalk
453-
}
454-
455-
// The base is unidentified
456-
self.result = nil
457-
return .abortWalk
458+
let base = AccessBase(baseAddress: address)
459+
self.result = AccessPath(base: base, projectionPath: path.projectionPath)
460+
return .continueWalk
458461
}
459462

460463
mutating func walkUp(address: Value, path: Path) -> WalkResult {
@@ -464,7 +467,6 @@ struct AccessPathWalker {
464467
} else if path.indexAddr && !canBeOperandOfIndexAddr(address) {
465468
// An `index_addr` instruction cannot be derived from an address
466469
// projection. Bail out
467-
self.result = nil
468470
return .abortWalk
469471
} else if let ba = address as? BeginAccessInst, foundBeginAccess == nil {
470472
foundBeginAccess = ba
@@ -496,7 +498,7 @@ extension AccessStoragePathWalker {
496498
return walkUp(value: rea.operand, path: path.push(.classField, index: rea.fieldIndex)) != .abortWalk
497499
case .tail(let rta):
498500
return walkUp(value: rta.operand, path: path.push(.tailElements, index: 0)) != .abortWalk
499-
case .stack, .global, .argument, .yield, .pointer:
501+
case .stack, .global, .argument, .yield, .pointer, .unidentified:
500502
return false
501503
}
502504
}

0 commit comments

Comments
 (0)