|
21 | 21 | /// |
22 | 22 | /// 3. Stored properties in heap objects or global variables. These are always formally accessed. |
23 | 23 | /// |
| 24 | +/// Pass dependencies: |
| 25 | +/// |
| 26 | +/// AccessEnforcementSelection must run first to correctly determine which non-esacping closure captures may have |
| 27 | +/// escaped prior to the closure invocation. Any access to an inout_aliasable argument that may have escaped in the |
| 28 | +/// caller will be marked [dynamic]. |
| 29 | +/// |
24 | 30 | //===----------------------------------------------------------------------===// |
25 | 31 |
|
26 | 32 | import SIL |
@@ -287,6 +293,9 @@ struct LocalVariableAccessMap: Collection, CustomStringConvertible { |
287 | 293 |
|
288 | 294 | var isBoxed: Bool { allocation is AllocBoxInst } |
289 | 295 |
|
| 296 | + // If 'mayAlias' is true (@inout_aliasable), then this variable may have escaped before entering the current |
| 297 | + // function. 'walkAccesses' determines whether this allocation is considered to have escaped on entry by checked for |
| 298 | + // the existienced of begin_access [dynamic]. |
290 | 299 | var mayAlias: Bool { |
291 | 300 | if let arg = allocation as? FunctionArgument, arg.convention == .indirectInoutAliasable { |
292 | 301 | return true |
@@ -324,18 +333,26 @@ struct LocalVariableAccessMap: Collection, CustomStringConvertible { |
324 | 333 | if walker.walkDown(allocation: allocation) == .abortWalk { |
325 | 334 | return .abortWalk |
326 | 335 | } |
| 336 | + var escapedOnEntry = false |
327 | 337 | for localAccess in walker.accessStack { |
328 | 338 | let info = LocalVariableAccessInfo(localAccess: localAccess) |
329 | | - if mayAlias { |
330 | | - // Local allocations can only escape prior to assignment if they are boxed or inout_aliasable. |
331 | | - info.hasEscaped = true |
332 | | - } else if !isBoxed { |
| 339 | + // inout_aliasable "allocation" has escaped on entry if any begin_access [dynamic] is present. |
| 340 | + if mayAlias, info.access.kind == .beginAccess, |
| 341 | + (localAccess.instruction as! BeginAccessInst).enforcement == .dynamic { |
| 342 | + escapedOnEntry = true |
| 343 | + } |
| 344 | + if !isBoxed { |
333 | 345 | // Boxed allocation requires reachability to determine whether the box escaped prior to assignment. |
334 | 346 | info.hasEscaped = info.isEscape |
335 | 347 | } |
336 | 348 | accessMap[localAccess.instruction!] = info |
337 | 349 | accessList.append(info) |
338 | 350 | } |
| 351 | + if escapedOnEntry { |
| 352 | + for accessInfo in accessList { |
| 353 | + accessInfo.hasEscaped = true |
| 354 | + } |
| 355 | + } |
339 | 356 | return .continueWalk |
340 | 357 | } |
341 | 358 |
|
|
0 commit comments