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.
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
Usually there _must_ be a read from a consuming in-argument, because the function has to consume the argument.
But in the special case if all control paths end up in an `unreachable`, the consuming read might have been dead-code eliminated.
Therefore make sure to add the read-effect in any case. Otherwise it can result in memory lifetime failures at a call site.
fixes a memory lifetime failure
rdar://134881045
Make SILLInkage available in SIL as `SIL.Linkage`.
Also, rename the misleading Function and GlobalVariable ABI `isAvailableExternally` to `isDefinedExternally`
This corresponds to the parameter-passing convention of the Itanium C++
ABI, in which the argument is passed indirectly and possibly modified,
but not destroyed, by the callee.
@in_cxx is handled the same way as @in in callers and @in_guaranteed in
callees. OwnershipModelEliminator emits the call to destroy_addr that is
needed to destroy the argument in the caller.
rdar://122707697
If an argument escapes in a called function, we don't know anything about the argument's side effects.
For example, it could escape to the return value and effects might occur in the caller.
Fixes a miscompile
https://github.com/apple/swift/issues/73477
rdar://127691335
Layers:
- FunctionConvention: AST FunctionType: results, parameters
- ArgumentConventions: SIL function arguments
- ApplyOperandConventions: applied operands
The meaning of an integer index is determined by the collection
type. All the mapping between the various indices (results,
parameters, SIL argument, applied arguments) is restricted to the
collection type that owns that mapping. Remove the concept of a
"caller argument index".
Fixes rdar://113339972 DeadStoreElimination causes uninitialized closure context
Before this fix, the recently enabled function side effect implementation
would return no side effects for a partial apply that is not applied
in the same function. This resulted in DeadStoreElimination
incorrectly eliminating the initialization of the closure context.
The fix is to model the effects of capturing the arguments for the
closure context. The effects of running the closure body will be
considered later, at the point that the closure is
applied. Running the closure does, however, depend on the captured
values to be valid. If the value being captured is addressible,
then we need to model the effect of reading from that memory. In
this case, the capture reads from a local stack slot:
%stack = alloc_stack $Klass
store %ref to %stack : $*Klass
%closure = partial_apply [callee_guaranteed] %f(%stack)
: $@convention(thin) (@in_guaranteed Klass) -> ()
Later, when the closure is applied, we won't have any reference back
to the original stack slot. The application may not even happen in a caller.
Note that, even if the closure will be applied in the current
function, the side effects of the application are insufficient to
cover the side effects of the capture. For example, the closure
body itself may not read from an argument, but the context must
still be valid in case it is copied or if the capture itself was
not a bitwise-move.
As an optimization, we ignore the effect of captures for on-stack
partial applies. Such captures are always either a bitwise-move
or, more commonly, capture the source value by address. In these
cases, the side effects of applying the closure are sufficient to
cover the effects of the captures. And, if an on-stack closure is
not invoked in the current function (or passed to a callee) then
it will never be invoked, so the captures never have effects.
`ownership` is a bad name in `LoadInst`, because it hides `Value.ownership`.
Therefore rename it to `loadOwnership`.
Do the same for ownership in StoreInst to be consistent.
* split the `PassContext` into multiple protocols and structs: `Context`, `MutatingContext`, `FunctionPassContext` and `SimplifyContext`
* change how instruction passes work: implement the `simplify` function in conformance to `SILCombineSimplifyable`
* add a mechanism to add a callback for inserted instructions
A destroy_addr also involves a read from the address. It's equivalent to a `%x = load [take]` and `destroy_value %x`.
It's also a write, because the stored value is not available anymore after the destroy.
Fixes a compiler crash in SILMem2Reg.
rdar://103879105
This is consistent with `Type.isTrivial`.
Also, introduce corresponding properties in `Value`: `hasTrivialType` and `hasTrivialNonPointerType`, because
1. It's less to type than `Type.isTrivial(in: function)` because `Value` knows in which function it is.
2. It fixes the corner case where value is an `Undef`, which has not parent function.
Functions "are deinit barriers" (more pedantically, applies of functions
are deinit barriers) if any of their instructions are deinit barriers.
During side-effect analysis, when walking a function's instructions for
other global effects, also check for the deinit-barrier effect. If an
instruction is found to be a deinit barrier, mark the function's global
effects accordingly.
Add SILFunction::isDeinitBarrier to conveniently access the effects
computed during ComputeSideEffects.
Update the isBarrierApply predicate to iterate over the list of callees,
if complete, to check whether any is a deinit barrier. If none is, then
the apply is not a deinit barrier.
Computes the side effects for a function, which consists of argument- and global effects.
This is similar to the ComputeEscapeEffects pass, just for side-effects.