When the -enable-experimental-lexical-lifetimes flag is enabled, the
alloc_stack instructions which the pass replaces alloc_box instructions
with have the lexical attribute.
Split AccessedStorage functionality in two pieces. This doesn't add
any new logic, it just allows utilities to make queries on the access
base. This is important for OSSA where we often need to find the
borrow scope or ownership root that contains an access.
To create OSSA terminator results, use:
- OwnershipForwardingTermInst::createResult(SILType ValueOwnershipKind)
- SwitchEnumInst::createDefaultResult()
Add support for passing trivial values to nontrivial forwarding
ownership. This effectively converts None to Guaranteed ownership.
This is essential for handling ".none" enums as trivial values while
extracting a nontrivial payload with switch_enum. This converts None
to Guaranteed ownership. Generates a copy if needed to convert back to
Owned ownership.
This patch replace all in-memory objects of DebugValueAddrInst with
DebugValueInst + op_deref, and duplicates logics that handles
DebugValueAddrInst with the latter. All related check in the tests
have been updated as well.
Note that this patch neither remove the DebugValueAddrInst class nor
remove `debug_value_addr` syntax in the test inputs.
In OSSA RLE for loops, in certain cases SSAUpdater will not create a new
SILPhiArgument to be used as the forwarding value. Based on dominator info
it may return the newly copied available value as the forwarding value.
This newly copied available value in the dominating predecessor
will have destroy values at leaking blocks.
Rename makeNewValueAvailable to makeValueAvailable and handle users so that only
additional required destroy_values are inserted.
Don't let debug_value instructions bail the optimization.
This fixes a couple of performance regressions, which were introduced by adding more debug_value instructions (https://github.com/apple/swift/pull/38736).
rdar://82327743
Due to mismatch in the instructions handled in DestroyHoisting::getUsedLocationsOfInst
and MemoryLocations::analyzeLocationUsesRecursively, certain users of addresses
were not considered and the destroys were hoisted before valid uses causing use-after-frees
After hoisting the destroy of the copy src, debug_value_addr users of the
copy src become dead, this PR cleans them so that MemoryLifetimeVerifier does not
complain later.
OSSA rauw cleans up end of scope markers before rauw'ing.
This can lead to inadvertant deleting of end_lifetime, later
resulting in an ownership verifier error indicating a leak.
This PR stops treating end_lifetime scope ending like end_borrow/end_access.
SROA and Mem2Reg now can leverage DIExpression -- op_fragment, more
specifically -- to generate correct debug info for optimized SIL. Some
important highlights:
- The new swift::salvageDebugInfo, similar to llvm::salvageDebugInfo,
tries to restore / transfer debug info from a deleted instruction.
Currently I only implemented this for store instruction whose
destination is an alloc_stack value.
- Since we now have source-variable-specific SIL location inside a
`debug_value` instruction (and its friends), this patch teaches
SILCloner and SILInliner to remap the debug scope there in addition
to debug scope of the instruction.
- DCE now does not remove `debug_value` instruction whose associating
with a function argument SSA value that is not used elsewhere. Since
that SSA value will not disappear so we should keep the debug info.
Change the code generation patterns for `async let` bindings to use an ABI based on the following
functions:
- `swift_asyncLet_begin`, which starts an `async let` child task, but which additionally
now associates the `async let` with a caller-owned buffer to receive the result of the task.
This is intended to allow the task to emplace its result in caller-owned memory, allowing the
child task to be deallocated after completion without invalidating the result buffer.
- `swift_asyncLet_get[_throwing]`, which replaces `swift_asyncLet_wait[_throwing]`. Instead of
returning a copy of the value, this entry point concerns itself with populating the local buffer.
If the buffer hasn't been populated, then it awaits completion of the task and emplaces the
result in the buffer; otherwise, it simply returns. The caller can then read the result out of
its owned memory. These entry points are intended to be used before every read from the
`async let` binding, after which point the local buffer is guaranteed to contain an initialized
value.
- `swift_asyncLet_finish`, which replaces `swift_asyncLet_end`. Unlike `_end`, this variant
is async and will suspend the parent task after cancelling the child to ensure it finishes
before cleaning up. The local buffer will also be deinitialized if necessary. This is intended
to be used on exit from an `async let` scope, to handle cleaning up the local buffer if necessary
as well as cancelling, awaiting, and deallocating the child task.
- `swift_asyncLet_consume[_throwing]`, which combines `get` and `finish`. This will await completion
of the task, leaving the result value in the result buffer (or propagating the error, if it
throws), while destroying and deallocating the child task. This is intended as an optimization
for reading `async let` variables that are read exactly once by their parent task.
To avoid an epoch break with existing swiftinterfaces and ABI clients, the old builtins and entry
points are kept intact for now, but SILGen now only generates code using the new interface.
This new interface fixes several issues with the old async let codegen, including use-after-free
crashes if the `async let` was never awaited, and the inability to read from an `async let` variable
more than once.
rdar://77855176