The pass to decide which functions should get stack protection was added in https://github.com/apple/swift/pull/60933, but was disabled by default.
This PR enables stack protection by default, but not the possibility to move arguments into temporaries - to keep the risk low.
Moving to temporaries can be enabled with the new frontend option `-enable-move-inout-stack-protector`.
rdar://93677524
We can ignore any memory writes in a program termination point, because it's not relevant for the caller.
But we need to consider memory reads, otherwise preceeding memory writes would be eliminated by dead-store-elimination in the caller.
E.g. String initialization for error strings which are printed by the program termination point.
Regarding ownership: a program termination point must not touch any reference counted objects.
Previously, to workaround an issue with ShrinkBorrowScope (where it
assumed a reasonable definition of isDeinitBarrier), a placeholder
version of the function was added. It is now removed by moving the
implementation of a version of that predicate back to C++.
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.
This invalidation kind is used when a compute-effects pass changes function effects.
Also, let optimization passes which don't change effects only invalidate the `FunctionBody` and not `Everything`.
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.
Added new C++-to-Swift callback for isDeinitBarrier.
And pass it CalleeAnalysis so it can depend on function effects. For
now, the argument is ignored. And, all callers just pass nullptr.
Promoted to API the mayAccessPointer component predicate of
isDeinitBarrier which needs to remain in C++. That predicate will also
depends on function effects. For that reason, it too is now passed a
BasicCalleeAnalysis and is moved into SILOptimizer.
Also, added more conservative versions of isDeinitBarrier and
maySynchronize which will never consider side-effects.
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.
So far, function effects only included escape effects.
This change adds side-effects (but they are not computed, yet).
It also involves refactoring of the existing escape effects.
Also the SIL effect syntax changed a bit. Details are in docs/SIL.rst
* In `ApplySite`: `argumentOperands` and `isCalleeOperand`
* In `ArgumentConvention`: `isIndirect`, `isIndirectIn` and `isGuaranteed`
* In `Function`: `isDefinition`, `numParameterArguments`, `numArguments`, `getArgumentConvention`, `effectAttribute`
* In `Type`: `isFunction` and `isCalleeConsumedFunction`
* In `Instruction`: `hasUnspecifiedSideEffects`
* New bridged instructions: `EndApplyInst` and `AbortApplyInst`
* `LoadInst.ownership`
* `BeginAccessInst.isStatic`
* make the `Allocation` protocol a `SingleValueInstruction` (instead of `AnyObject`)
And simplify it.
This struct is not really needed by clients. It's just needed internally in 'Value.accessPath` (and similar properties) to compute the access path.
Dead-end blocks are blocks from which there is no path to the function exit (`return`, `throw` or unwind).
These are blocks which end with an unreachable instruction and blocks from which all paths end in "unreachable" blocks.
Let's lldb's `po` command not print any "internal" properties of the conforming type.
This is useful if the `description` already contains all the information of a type instance.