When checking whether an instruction is contained in a liveness
boundary, a pointer to a DeadEndBlocks instance must always be passed.
When the pointer is null, it is only checked that the instruction occurs
within the direct live region. When the pointer is non-null, it is
checked whether the instruction occurs within the region obtained by
extending the live region up to the availability boundary within
dead-end regions that are adjacent to the non-lifetime-ending portion of
the liveness boundary.
Now that the two known issues which resulted in invalid SIL being
provided to lifetime completion have been addressed, tighten up the
completion done on the availability boundary not to allow leaks.
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
The new boundary allows for invalid OSSA where values are not consumed
on paths leading to blocks that exit the function normally. In such
cases, the value is allowed to continue leaking as before.
This lambda has to do with availability or the lack thereof but
unreachable instructions are of interest in this context so using the
wrong name confuses things unnecessarily.
A destroy_value of an alloc_box unconditionally destroys the value
within the box. On unreachable paths, such memory may not be
initialized, so it cannot be destroyed unconditionally. Moreover,
destroying values stored in memory is outside the purview of OSSA
lifetime completion.
In the C++ sources it is slightly more convenient to dump to stderr than
to print to stdout, but it is rather more unsightly to print to stderr
from the Swift sources. Switch to stdout. Also allows the dump
functions to be marked debug only.
Not every block in a region which begins with the non-lifetime-ending
boundary of a value and ending with unreachable-terminated blocks has
the value available. If the unreachable-terminated blocks in this
boundary are not available, it is incorrect to insert destroys of the
value in them: it is an overconsume on some paths. Previously,
however, destroys were simply being inserted at the unreachable.
Here, this is fixed by finding the boundary of availability within that
region and inserting destroys before the terminators of the blocks on
that boundary.
rdar://116255254
Extracted the new visitUnreachableLifetimeEnds static member of
OSSALifetimeCompletion from the preexisting
endLifetimeAtUnreachableBlocks which now calls through the former.
Add local lifetime-ending operations to any owned or borrowed value.
This puts a single value into valid OSSA form so that linear lifetime
checking will pass.
Also adds UnreachableLifetimeCompletion which fixes OSSA after
converting a code path to unreachable (e.g. DiagnoseUnreachable and MandatoryInlining).