Commit Graph

361 Commits

Author SHA1 Message Date
Erik Eckstein
23b4c6fc34 embedded: fix specialization of associated conformance entries in witness tables
When creating a specialized witness table, we need to get the right specialized conformance.
In IRGen don't emit associated conformance witness table entries if the protocol is not a class protocol.
In this case the associated type can never be used to create an existential. Therefore such a witness table entry is never used at runtime in embedded swift.

Fixes a compiler crash

rdar://146448091
2025-03-11 11:33:10 +01:00
Erik Eckstein
5016e35880 Optimizer: add two small utilities for instructions
* `func Instruction.dominatesInSameBlock(_ otherInst: Instruction) -> Bool`
* `var Instruction.concreteTypeOfDependentExistentialArchetype`
2025-03-07 15:59:34 +01:00
Erik Eckstein
810064b7dc Cleanup and additions to AST and SIL Type/CanonicalType
* factor out common methods of AST Type/CanonicalType into a `TypeProperties` protocol.
* add more APIs to AST Type/CanoncialType.
* move `MetatypeRepresentation` from SIL.Type to AST.Type and implement it with a swift enum.
* let `Builder.createMetatype` get a CanonicalType as instance type, because the instance type must not be a lowered type.
2025-03-07 15:59:33 +01: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
6e75813a9b OwnershipLiveness fix: support visitInnerUses
DestroyHoisting is using this utility. This requires complete liveness. But we
can't rely on complete liveness because complete lifetimes is not
enabled. Instead, we use a visitInnerUses flag to try to ignore borrow
scopes. That flag was never properly implemented. Make an attempt here.
2025-02-26 02:54:37 -08:00
Andrew Trick
2542515b69 OwnershipLiveness.swift fix: don't ignore trivial types
interiorPointerUse is dealing with addresses, so the memory still needs to be
alive regardless of the type.
2025-02-26 02:33:13 -08:00
Andrew Trick
747b1ac28a Fix OwnershipLivenes.swift visitInnerBorrowUses
Always visit the use even if it is the beginning of an inner borrow. This
provides a "better" liveness result in the case of dead borrows and gives the
client a chance to see/intercept all uses.
2025-02-26 01:42:19 -08:00
Andrew Trick
0f728f0514 Fix BorrowingInstruction.visitEndBorrows to handle borrowed-from
For borrowed-from of a reborrow, the value is the block argument. So we need to
look through the borrowed-from user.
2025-02-26 01:40:42 -08:00
Andrew Trick
38137c5383 OwnershipLiveness.swift: add comments
and rename visitOwnedDependentUses
2025-02-26 00:39:25 -08:00
Andrew Trick
406afc7202 SwiftCompilerSources: Fix InteriorUseWalker with visitInnerUses.
Add support to all kinds of borrowing instructions so we visit all their inner uses.
2025-02-26 00:38:18 -08:00
Andrew Trick
8decfa4910 Add BorrowingInstruction.innerValue 2025-02-26 00:37:20 -08:00
Andrew Trick
083ab98818 Simplify OwnershipLiveness.swift, remove reborrowingUse.
Remove complexity around reborrows. They no longer need special treatment.
2025-02-25 23:36:14 -08:00
Andrew Trick
b854ab18c1 OwnershipUseVisitor.visitInnerBorrowUses: support dependent values
Add liveness support for dependent values: borrowed-from & mark_dependence so
they aren't reported as unknown uses.
2025-02-25 23:08:55 -08:00
Andrew Trick
907097421b Add BorrowingInstruction.dependentValue and .scopedValue
This consolidates the rules for borrow scopes so we can simplify interior liveness.
2025-02-25 23:08:55 -08:00
Andrew Trick
5864004c4e SwiftCompilerSources: remove adjacent phis from InteriorUseWalker.
The extra complexity for traversing phis is not needed now that it handles
borrowed-from instructions. Remove the redundant logic because it complicates
the liveness algorithm and generates confusing results.
2025-02-25 23:08:54 -08:00
Andrew Trick
5a1a487d14 Fix InteriorUseWalker to handle dependent lifetimes as inner scopes
Inner scopes must all be reported because the walker assumes they are
complete. It is up to the client to either complete them or recursively follow
them.
2025-02-25 23:08:54 -08:00
Andrew Trick
7f6962adff Fix OwnershipUseVisitor.dependentUse()
Check if the forwarded value is trivial, not the base value. Presumably, we
won't call this visitor at all if the base is trivial.

