@@ -340,8 +340,15 @@ extension ValueDefUseWalker {
340
340
} else {
341
341
return unmatchedPath ( value: operand, path: path)
342
342
}
343
- case is InitExistentialRefInst , is OpenExistentialRefInst ,
344
- is BeginBorrowInst , is CopyValueInst , is MoveValueInst ,
343
+ case let ier as InitExistentialRefInst :
344
+ return walkDownUses ( ofValue: ier, path: path. push ( . existential, index: 0 ) )
345
+ case let oer as OpenExistentialRefInst :
346
+ if let path = path. popIfMatches ( . existential, index: 0 ) {
347
+ return walkDownUses ( ofValue: oer, path: path)
348
+ } else {
349
+ return unmatchedPath ( value: operand, path: path)
350
+ }
351
+ case is BeginBorrowInst , is CopyValueInst , is MoveValueInst ,
345
352
is UpcastInst , is UncheckedRefCastInst , is EndCOWMutationInst ,
346
353
is RefToBridgeObjectInst , is BridgeObjectToRefInst , is MarkMustCheckInst :
347
354
return walkDownUses ( ofValue: ( instruction as! SingleValueInstruction ) , path: path)
@@ -470,14 +477,23 @@ extension AddressDefUseWalker {
470
477
} else {
471
478
return unmatchedPath ( address: operand, path: path)
472
479
}
473
- case is InitExistentialAddrInst , is OpenExistentialAddrInst ,
474
- is IndexAddrInst , is MarkMustCheckInst :
475
- // FIXME: for now `index_addr` is treated as a forwarding instruction since
476
- // SmallProjectionPath does not track indices.
477
- // This is ok since `index_addr` is eventually preceeded by a `tail_addr`
478
- // which has pushed a `"ct"` component on the path that matches any
479
- // `index_addr` address.
480
- return walkDownUses ( ofAddress: instruction as! SingleValueInstruction , path: path)
480
+ case is InitExistentialAddrInst , is OpenExistentialAddrInst :
481
+ if let path = path. popIfMatches ( . existential, index: 0 ) {
482
+ return walkDownUses ( ofAddress: instruction as! SingleValueInstruction , path: path)
483
+ } else {
484
+ return unmatchedPath ( address: operand, path: path)
485
+ }
486
+ case let ia as IndexAddrInst :
487
+ if let ( pathIdx, subPath) = path. pop ( kind: . indexedElement) {
488
+ if let idx = ia. constantSmallIndex,
489
+ idx == pathIdx {
490
+ return walkDownUses ( ofAddress: ia, path: subPath)
491
+ }
492
+ return walkDownUses ( ofAddress: ia, path: subPath. push ( . anyIndexedElement, index: 0 ) )
493
+ }
494
+ return walkDownUses ( ofAddress: ia, path: path)
495
+ case let mmc as MarkMustCheckInst :
496
+ return walkDownUses ( ofAddress: mmc, path: path)
481
497
case let ba as BeginAccessInst :
482
498
// Don't treat `end_access` as leaf-use. Just ignore it.
483
499
return walkDownNonEndAccessUses ( of: ba, path: path)
@@ -630,8 +646,15 @@ extension ValueUseDefWalker {
630
646
} else {
631
647
return rootDef ( value: mvr, path: path)
632
648
}
633
- case is InitExistentialRefInst , is OpenExistentialRefInst ,
634
- is BeginBorrowInst , is CopyValueInst , is MoveValueInst ,
649
+ case let ier as InitExistentialRefInst :
650
+ if let path = path. popIfMatches ( . existential, index: 0 ) {
651
+ return walkUp ( value: ier. instance, path: path)
652
+ } else {
653
+ return unmatchedPath ( value: ier, path: path)
654
+ }
655
+ case let oer as OpenExistentialRefInst :
656
+ return walkUp ( value: oer. existential, path: path. push ( . existential, index: 0 ) )
657
+ case is BeginBorrowInst , is CopyValueInst , is MoveValueInst ,
635
658
is UpcastInst , is UncheckedRefCastInst , is EndCOWMutationInst ,
636
659
is RefToBridgeObjectInst , is BridgeObjectToRefInst , is MarkMustCheckInst :
637
660
return walkUp ( value: ( def as! Instruction ) . operands [ 0 ] . value, path: path)
@@ -718,18 +741,34 @@ extension AddressUseDefWalker {
718
741
case is InitEnumDataAddrInst , is UncheckedTakeEnumDataAddrInst :
719
742
return walkUp ( address: ( def as! UnaryInstruction ) . operand. value,
720
743
path: path. push ( . enumCase, index: ( def as! EnumInstruction ) . caseIndex) )
721
- case is InitExistentialAddrInst , is OpenExistentialAddrInst , is BeginAccessInst , is IndexAddrInst ,
722
- is MarkMustCheckInst :
723
- // FIXME: for now `index_addr` is treated as a forwarding instruction since
724
- // SmallProjectionPath does not track indices.
725
- // This is ok since `index_addr` is eventually preceeded by a `tail_addr`
726
- // which has pushed a `"ct"` component on the path that matches any
727
- // `index_addr` address.
744
+ case is InitExistentialAddrInst , is OpenExistentialAddrInst :
745
+ return walkUp ( address: ( def as! Instruction ) . operands [ 0 ] . value, path: path. push ( . existential, index: 0 ) )
746
+ case is BeginAccessInst , is MarkMustCheckInst :
728
747
return walkUp ( address: ( def as! Instruction ) . operands [ 0 ] . value, path: path)
748
+ case let ia as IndexAddrInst :
749
+ if let idx = ia. constantSmallIndex {
750
+ return walkUp ( address: ia. base, path: path. push ( . indexedElement, index: idx) )
751
+ } else {
752
+ return walkUp ( address: ia. base, path: path. push ( . anyIndexedElement, index: 0 ) )
753
+ }
729
754
case let mdi as MarkDependenceInst :
730
755
return walkUp ( address: mdi. operands [ 0 ] . value, path: path)
731
756
default :
732
757
return rootDef ( address: def, path: path)
733
758
}
734
759
}
735
760
}
761
+
762
+ private extension IndexAddrInst {
763
+ var constantSmallIndex : Int ? {
764
+ guard let literal = index as? IntegerLiteralInst else {
765
+ return nil
766
+ }
767
+ let index = literal. value
768
+ if index. isIntN ( 16 ) {
769
+ return Int ( index. getSExtValue ( ) )
770
+ }
771
+ return nil
772
+ }
773
+ }
774
+
0 commit comments