@@ -903,10 +903,124 @@ extension Function {
903903 }
904904}
905905
906+ //===--------------------------------------------------------------------===//
907+ // Tests
908+ //===--------------------------------------------------------------------===//
909+
906910let getAccessBaseTest = Test ( " swift_get_access_base " ) {
907911 function, arguments, context in
908912 let address = arguments. takeValue ( )
909913 print ( " Address: \( address) " )
910914 let base = address. accessBase
911915 print ( " Base: \( base) " )
912916}
917+
918+ let accessPathTest = Test ( " access_path " ) {
919+ function, arguments, context in
920+
921+ // Prints access path information for memory accesses (`load` and `store`) instructions.
922+ // Also verifies that `AccessPath.isDistinct(from:)` is correct.
923+
924+ print ( " Accesses for \( function. name) " )
925+
926+ for block in function. blocks {
927+ for instr in block. instructions {
928+ switch instr {
929+ case let st as StoreInst :
930+ printAccessInfo ( address: st. destination)
931+ case let load as LoadInst :
932+ printAccessInfo ( address: load. address)
933+ case let apply as ApplyInst :
934+ guard let callee = apply. referencedFunction else {
935+ break
936+ }
937+ if callee. name == " _isDistinct " {
938+ checkAliasInfo ( forArgumentsOf: apply, expectDistinct: true )
939+ } else if callee. name == " _isNotDistinct " {
940+ checkAliasInfo ( forArgumentsOf: apply, expectDistinct: false )
941+ }
942+ default :
943+ break
944+ }
945+ }
946+ }
947+
948+ print ( " End accesses for \( function. name) " )
949+ }
950+
951+ private struct AccessStoragePathVisitor : ValueUseDefWalker {
952+ var walkUpCache = WalkerCache < Path > ( )
953+ mutating func rootDef( value: Value , path: SmallProjectionPath ) -> WalkResult {
954+ print ( " Storage: \( value) " )
955+ print ( " Path: \" \( path) \" " )
956+ return . continueWalk
957+ }
958+ }
959+
960+ private func printAccessInfo( address: Value ) {
961+ print ( " Value: \( address) " )
962+
963+ let ( ap, scope) = address. accessPathWithScope
964+ if let beginAccess = scope {
965+ print ( " Scope: \( beginAccess) " )
966+ } else {
967+ print ( " Scope: base " )
968+ }
969+
970+ let constAp = address. constantAccessPath
971+ if constAp == ap {
972+ print ( " Base: \( ap. base) " )
973+ print ( " Path: \" \( ap. projectionPath) \" " )
974+ } else {
975+ print ( " nonconst-base: \( ap. base) " )
976+ print ( " nonconst-path: \" \( ap. projectionPath) \" " )
977+ print ( " const-base: \( constAp. base) " )
978+ print ( " const-path: \" \( constAp. projectionPath) \" " )
979+ }
980+
981+ var arw = AccessStoragePathVisitor ( )
982+ if !arw. visitAccessStorageRoots ( of: ap) {
983+ print ( " no Storage paths " )
984+ }
985+ }
986+
987+ private func checkAliasInfo( forArgumentsOf apply: ApplyInst , expectDistinct: Bool ) {
988+ let address1 = apply. arguments [ 0 ]
989+ let address2 = apply. arguments [ 1 ]
990+
991+ checkIsDistinct ( path1: address1. accessPath,
992+ path2: address2. accessPath,
993+ expectDistinct: expectDistinct,
994+ instruction: apply)
995+
996+ if !expectDistinct {
997+ // Also check all combinations with the constant variant of access paths.
998+ // Note: we can't do that for "isDistinct" because "isDistinct" might be more conservative in one of the variants.
999+ checkIsDistinct ( path1: address1. constantAccessPath,
1000+ path2: address2. constantAccessPath,
1001+ expectDistinct: false ,
1002+ instruction: apply)
1003+ checkIsDistinct ( path1: address1. accessPath,
1004+ path2: address2. constantAccessPath,
1005+ expectDistinct: false ,
1006+ instruction: apply)
1007+ checkIsDistinct ( path1: address1. constantAccessPath,
1008+ path2: address2. accessPath,
1009+ expectDistinct: false ,
1010+ instruction: apply)
1011+ }
1012+ }
1013+
1014+ private func checkIsDistinct( path1: AccessPath , path2: AccessPath , expectDistinct: Bool , instruction: Instruction ) {
1015+ if path1. isDistinct ( from: path2) != expectDistinct {
1016+ print ( " wrong isDistinct result of \( instruction) " )
1017+ } else if path2. isDistinct ( from: path1) != expectDistinct {
1018+ print ( " wrong reverse isDistinct result of \( instruction) " )
1019+ } else {
1020+ return
1021+ }
1022+
1023+ print ( " in function " )
1024+ print ( instruction. parentFunction)
1025+ fatalError ( )
1026+ }
0 commit comments