Record a dependent non-Escapable values as a pointer-escape. InteriorUseWalker
does not handle lifetime dependencies. That requires
LifetimeDependenceDefUseWalker.
2025-02-25 23:08:54 -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
a4a675ee00 Remove adjacent phi handling from InteriorUseWalker.
At least the Swift utilities should rely on borrowed-from.
2025-02-25 23:08:54 -08:00
Andrew Trick
6188d29026 Handle borrowed-from in OwnershipUseVisitor.
If it is not a reborrow, then it produces a dependent value, just like
mark_dependence.
2025-02-25 23:08:54 -08:00
Andrew Trick
e22541544c Remove unused computeInterorLiveness API.
This encourages the client to check whether InteriorLivenessResult is valid or
escaping before using the instruction range.
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
6c99017588 Minor comment cleanup and code formatting.
Extracted from the functional changes for clarity.
2025-02-25 23:08:53 -08:00
Andrew Trick
75e84f1e97 Rename InteriorLiveness methods for clarity.
It was too easy to confuse the "inner" vs. "outer" value.

Use less ambigous names: visitAllUses vs visitInnerScopeUses
2025-02-25 23:08:53 -08:00
Erik Eckstein
57a236e671 InitializeStaticGlobals: support statically initializing globals which are or contain inline arrays
For example:

```
struct S {
  static let slab: Slab = [1, 2, 3, 4]
}
```

rdar://143005996
2025-02-12 22:37:49 +01:00
Erik Eckstein
e0b4f71af6 SIL: remove the alloc_vector instruction
It's not needed anymore, because the "FixedArray" experimental feature is replaced by inline-arrays.
2025-02-12 10:51:14 +01: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
Andrew Trick
eae2f06dc7 Extend and improve AccessBase.findSingleInitializer
Return an Initializer rather than a tuple. This makes it easier and more robust
for clients to track dependencies on initialized memory.
2025-02-10 09:11:22 -08:00
Andrew Trick
8b39b6d16a LocalVariableUtils: record mark_dependence bad address operands
Avoid bailing out when something depends on the local variable.
2025-02-10 09:11:22 -08:00
Erik Eckstein
ce73deebc4 RedundantLoadElimination: add a "mandatory" redundant load elimination pass
And make `eliminateRedundantLoads` callable from other optimizations
2025-02-07 11:30:35 +01:00
Erik Eckstein
ad2462f7f2 RedundantLoadElimination: optimize a load from a memory location which was written by copy_addr
For example:
```
  %1 = alloc_stack $B
  copy_addr %0 to [init] %1
  %3 = load [take] %1
  dealloc_stack %1
```
->
```
  %3 = load [copy] %0
```
2025-02-07 11:30:34 +01:00
Andrew Trick
e705a6d7c3 Temporarily introduce AnyInteriorPointer operand ownership.
This is necessary to fix a recent OSSA bug that breaks common occurrences on
mark_dependence [nonescaping]. Rather than reverting that change above, we make
forward progress toward implicit borrows scopes, as was the original intention.

In the near future, all InteriorPointer instructions will create an implicit
borrow scope. This means we have the option of not emitting extraneous
begin/end_borrow instructions around intructions like ref_element_addr,
open_existential, and project_box. After that, we can also migrate
GuaranteedForwarding instructions like tuple_extract and struct_extract.
2025-02-05 16:23:02 -08:00
Erik Eckstein
1f534e1c6f DeinitDevirtualizer: bail out for C++ move-only types.
We cannot de-virtualize C++ destructor calls of C++ move-only types because we cannot get its destructor in SIL.
Fixes a miscompile.
2025-01-27 09:59:48 +01: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
eeckstein
2af03dd177 Merge pull request #78768 from eeckstein/fix-borrowed-from-updater
SIL: when updating borrowed-from instructions, remove the old enclosing values first
2025-01-22 18:40:26 +01:00
Erik Eckstein
5dc67fab3f SIL Verifier: check that the enclosing values of a borrowed-from instructions are valid 2025-01-21 08:21:26 +01:00
Erik Eckstein
012aa6227d SIL: when updating borrowed-from instructions, remove the old enclosing values first
When an optimization updates borrowed-from instruction it might be necessary to remove the old enclosing values from the borrowed-from instructions.
An optimization might transform the SIL in a way that an existing enclosing value is not valid anymore.
Fixes a compiler crash:
rdar://142991910
2025-01-21 08:21:26 +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
afda6453a5 Improve LocalVariableAccessInfo: recognize more full-assignments.
Ignore marker instructions for the purpose of determining whether a store is a
full assignment:

  %a = alloc_stack
  %m = moveonlywrapper_to_copyable_addr %a
  store %0 to [init] %m // <=== full assignemt
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
a8caedfbec LifetimeDependenceInsertion: fix dependence on store_borrow.
For a lifetime dependent call that depends on a temporary store_borrow, the
generated mark_dependendence should be on the stored value, not the stack
location.

  %temp = alloc_stack $AnyObject
  %sb = store_borrow %arg to %temp
  apply %10(%out, %sb)
  mark_dependence [unresolved] %out on %arg
  end_borrow %sb

Fixes rdar://142847915 (Crash during lifetime checking while
building new swift standard library `Span`-related features)
2025-01-14 00:11:17 -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
Erik Eckstein
df62235fe6 SIL Verifier: avoid crashing for a missing borrowed-from - instead report an error 2025-01-09 19:56:25 +01:00