I think this was a mistake from when I changed implementations to use pure
scalar bit processing rather than processing all at once. Instead of just
updating the internal found resulting uses array, we were appending to it.
Some notes:
1. This actually did not break anything semantically in the move checker since
we do not use this array in the caller in anyway. We just use it internally in
the routine to first lookup the current state which we then process in the
routine. That being said, this API is written such that a user /could/ do that
and we want to allow for users to be able to do that so that we match what
PrunedLiveness does.
2. This could cause memory corruption due to iterator invalidation if by
appending we caused the SmallVector to reallocate as we iterated over the
array.
So to fix this I did the following:
a. I changed the push_back to be an assignment.
b. I removed llvm::enumerate just out of paranoia if the assignment could
potentially cause iterator invalidation.
The given test exercises this code path and with the old behavior would crash
with asan or guard malloc.
rdar://109673338
After a value is consumed, we emit a `debug_value undef` to indicate that the
variable value is no longer valid to the debugger. However, once a value is
reassigned, it becomes valid again, so emit a `debug_value %original_address` to
reassociate the variable with the valid memory location. rdar://109218404
"reborrow" flag on the SILArgument avoids transitive walk over the phi operandsi
to determine if it is a reborrow in multiple utilities.
SIL transforms must keep the flag up-to-date by calling SILArgument::setReborrow.
SILVerifier checks to ensure the flag is not invalidated.
Currently "escaping" is not used anywhere.
This makes it so that the move address checker is not dependent on starting the
traversal at a base object. I also included verifier checks that the API can
visit all address uses for:
1. project_box.
2. alloc_stack.
3. ref_element_addr.
4. ref_tail_addr.
5. global_addr_inst.
this is because this visitor is now apart of the SIL API definition as being
able to enumerate /all/ addresses derived from a specific chosen address value.
This is a refactoring NFCI change.
rdar://108510644
Previously, calling `visitEnclosingDefs` or `visitBorrowIntroducers`
would crash if the `SILValue` argument were an instance of `SILUndef`
because both instantiate a `::FindEnclosingDefs` with the the result of
of calling `getFunction()` on that argument and `::FindEnclosingDefs` in
turn uses that result to create a `ValueSet`; but
`SILUndef::getFunction` returns `nullptr`, which is illegal to use as
the function for a `ValueSet`(or any other data structure relying on
`NodeBits`).
If the function specified as a separate argument, no values would be
visited and `true` would be returned. Instead of burdening the API with
a separate argument, check for `SILUndef` up front and return `true`.
It's equivalent to getBorrowIntroducingUserResult except that it's less
convenient to use. There's only ever one result, so there's no need for
a visitor. Updated all users to call getBorrowIntroducingUserResult
instead.
Added the assertions from visitBorrowIntroducingUserResults to
getBorrowIntroducingUserResult. In preparation for deleting the former
in favor of the latter.
This now supports liveness holes within blocks where previously we
expected a phi def.
PrunedLiveness is streamlined for SSA liveness where we expect the
defs and uses to be related in the SSA def-use graph.
MultiDefPrunedLiveness was added on top of SSAPrunedLivenes to handle
extended SSA liveness that occurs with phis, but are still connected
in the def-use graph. Recently MultiDefPrunedLiveness was repurposed
for liveness of addressible storage. This means that we can now have
uses before defs in the same block without a corresponding phi.
Fortunately, handling this case is a straightforward extension of
MultiDefPrunedLiveness that does not complicate or penalize the
streamlined SSA case.
PrunedLiveness only knows about the live blocks and uses.
The PrunedLiveRange subclass is now responsible for updating liveness
based on both the defs and uses. This is in preparation for handling
non-SSA liveness when uses occur before the first def.
This now supports liveness holes within blocks where previously we
expected a phi def.
PrunedLiveness is streamlined for SSA liveness where we expect the
defs and uses to be related in the SSA def-use graph.
MultiDefPrunedLiveness was added on top of SSAPrunedLivenes to handle
extended SSA liveness that occurs with phis, but are still connected
in the def-use graph. Recently MultiDefPrunedLiveness was repurposed
for liveness of addressible storage. This means that we can now have
uses before defs in the same block without a corresponding phi.
Fortunately, handling this case is a straightforward extension of
MultiDefPrunedLiveness that does not complicate or penalize the
streamlined SSA case.
PrunedLiveness only knows about the live blocks and uses.
The PrunedLiveRange subclass is now responsible for updating liveness
based on both the defs and uses. This is in preparation for handling
non-SSA liveness when uses occur before the first def.
If a deinitializer has an external side-effect, it should execute after
any other tasks have executed on the same actor with potentially
external side effects.
rdar://98542036
Use BasicBlockBitfield to record per-block liveness state. This has
been the intention since BasicBlockBitfield was first introduced.
Remove the per-field bitfield from PrunedLiveBlocks. This
(re)specializes the data structure for scalar liveness and drastically
simplifies the implementation.
This utility is fundamental to all ownership utilities. It will be on
the critical path in many areas of the compiler, including at
-Onone. It needs to be minimal and as easy as possible for compiler
engineers to understand, investigate, and debug.
This is in preparation for fixing bugs related to multi-def liveness
as used by the move checker.