@@ -65,7 +65,7 @@ struct AliasAnalysis {
6565 AliasAnalysis_register (
6666 // getMemEffectsFn
6767 { ( bridgedCtxt: BridgedPassContext , bridgedVal: BridgedValue , bridgedInst: BridgedInstruction ) -> BridgedMemoryBehavior in
68- let context = PassContext ( _bridged: bridgedCtxt)
68+ let context = FunctionPassContext ( _bridged: bridgedCtxt)
6969 let inst = bridgedInst. instruction
7070 let val = bridgedVal. value
7171 let path = AliasAnalysis . getPtrOrAddressPath ( for: val)
@@ -78,28 +78,28 @@ struct AliasAnalysis {
7878 case ( true , true ) : return MayReadWriteBehavior
7979 }
8080 }
81- if val. at ( path) . isAddressEscaping ( using: EscapesToInstructionVisitor ( target: inst) , context) {
81+ if val. at ( path) . isEscaping ( using: EscapesToInstructionVisitor ( target: inst, isAddress : true ) , context) {
8282 return MayReadWriteBehavior
8383 }
8484 return NoneBehavior
8585 } ,
8686
8787 // isObjReleasedFn
8888 { ( bridgedCtxt: BridgedPassContext , bridgedObj: BridgedValue , bridgedInst: BridgedInstruction ) -> Bool in
89- let context = PassContext ( _bridged: bridgedCtxt)
89+ let context = FunctionPassContext ( _bridged: bridgedCtxt)
9090 let inst = bridgedInst. instruction
9191 let obj = bridgedObj. value
9292 let path = SmallProjectionPath ( . anyValueFields)
9393 if let apply = inst as? ApplySite {
9494 let effect = getOwnershipEffect ( of: apply, for: obj, path: path, context)
9595 return effect. destroy
9696 }
97- return obj. at ( path) . isEscaping ( using: EscapesToInstructionVisitor ( target: inst) , context)
97+ return obj. at ( path) . isEscaping ( using: EscapesToInstructionVisitor ( target: inst, isAddress : false ) , context)
9898 } ,
9999
100100 // isAddrVisibleFromObj
101101 { ( bridgedCtxt: BridgedPassContext , bridgedAddr: BridgedValue , bridgedObj: BridgedValue ) -> Bool in
102- let context = PassContext ( _bridged: bridgedCtxt)
102+ let context = FunctionPassContext ( _bridged: bridgedCtxt)
103103 let addr = bridgedAddr. value. at ( AliasAnalysis . getPtrOrAddressPath ( for: bridgedAddr. value) )
104104
105105 // This is similar to `canReferenceSameFieldFn`, except that all addresses of all objects are
@@ -110,7 +110,7 @@ struct AliasAnalysis {
110110
111111 // canReferenceSameFieldFn
112112 { ( bridgedCtxt: BridgedPassContext , bridgedLhs: BridgedValue , bridgedRhs: BridgedValue ) -> Bool in
113- let context = PassContext ( _bridged: bridgedCtxt)
113+ let context = FunctionPassContext ( _bridged: bridgedCtxt)
114114
115115 // If `lhs` or `rhs` is not an address, but an object, it means: check for alias of any class
116116 // field address of the object.
@@ -122,13 +122,13 @@ struct AliasAnalysis {
122122 }
123123}
124124
125- private func getMemoryEffect( of apply: ApplySite , for address: Value , path: SmallProjectionPath , _ context: PassContext ) -> SideEffects . Memory {
125+ private func getMemoryEffect( of apply: ApplySite , for address: Value , path: SmallProjectionPath , _ context: FunctionPassContext ) -> SideEffects . Memory {
126126 let calleeAnalysis = context. calleeAnalysis
127- let visitor = SideEffectsVisitor ( apply: apply, calleeAnalysis: calleeAnalysis)
127+ let visitor = SideEffectsVisitor ( apply: apply, calleeAnalysis: calleeAnalysis, isAddress : true )
128128 let memoryEffects : SideEffects . Memory
129129
130130 // First try to figure out to which argument(s) the address "escapes" to.
131- if let result = address. at ( path) . visitAddress ( using: visitor, context) {
131+ if let result = address. at ( path) . visit ( using: visitor, context) {
132132 // The resulting effects are the argument effects to which `address` escapes to.
133133 memoryEffects = result. memory
134134 } else {
@@ -145,8 +145,8 @@ private func getMemoryEffect(of apply: ApplySite, for address: Value, path: Smal
145145 return memoryEffects
146146}
147147
148- private func getOwnershipEffect( of apply: ApplySite , for value: Value , path: SmallProjectionPath , _ context: PassContext ) -> SideEffects . Ownership {
149- let visitor = SideEffectsVisitor ( apply: apply, calleeAnalysis: context. calleeAnalysis)
148+ private func getOwnershipEffect( of apply: ApplySite , for value: Value , path: SmallProjectionPath , _ context: FunctionPassContext ) -> SideEffects . Ownership {
149+ let visitor = SideEffectsVisitor ( apply: apply, calleeAnalysis: context. calleeAnalysis, isAddress : false )
150150 if let result = value. at ( path) . visit ( using: visitor, context) {
151151 // The resulting effects are the argument effects to which `value` escapes to.
152152 return result. ownership
@@ -159,6 +159,7 @@ private func getOwnershipEffect(of apply: ApplySite, for value: Value, path: Sma
159159private struct SideEffectsVisitor : EscapeVisitorWithResult {
160160 let apply : ApplySite
161161 let calleeAnalysis : CalleeAnalysis
162+ let isAddress : Bool
162163 var result = SideEffects . GlobalEffects ( )
163164
164165 mutating func visitUse( operand: Operand , path: EscapePath ) -> UseResult {
@@ -175,6 +176,30 @@ private struct SideEffectsVisitor : EscapeVisitorWithResult {
175176 }
176177 return . continueWalk
177178 }
179+
180+ var followTrivialTypes : Bool { isAddress }
181+ var followLoads : Bool { !isAddress }
182+ }
183+
184+ /// Lets `ProjectedValue.isEscaping` return true if the value is "escaping" to the `target` instruction.
185+ private struct EscapesToInstructionVisitor : EscapeVisitor {
186+ let target : Instruction
187+ let isAddress : Bool
188+
189+ mutating func visitUse( operand: Operand , path: EscapePath ) -> UseResult {
190+ let user = operand. instruction
191+ if user == target {
192+ return . abort
193+ }
194+ if user is ReturnInst {
195+ // Anything which is returned cannot escape to an instruction inside the function.
196+ return . ignore
197+ }
198+ return . continueWalk
199+ }
200+
201+ var followTrivialTypes : Bool { isAddress }
202+ var followLoads : Bool { !isAddress }
178203}
179204
180205private extension Value {
0 commit comments