When the source of a lifetime dependency is a stack-allocated address, extend
the stack allocation to cover all dependent uses.
This avoids miscompilations for "addressable" dependencies which arise in code
built with -enable-experimental-feature AddressableTypes or
AddressableParameters. It is always an error for SILGen to emit the alloc_stack
in such cases. Nonetheless, we want to handle these unexpected cases gracefully
in SIL as a diagnostic error rather than allowing a miscompile.
Fixes rdar://159680262 ([nonescapable] diagnose dependence on a
temporary copy of a global array)
(old name: CapturePropagation)
The pass is now rewritten in swift which makes the code smaller and simpler.
Compared to the old pass it has two improvements:
* It can constant propagate whole structs (and not only builtin literals). This is important for propagating "real" Swift constants which have a struct type of e.g. `Int`.
* It constant propagates keypaths even if there are other non-constant closure captures which are not propagated. This is something the old pass didn't do.
rdar://151185177
Once we have promoted the box to stack, access violations can be detected statically by the DiagnoseStaticExclusivity pass (which runs after MandatoryAllocBoxToStack).
Therefore we can convert dynamic accesses to static accesses.
rdar://157458037
If exclusivity is checked for the alloc_stack we must not replace it with the copy-destination.
If the copy-destination is also in an access-scope this would result in an exclusivity violation which was not there before.
Fixes a miscompile which results in a wrong exclusivity violation error at runtime.
https://github.com/swiftlang/swift/issues/83924
rdar://159220436
It is valid to leak a value on paths into dead-end regions.
Specifically, it is valid to leak an `alloc_box`. Thus, "final
releases" in dead-end regions may not destroy the box and consequently
may not release its contents. Therefore it's invalid to lower such final
releases to `dealloc_stack`s, let alone `destroy_addr`s. The in-general
invalidity of that transformation results in miscompiling whenever a box
is leaked and its projected address is used after such final releases.
Fix this by not treating final releases as boundary markers of the
`alloc_box` and not lowering them to `destroy_addr`s and
`dealloc_stack`s.
rdar://158149082
The rewrite was missing the intentional omission of `dealloc_stack`s
corresponding to `[dead_end]` `dealloc_box`es. Add the necessary
bridging to get to parity with the original.
Without this check, `dealloc_box [dead_end]`s are promoted to
`dealloc_stack`s but the memory projected out of such `alloc_box`s need
not be valid.
rdar://159271158
After computing side effects, we also remove any global or argument effects that
are computed to happen, but are defined not to, based on the effect attribute.
This allows us to compute the deinit_barrier effect for such functions, fixing
the test case here: rdar://155870190
This supercedes #38324.
Extend temporary allocations (sink dealloc_stacks) initialized by a store_borrow
across lifetime dependent uses.
Fixes rdar://143159873 ([nonescapable] extend rvalue lifetimes when they are the source of a dependency)
Look through `@_rawLayout` projections, which "type casts" a raw-layout struct to it's content, which must match the like-type of the raw-layout, e.g.
```
@_rawLayout(like: T)
struct S {}
%2 = builtin "addressOfRawLayout"<S>(%1 : $*S) : $Builtin.RawPointer
%3 = pointer_to_address %2 to $*T
```
Previously, AutoDiff closure specialization pass was triggered only on
VJPs containing single basic block. However, the pass logic allows
running on arbitrary VJPs. This PR enables the pass for all VJPs
unconditionally. So, if the pullback corresponding to multiple-BB VJP
accepts some closures directly as arguments, these closures might become
specialized by the pass. Closures passed via payload of branch tracing
enum are not specialized - this is subject for future changes.
The PR contains several commits.
1. The thing named "call site" in the code is partial_apply of pullback
corresponding to the VJP. This might appear only once, so we drop
support for multiple "call sites".
2. Enhance existing SILOptimizer tests for the pass.
3. Add validation-tests for single basic block case.
4. The change itself - delete check against single basic block.
5. Add validation-tests for multiple basic block case.
6. Add SILOptimizer tests for multiple basic block case.
Bypess lifetime dependence diagnostics completely for immortal values. We did
not do this initially because we wanted to potentially consider a value with a missing
dependency to mean that it could not escape the current function. But now we use
`Void` as a stand-in for immortal values.
This is needed for reassigning a Span/MutableSpan to an empty, immortal
Span:
func inoutToImmortal(_ s: inout RawSpan) {
let tmp = RawSpan(_unsafeBytes: UnsafeRawBufferPointer(start: nil, count: 0))
s = _overrideLifetime(tmp, borrowing: ())
}
Fixes rdar://152572002 ([GH:#81976] Cannot reinitialize inout parameter of type
`MutableSpan<T>?`)
This is needed after running the SSAUpdater, because the updater can insert unnecessary phis in the middle of the original liverange of a value.
Fixes an ownership error.
rdar://153229472