@@ -103,11 +103,33 @@ public enum AccessBase : CustomStringConvertible, Hashable {
103
103
}
104
104
case let sb as StoreBorrowInst :
105
105
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
+ }
106
112
default :
107
113
self = . unidentified
108
114
}
109
115
}
110
116
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
+
111
133
public var description : String {
112
134
switch self {
113
135
case . unidentified: return " ? "
@@ -480,9 +502,40 @@ public enum EnclosingScope {
480
502
case base( AccessBase )
481
503
}
482
504
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
+
483
533
private struct AccessPathWalker : AddressUseDefWalker {
484
534
var result = AccessPath . unidentified ( )
485
- var foundBeginAccess : BeginAccessInst ?
535
+
536
+ // List of nested BeginAccessInst: inside-out order.
537
+ var foundBeginAccesses = SingleInlineArray < BeginAccessInst > ( )
538
+
486
539
let enforceConstantProjectionPath : Bool
487
540
488
541
init ( enforceConstantProjectionPath: Bool = false ) {
@@ -528,18 +581,9 @@ private struct AccessPathWalker : AddressUseDefWalker {
528
581
mutating func rootDef( address: Value , path: Path ) -> WalkResult {
529
582
assert ( result. base == . unidentified, " rootDef should only called once " )
530
583
// 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)
541
586
}
542
-
543
587
let base = AccessBase ( baseAddress: address)
544
588
self . result = AccessPath ( base: base, projectionPath: path. projectionPath)
545
589
return . continueWalk
@@ -557,8 +601,8 @@ private struct AccessPathWalker : AddressUseDefWalker {
557
601
// An `index_addr` instruction cannot be derived from an address
558
602
// projection. Bail out
559
603
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 )
562
606
}
563
607
return walkUpDefault ( address: address, path: path. with ( indexAddr: false ) )
564
608
}
@@ -611,17 +655,20 @@ extension Value {
611
655
public var accessPathWithScope : ( AccessPath , scope: BeginAccessInst ? ) {
612
656
var walker = AccessPathWalker ( )
613
657
walker. walk ( startAt: self )
614
- return ( walker. result, walker. foundBeginAccess )
658
+ return ( walker. result, walker. foundBeginAccesses . first )
615
659
}
616
660
617
661
/// Computes the enclosing access scope of this address value.
618
662
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 > ) {
619
669
var walker = AccessPathWalker ( )
620
670
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)
625
672
}
626
673
627
674
/// The root definition of a reference, obtained by skipping ownership forwarding and ownership transition.
0 commit comments