@@ -337,108 +337,75 @@ enum EnclosingScope {
337
337
case base( AccessBase )
338
338
}
339
339
340
- /// A walker utility that, given an address value, computes the `AccessPath`
341
- /// of the access (the base address and the address projections to the accessed fields) and
342
- /// the innermost enclosing scope (`begin_access`).
343
- struct AccessPathWalker {
344
- mutating func getAccessPath( of address: Value ) -> AccessPath {
345
- assert ( address. type. isAddress, " Expected address " )
346
- walker. start ( )
347
- if walker. walkUp ( address: address, path: Walker . Path ( ) ) == . abortWalk {
348
- assert ( walker. result. base == . unidentified,
340
+ private struct AccessPathWalker : AddressUseDefWalker {
341
+ var result = AccessPath . unidentified ( )
342
+ var foundBeginAccess : BeginAccessInst ?
343
+
344
+ mutating func walk( startAt address: Value , initialPath: SmallProjectionPath = SmallProjectionPath ( ) ) {
345
+ if walkUp ( address: address, path: Path ( projectionPath: initialPath) ) == . abortWalk {
346
+ assert ( result. base == . unidentified,
349
347
" shouldn't have set an access base in an aborted walk " )
350
348
}
351
- return walker. result
352
349
}
353
350
354
- mutating func getAccessPathWithScope( of address: Value ) -> ( AccessPath , scope: BeginAccessInst ? ) {
355
- let ap = getAccessPath ( of: address)
356
- return ( ap, walker. foundBeginAccess)
357
- }
351
+ struct Path : SmallProjectionWalkingPath {
352
+ let projectionPath : SmallProjectionPath
358
353
359
- mutating func getAccessBase( of address: Value ) -> AccessBase {
360
- getAccessPath ( of: address) . base
361
- }
354
+ // Tracks whether an `index_addr` instruction was crossed.
355
+ // It should be (FIXME: check if it's enforced) that operands
356
+ // of `index_addr` must be `tail_addr` or other `index_addr` results.
357
+ let indexAddr : Bool
362
358
363
- mutating func getEnclosingScope( of address: Value ) -> EnclosingScope {
364
- let accessPath = getAccessPath ( of: address)
365
-
366
- if let ba = walker. foundBeginAccess {
367
- return . scope( ba)
359
+ init ( projectionPath: SmallProjectionPath = SmallProjectionPath ( ) , indexAddr: Bool = false ) {
360
+ self . projectionPath = projectionPath
361
+ self . indexAddr = indexAddr
368
362
}
369
- return . base( accessPath. base)
370
- }
371
-
372
- private var walker = Walker ( )
373
-
374
- private struct Walker : AddressUseDefWalker {
375
- private( set) var result = AccessPath . unidentified ( )
376
- private( set) var foundBeginAccess : BeginAccessInst ?
377
363
378
- mutating func start( ) {
379
- result = . unidentified( )
380
- foundBeginAccess = nil
364
+ func with( projectionPath: SmallProjectionPath ) -> Self {
365
+ return Self ( projectionPath: projectionPath, indexAddr: indexAddr)
381
366
}
382
367
383
- struct Path : SmallProjectionWalkingPath {
384
- let projectionPath : SmallProjectionPath
385
-
386
- // Tracks whether an `index_addr` instruction was crossed.
387
- // It should be (FIXME: check if it's enforced) that operands
388
- // of `index_addr` must be `tail_addr` or other `index_addr` results.
389
- let indexAddr : Bool
390
-
391
- init ( projectionPath: SmallProjectionPath = SmallProjectionPath ( ) , indexAddr: Bool = false ) {
392
- self . projectionPath = projectionPath
393
- self . indexAddr = indexAddr
394
- }
395
-
396
- func with( projectionPath: SmallProjectionPath ) -> Self {
397
- return Self ( projectionPath: projectionPath, indexAddr: indexAddr)
398
- }
399
-
400
- func with( indexAddr: Bool ) -> Self {
401
- return Self ( projectionPath: projectionPath, indexAddr: indexAddr)
402
- }
368
+ func with( indexAddr: Bool ) -> Self {
369
+ return Self ( projectionPath: projectionPath, indexAddr: indexAddr)
370
+ }
403
371
404
- func merge( with other: Self ) -> Self {
405
- return Self (
406
- projectionPath: projectionPath. merge ( with: other. projectionPath) ,
407
- indexAddr: indexAddr || other. indexAddr
408
- )
409
- }
372
+ func merge( with other: Self ) -> Self {
373
+ return Self (
374
+ projectionPath: projectionPath. merge ( with: other. projectionPath) ,
375
+ indexAddr: indexAddr || other. indexAddr
376
+ )
410
377
}
378
+ }
411
379
412
- mutating func rootDef( address: Value , path: Path ) -> WalkResult {
413
- assert ( result. base == . unidentified, " rootDef should only called once " )
414
- // Try identifying the address a pointer originates from
415
- if let p2ai = address as? PointerToAddressInst {
416
- if let originatingAddr = p2ai. originatingAddress {
417
- return walkUp ( address: originatingAddr, path: path)
418
- } else {
419
- self . result = AccessPath ( base: . pointer( p2ai) , projectionPath: path. projectionPath)
420
- return . continueWalk
421
- }
380
+ mutating func rootDef( address: Value , path: Path ) -> WalkResult {
381
+ assert ( result. base == . unidentified, " rootDef should only called once " )
382
+ // Try identifying the address a pointer originates from
383
+ if let p2ai = address as? PointerToAddressInst {
384
+ if let originatingAddr = p2ai. originatingAddress {
385
+ return walkUp ( address: originatingAddr, path: path)
386
+ } else {
387
+ self . result = AccessPath ( base: . pointer( p2ai) , projectionPath: path. projectionPath)
388
+ return . continueWalk
422
389
}
423
-
424
- let base = AccessBase ( baseAddress: address)
425
- self . result = AccessPath ( base: base, projectionPath: path. projectionPath)
426
- return . continueWalk
427
390
}
428
391
429
- mutating func walkUp( address: Value , path: Path ) -> WalkResult {
430
- if address is IndexAddrInst {
431
- // Track that we crossed an `index_addr` during the walk-up
432
- return walkUpDefault ( address: address, path: path. with ( indexAddr: true ) )
433
- } else if path. indexAddr && !canBeOperandOfIndexAddr( address) {
434
- // An `index_addr` instruction cannot be derived from an address
435
- // projection. Bail out
436
- return . abortWalk
437
- } else if let ba = address as? BeginAccessInst , foundBeginAccess == nil {
438
- foundBeginAccess = ba
439
- }
440
- return walkUpDefault ( address: address, path: path. with ( indexAddr: false ) )
392
+ let base = AccessBase ( baseAddress: address)
393
+ self . result = AccessPath ( base: base, projectionPath: path. projectionPath)
394
+ return . continueWalk
395
+ }
396
+
397
+ mutating func walkUp( address: Value , path: Path ) -> WalkResult {
398
+ if address is IndexAddrInst {
399
+ // Track that we crossed an `index_addr` during the walk-up
400
+ return walkUpDefault ( address: address, path: path. with ( indexAddr: true ) )
401
+ } else if path. indexAddr && !canBeOperandOfIndexAddr( address) {
402
+ // An `index_addr` instruction cannot be derived from an address
403
+ // projection. Bail out
404
+ return . abortWalk
405
+ } else if let ba = address as? BeginAccessInst , foundBeginAccess == nil {
406
+ foundBeginAccess = ba
441
407
}
408
+ return walkUpDefault ( address: address, path: path. with ( indexAddr: false ) )
442
409
}
443
410
}
444
411
@@ -451,27 +418,36 @@ extension Value {
451
418
// go through phi-arguments, the AccessPathWalker will allocate memnory in its cache.
452
419
453
420
/// Computes the access base of this address value.
454
- var accessBase : AccessBase {
455
- var apWalker = AccessPathWalker ( )
456
- return apWalker. getAccessBase ( of: self )
457
- }
421
+ var accessBase : AccessBase { accessPath. base }
458
422
459
423
/// Computes the access path of this address value.
460
424
var accessPath : AccessPath {
461
- var apWalker = AccessPathWalker ( )
462
- return apWalker. getAccessPath ( of: self )
425
+ var walker = AccessPathWalker ( )
426
+ walker. walk ( startAt: self )
427
+ return walker. result
428
+ }
429
+
430
+ func getAccessPath( fromInitialPath: SmallProjectionPath ) -> AccessPath {
431
+ var walker = AccessPathWalker ( )
432
+ walker. walk ( startAt: self , initialPath: fromInitialPath)
433
+ return walker. result
463
434
}
464
435
465
436
/// Computes the access path of this address value and also returns the scope.
466
437
var accessPathWithScope : ( AccessPath , scope: BeginAccessInst ? ) {
467
- var apWalker = AccessPathWalker ( )
468
- return apWalker. getAccessPathWithScope ( of: self )
438
+ var walker = AccessPathWalker ( )
439
+ walker. walk ( startAt: self )
440
+ return ( walker. result, walker. foundBeginAccess)
469
441
}
470
442
471
443
/// Computes the enclosing access scope of this address value.
472
444
var enclosingAccessScope : EnclosingScope {
473
- var apWalker = AccessPathWalker ( )
474
- return apWalker. getEnclosingScope ( of: self )
445
+ var walker = AccessPathWalker ( )
446
+ walker. walk ( startAt: self )
447
+ if let ba = walker. foundBeginAccess {
448
+ return . scope( ba)
449
+ }
450
+ return . base( walker. result. base)
475
451
}
476
452
}
477
453
0 commit comments