Commit Graph

76 Commits

Author SHA1 Message Date
Andrew Trick
060364546a [NFC] LifetimeDependenceUtils comment 2025-04-25 17:58:23 -07:00
Andrew Trick
5831777407 Fix LifetimeDependenceDiagnostics: handle address-only 'let's
Add a case to LifetimeDependence.Scope to support dependencies on address-only
'let' variables. This comes up with C++ interop.

Fixes rdar://147500193 (Spurious lifetime error with closures)
2025-04-23 22:48:27 -07:00
Andrew Trick
a1aaed9159 LifetimeDependenceScopeFixup: handle returning dependent Optional
Add support for returnValue phis (e.g. to return an Optional .some or .none).

Fixes rdar://149397018 (Wrapping non escapable in an Optional
(or any copy lifetime wrapper) is an escape)
2025-04-21 22:33:38 -07:00
Andrew Trick
6f8605263d Fix unidentified LifetimeDependence.Scope initialization.
Fixes rdar://149226564 (Compiler crash with non-escapable storing another
non-escapable and having a deinit)
2025-04-16 16:46:38 -07:00
Andrew Trick
4e35d255ad LocalVariableUtils: add store_borrow access tracking.
We sometimes use LocalVariableUtils to analyze temporary storage in which the
store_borrow is not already enclosed by an access scope.
2025-04-16 16:46:38 -07:00
Andrew Trick
b80bd16eea [NFC] Add LifetimeDependenceUseDefWalker utility.
Refactor VariableIntroducerUseDefWalker into a general
LifetimeDependenceUseDefWalker for use with LifetimeDependenceScopeFixup.
2025-04-16 16:43:23 -07:00
Andrew Trick
2bdaa68e98 SwiftCompilerSources: add IgnoredUseInst as incidental
Fixes rdar://148540048 (Assigning span value to `_` results in an incorrect escape diagnostic)
2025-04-16 16:42:36 -07:00
Andrew Trick
c9279d9899 Fix AddressOwnershipLiveRange to include the full range.
This allows further extension of access scopes.

Fixes rdar://143992296 (Use of `RawSpan` in switch context causes compiler crash
in AddressOwnershipLiveRange)
2025-04-11 23:49:07 -07:00
Andrew Trick
69b6b1d309 LifetimeDependenceDefUseWalker: handle addressable dependencies 2025-03-25 23:02:45 -07:00
Andrew Trick
d9dd93560d Support mark_dependence_addr in SIL passes. 2025-03-25 23:02:45 -07:00
Andrew Trick
ea8cb3c1b4 LifetimeDependenceDiagnostics: recognize store_borrow ranges
Avoid an unnecessary diagnostic when the dependent value's uses are covered by a
StoreBorrow.
2025-03-20 12:17:24 -07:00
Andrew Trick
b3f401d346 LifetimeDependenceScopeFixup: handle indirect yields & fix bugs
Handle coroutines that yield an address. Fix bugs involving extension of
multiple nested scopes that depend on multiple coroutine operands.
2025-03-05 02:12:21 -08:00
Andrew Trick
3019c843be LifetimeDependence: allow dependence on the store_borrow address
Previously, the dependence was on the stored value, but that is incorrect for
'@'_addressable parameters.
2025-03-03 11:56:37 -08:00
Andrew Trick
bc6200e592 SwiftCompilerSources: bridge '@'_addressable dependencies 2025-03-03 11:56:37 -08:00
Andrew Trick
f1792d80b3 Fix BorrowingOperand.visitScopeEndingUses
Only return false if the visitor returns false. Clients were ignoring the
result.

If the BorrowingOperand does not create a borrow scope, call visitUnknownUse
instead.

Until we have complete lifetimes, to avoid breaking code that cannot handle dead
defs, consider a dead borrow scope to be an unknown use.
2025-02-25 23:08:54 -08:00
Andrew Trick
fda53929c2 Add support for borrowed-from to BorrowingInstruction.
All instructions with a "Borrow" operand ownership must be valid
BorrowingInstructions.
2025-02-25 23:08:54 -08:00
Andrew Trick
fa3ebb5c1e LifetimeDependence.Scope add global variable support.
This fixes functions that return @lifetime(immortal).
2025-02-10 09:11:22 -08:00
Andrew Trick
39bae0bb58 LifetimeDependenceDiagnostics: immortal dependence on global 'let' 2025-02-10 09:11:22 -08:00
Andrew Trick
c3de120ca5 LifetimeDependence: simplify and fix multiple bugs.
Functional changes:

Improved modeling of dependence on local variable scopes.

For nested modify->read accesses, only extend the read accesses.

Avoid making a read access dependent on an inout argument.
The following needs to be an error to prevent span storage from being modified:

  @lifetime(owner)
  foo(owner: inout Owner) -> Span {
    owner.span
  }

Improve usability of borrowing trivial values (UnsafePointer). Allow:

  let span = Span(buffer.baseAddress)

Ignore access scopes for trivial values.

