@@ -103,11 +103,33 @@ public enum AccessBase : CustomStringConvertible, Hashable {
103103 }
104104 case let sb as StoreBorrowInst :
105105 self = . storeBorrow( sb)
106+ case let p2a as PointerToAddressInst :
107+ if let global = p2a. resultOfGlobalAddressorCall {
108+ self = . global( global)
109+ } else {
110+ self = . pointer( p2a)
111+ }
106112 default :
107113 self = . unidentified
108114 }
109115 }
110116
117+ /// Return 'nil' for global varabiables and unidentified addresses.
118+ public var address : Value ? {
119+ switch self {
120+ case . global, . unidentified: return nil
121+ case . box( let pbi) : return pbi
122+ case . stack( let asi) : return asi
123+ case . class( let rea) : return rea
124+ case . tail( let rta) : return rta
125+ case . argument( let arg) : return arg
126+ case . yield( let result) : return result
127+ case . storeBorrow( let sb) : return sb
128+ case . pointer( let p) : return p
129+ case . index( let ia) : return ia
130+ }
131+ }
132+
111133 public var description : String {
112134 switch self {
113135 case . unidentified: return " ? "
@@ -480,9 +502,40 @@ public enum EnclosingScope {
480502 case base( AccessBase )
481503}
482504
505+ private struct EnclosingAccessWalker : AddressUseDefWalker {
506+ var enclosingScope : EnclosingScope ?
507+
508+ mutating func walk( startAt address: Value , initialPath: UnusedWalkingPath = UnusedWalkingPath ( ) ) {
509+ if walkUp ( address: address, path: UnusedWalkingPath ( ) ) == . abortWalk {
510+ assert ( enclosingScope == nil , " shouldn't have set an enclosing scope in an aborted walk " )
511+ }
512+ }
513+
514+ mutating func rootDef( address: Value , path: UnusedWalkingPath ) -> WalkResult {
515+ assert ( enclosingScope == nil , " rootDef should only called once " )
516+ // Try identifying the address a pointer originates from
517+ if let p2ai = address as? PointerToAddressInst , let originatingAddr = p2ai. originatingAddress {
518+ return walkUp ( address: originatingAddr, path: path)
519+ }
520+ enclosingScope = . base( AccessBase ( baseAddress: address) )
521+ return . continueWalk
522+ }
523+
524+ mutating func walkUp( address: Value , path: UnusedWalkingPath ) -> WalkResult {
525+ if let ba = address as? BeginAccessInst {
526+ enclosingScope = . scope( ba)
527+ return . continueWalk
528+ }
529+ return walkUpDefault ( address: address, path: path)
530+ }
531+ }
532+
483533private struct AccessPathWalker : AddressUseDefWalker {
484534 var result = AccessPath . unidentified ( )
485- var foundBeginAccess : BeginAccessInst ?
535+
536+ // List of nested BeginAccessInst: inside-out order.
537+ var foundBeginAccesses = SingleInlineArray < BeginAccessInst > ( )
538+
486539 let enforceConstantProjectionPath : Bool
487540
488541 init ( enforceConstantProjectionPath: Bool = false ) {
@@ -528,18 +581,9 @@ private struct AccessPathWalker : AddressUseDefWalker {
528581 mutating func rootDef( address: Value , path: Path ) -> WalkResult {
529582 assert ( result. base == . unidentified, " rootDef should only called once " )
530583 // Try identifying the address a pointer originates from
531- if let p2ai = address as? PointerToAddressInst {
532- if let originatingAddr = p2ai. originatingAddress {
533- return walkUp ( address: originatingAddr, path: path)
534- } else if let global = p2ai. resultOfGlobalAddressorCall {
535- self . result = AccessPath ( base: . global( global) , projectionPath: path. projectionPath)
536- return . continueWalk
537- } else {
538- self . result = AccessPath ( base: . pointer( p2ai) , projectionPath: path. projectionPath)
539- return . continueWalk
540- }
584+ if let p2ai = address as? PointerToAddressInst , let originatingAddr = p2ai. originatingAddress {
585+ return walkUp ( address: originatingAddr, path: path)
541586 }
542-
543587 let base = AccessBase ( baseAddress: address)
544588 self . result = AccessPath ( base: base, projectionPath: path. projectionPath)
545589 return . continueWalk
@@ -557,8 +601,8 @@ private struct AccessPathWalker : AddressUseDefWalker {
557601 // An `index_addr` instruction cannot be derived from an address
558602 // projection. Bail out
559603 return . abortWalk
560- } else if let ba = address as? BeginAccessInst , foundBeginAccess == nil {
561- foundBeginAccess = ba
604+ } else if let ba = address as? BeginAccessInst {
605+ foundBeginAccesses . push ( ba )
562606 }
563607 return walkUpDefault ( address: address, path: path. with ( indexAddr: false ) )
564608 }
@@ -611,17 +655,20 @@ extension Value {
611655 public var accessPathWithScope : ( AccessPath , scope: BeginAccessInst ? ) {
612656 var walker = AccessPathWalker ( )
613657 walker. walk ( startAt: self )
614- return ( walker. result, walker. foundBeginAccess )
658+ return ( walker. result, walker. foundBeginAccesses . first )
615659 }
616660
617661 /// Computes the enclosing access scope of this address value.
618662 public var enclosingAccessScope : EnclosingScope {
663+ var walker = EnclosingAccessWalker ( )
664+ walker. walk ( startAt: self )
665+ return walker. enclosingScope ?? . base( . unidentified)
666+ }
667+
668+ public var accessBaseWithScopes : ( AccessBase , SingleInlineArray < BeginAccessInst > ) {
619669 var walker = AccessPathWalker ( )
620670 walker. walk ( startAt: self )
621- if let ba = walker. foundBeginAccess {
622- return . scope( ba)
623- }
624- return . base( walker. result. base)
671+ return ( walker. result. base, walker. foundBeginAccesses)
625672 }
626673
627674 /// The root definition of a reference, obtained by skipping ownership forwarding and ownership transition.
0 commit comments