Structural changes:

Delete the LifetimeDependenceUseDefWalker.

Encapsulate all logic for variable introducers within the LifetimeDependenceInsertion pass. Once mark_dependence instructions are inserted, no subsequent pass needs to think about the "root" of a dependence.

Fixes: rdar://142451725 (Escape analysis fails with mutations)
2025-02-10 09:11:22 -08:00
Erik Eckstein
3ec5d7de24 SIL: replace the is_escaping_closure instruction with destroy_not_escaped_closure
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable.
For example, copy-propagation could break it.
As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`.
It
1. checks the reference count and returns true if it is 1
2. consumes and destroys the operand
2025-01-24 19:23:27 +01:00
Andrew Trick
cc07b4ba11 Fix LifetimeDependenceDiagnostics for @out dependencies.
Record a forwarding mark_dependence as a local access. This is necessary because
we now emit a mark_dependence for @out arguments, which will be the starting
point for diagnostics:

  %out = alloc_stack
  apply %f(%owned, %out) : $(Owner) -> @lifetime(borrow 0) @out View
  %unused = mark_dependence [unresolved] %out on %owner
  %dependentValue = load %out

This mark_dependence has no uses. Instead, it simply records the dependency of
the in-memory value on the owner. Consequently, simply walking the uses of
LifetimeDependence.dependentValue does fails to diagnose any escapes. Instead,
if the dependentValue is an address-type mark_dependence, treat it as a local
access to the address that it forwards. Then we find any reachable uses of that
local variable as a potential escape.

Fixes rdar://143040479
(Borrow diagnostics not triggered for @out return values)
2025-01-17 11:19:04 -08:00
Andrew Trick
c839e265df [NFC] Update an incomplete comment. 2025-01-15 16:53:03 -08:00
Andrew Trick
c8bec28e6a LifetimeDependence.Scope: recognize @in_guaranteed dependencies.
Unlike @in, treat @in_guaranteed like a caller-side dependence
scope because there is not need to look for the end of the lifetime in the
current function.

Completely fixes rdar://142847915 (Crash during lifetime checking
while building new swift standard library `Span`-related features)
2025-01-14 15:38:54 -08:00
Andrew Trick
6849b66bb3 LifetimeDependenceDiagnostics; remove a bootstrapping hack.
This temporary hack was preventing diagnostics from kicking in. This could even
result in invalid SIL after the diagnostic failed to trigger.
2025-01-13 08:30:41 -08:00
Andrew Trick
0326c98f72 LifetimeDependenceScopeFixup: handle unsafe addressors
Handle unsafe addressors just like projections of stored properties rather than
as separate variable accesses.
2025-01-11 15:40:22 -08:00
Andrew Trick
b0f2ca03a7 AccessUtils: allow mark_deps to be tracked by the EnclosingScope.
This encourages AccessPathWalker clients to handle enclosing mark_deps. In
some cases, it is necessary. The accessBaseWithScopes API now provides both
nested begin_access and mark_dependence.
2025-01-11 15:40:22 -08:00
Andrew Trick
195ca7ceae Improve LifetimeDependence.Scope for mutable trivial variables.
Recognize dependence on the address of a trivial 'var' as an "access" dependence
instead of an "unknown" dependence. This allows the mark_dependence to be
resolved as "[nonescaping]".
2025-01-07 22:21:15 -08:00
Andrew Trick
49136f237f Fix LifetimeDependenceScopeFixup to avoid rewriting mark_dependence.
This pass rewrites mark_depenendence to ignore "useless" borrow scopes. It was
also accidentally rewriting a dependence on a loaded value, which may redirect the
dependence to the access scope used to load that value. That access scope may be
narrower than the lifetime of the loaded value which could result in invalid
SIL. Do not rewrite this mark_dependence:

  %access = begin_access [read] [unknown] %base
  %load = load [trivial] %access
  end_access %access
  %adr = pointer_to_address
  %md = mark_dependence [unresolved] %adr on %load

Fixes rdar://142424000 (Swift compiler crashes with Assertion failed
(isa<UnreachableInst>(block->getTerminator())))
2025-01-07 15:36:52 -08:00
Erik Eckstein
c5b14c2b93 BorrowUtils: make unchecked_ownership_conversion to guaranteed ownership a BeginBorrowValue
BeginBorrowValue needs to handle all cases where a guaranteed value is produced.
Fixes a compiler crash.
2024-12-21 08:28:21 +01:00
Andrew Trick
3897929e4a LifetimeDependence: handle dependence on trivial values. 2024-12-16 16:09:37 -08:00
Andrew Trick
eab9a3599f [NFC] Add LifetimeDependence.Scope.ignoreBorrowScope utility.
Skip borrow scopes that do not actually require lifetime dependence. This
will improve LifetimeDependenceScopeFixup.
2024-12-16 15:28:00 -08:00
Andrew Trick
7811a63233 Extend LifetimeDependence to allow borrowed value base. 2024-12-16 15:28:00 -08:00
Andrew Trick
f5e16b698e [NFC] LifeDependenceUtils: fix a merge redundancy. 2024-12-16 15:27:25 -08:00
Andrew Trick
c4a2200669 Fix lifetime_dependence_borrow_fail diagnostic.
Report the correct variable name.
2024-12-14 22:46:55 -08:00
Andrew Trick
46db7ce24e LifetimeDependenceDefUseWalker: recognize ConvertPointerToPointer
Look through a call to the ConvertPointerToPointerArgument compiler intrinsic
just like it is a copy of the pointer. At the source level, that's all it is:

Treat this like a direct use of the argument 'p' rather than the result of the
invisible pointer conversion call:

func foo(_: UnsafeRawPointer)

func bar(p: UnsafePointer<T>) {
  foo(p)
}
2024-12-14 22:46:54 -08:00
Andrew Trick
f5fc17804e [NFC] SwiftCompilerSources: Add VariableScopeInstruction utility
To diagnose dependence on trivial variables.
2024-12-14 22:46:54 -08:00
Erik Eckstein
f0633d5638 AccessUtils: support computing "constant" access paths
Add `Value.constantAccessPath`. It is like `accessPath`, but ensures that the projectionPath only contains "constant" elements.
This means: if the access contains an `index_addr` projection with a non-constant index, the `projectionPath` does _not_ contain the `index_addr`.
Instead, the `base` is an `AccessBase.index` which refers to the `index_addr`.
2024-11-04 19:26:44 +01:00
Allan Shortlidge
9062271185 SILGen: Skip SIL verification and optimization if errors were emitted.
In lazy typechecking mode, errors in the program may only be discovered during
SILGen, which can leave the SIL in a bad state for subsequent stages of
compilation. If errors were detected, skip SIL verification and optimization to
prevent knock-on failures.

Partially reverts https://github.com/swiftlang/swift/pull/75428, which included
a more targeted fix for one of the possible knock-on effects of bad SIL coming
out of SILGen.

Resolves rdar://132107752.
2024-08-12 15:34:59 -07:00
Alexander Cyon
c18a24e499 [SwiftCompilerSources] Fix typos 2024-08-08 22:22:39 -07:00
Andrew Trick
3e98d2e232 Fix an assert in LifetimeDependenceUtils to allow all valid cases. 2024-07-31 22:58:39 -07:00
Andrew Trick
11ba799cd4 LifetimeDependence: diagnose yield and store-to-yield. 2024-07-30 16:27:48 -07:00
Andrew Trick
11640461ef Lifetime dependence: add inferrence for setters.
A nonescapable computed property should always depend on 'newValue'. We simply
infer that now. There's no way to explicitly spell the dependence.
2024-07-30 15:57:57 -07:00
Andrew Trick
ba9f12a80f LifetimeDependenceDiagnostics support for inout reassignment.
This relies on parameter dependence targets.

i.e. dependsOn in parameter position instead of result position.
2024-07-30 15:57:57 -07:00
Andrew Trick
f3cf529b5d [SwiftCompilerSources] use debugLog in diagnostic passes 2024-07-30 15:57:56 -07:00
Andrew Trick
b4cdbd276b LifetimeDependenceUtils comment typo. 2024-07-29 23:44:02 -07:00
Andrew Trick
c32c238720 Fix LifetimeDependenceDiagnostics to handle invalid SIL types
Invalid types are not considered Escapable. This makes it difficult to make any
assumptions about nonescapable types.

Fixes rdar://132348528 (Fix LifetimeDependenceDiagnostics to handle invalid SIL types)
2024-07-23 16:03:32 -07:00
Andrew Trick
ad2e58ed43 Assert that mark_dependence operands are distinct.
Various downstream passes assume that the dependent value is not the same as the
base value.
2024-07-05 10:42:31 -07:00
Nate Chandler
06921cfe84 [SIL] Hollow out Builtin.copy, deprecate _copy.
The copy operator has been implemented and doesn't use it.  Remove
`Builtin.copy` and `_copy` as much as currently possible.

Source compatibility requires that `_copy` remain in the stdlib.  It is
deprecated here and just uses the copy operator.

Handling old swiftinterfaces requires that `Builtin.copy` be defined.
Redefine it here as a passthrough--SILGen machinery will produce the
necessary copy_addr.

rdar://127502242
2024-05-03 15:56:25 -07:00
Erik Eckstein
e14c1d1f62 SIL, Optimizer: update and handle borrowed-from instructions
Compute, update and handle borrowed-from instruction in various utilities and passes.
Also, used borrowed-from to simplify `gatherBorrowIntroducers` and `gatherEnclosingValues`.
Replace those utilities by `Value.getBorrowIntroducers` and `Value.getEnclosingValues`, which return a lazily computed Sequence of borrowed/enclosing values.
2024-04-10 13:38:10 +02:00
Andrew Trick
bac1dc9699 Cleanup LifetimeDependenceUtils comments. 2024-04-03 10:46:09 -07:00