Commit Graph

163 Commits

Author SHA1 Message Date
Michael Gottesman
3dde9df468 [move-only] Emit an error if we /ever/ partially consume a noncopyable type.
The reason why I am doing this is that this was not part of the original
evolution proposal (it was called an extension) and after some discussion it was
realized that partial consumption would benefit from discussion on the forums.

rdar://111353459
2023-06-27 13:52:49 -07:00
Michael Gottesman
170ba67bd3 [move-only] Eliminate some temporary copies inserted by SILGen when accessing fields of lets.
In the next commit, I am modifying the move only checker to ensure that we
always error when partially invalidating. While doing this I discovered that
these copies were getting in the way of emitting good diagnostics in that case.
2023-06-27 13:41:31 -07:00
Nate Chandler
d00da4a0c1 [MoveOnlyAddressChecker] Fix repr for initInsts.
The address checker records instructions that initialize fields in its
initInsts map.  Previously, that map mapped from an instruction to a
range of fields of the type.  But an instruction can initialize multiple
discontiguous fields of a single value.  (Indeed an attempt to add a
second range that was initialized by an already initializing
instruction--even if it were overlapping or adjacent--would have no
effect and the map wouldn't be updated.)  Here, this is fixed by fixing
the representation and updating the storage whenver a new range is seen
to be initialized by the instruction.  As in
https://github.com/apple/swift/pull/66728 , a SmallBitVector is the
representation chosen.

rdar://111391893
2023-06-27 12:10:52 -07:00
Nate Chandler
f7f5802664 [MoveOnlyAddressChecker] NFC: Extracted helpers.
In preparation for having a third instance getting or creating the bits
affected by an instruction, introduce a typealias for maps
SILInstruction->SmallBitVector and a helper function that returns
a reference to the SmallBitVector for an instruction and two others that
set into those bits the bits from another bit vector or from a range.
2023-06-27 12:10:52 -07:00
Nate Chandler
4a5009a612 [MoveOnlyAddressChecker] Fix repr for reinits.
The address checker records instructions that reinit fields in its
reinitInsts map.  Previously, that map mapped from an instruction to a
range of fields of the type.  But an instruction can use multiple
discontiguous fields of a single value.  (Indeed an attempt to add a
second range that was reinit'd by an already reinit'ing
instruction--even if it were overlapping or adjacent--would have no
effect and the map wouldn't be updated.)  Here, this is fixed by fixing
the representation and updating the storage whenver a new range is seen
to be reinit'd by the instruction.  As in
https://github.com/apple/swift/pull/66728 , a SmallBitVector is the
representation chosen.

rdar://111356251
2023-06-27 12:10:52 -07:00
Nate Chandler
50798ff67e [MoveOnlyAddressChecker] NFC: Extracted function.
In preparation to share the getOrCreateConsumingBlock functionality with
another overload of recordConsumingBlock.
2023-06-27 11:24:47 -07:00
Nate Chandler
eb698970dd [MoveOnlyAddressChecker] NFC: Used helper.
Used the TypeTreeLeafTypeRange::setBits helper rather than looping over
the range and setting the bits in place.
2023-06-27 11:24:47 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
                     bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".

I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
2023-06-27 09:03:52 -07:00
nate-chandler
98d895db52 Merge pull request #66892 from nate-chandler/rdar111221183
[MoveOnlyAddressChecker] Fixed two use-before-def handlings.
2023-06-23 19:13:56 -07:00
Nate Chandler
ff7aa3c99a [LifetimeExtension] Fixed reinit collection.
During initializeLiveness, all blocks which contain destroys are to be
recorded in consuming blocks.  Previously, however, certain reinits were
not being added.  Here, all reinits are correctly added.
2023-06-23 12:50:05 -07:00
Nate Chandler
8eff2e8299 [LifetimeExtension] Handle use-before-def.
The multi-def algorithm is based off the single-def algorithm.  However,
it differs from it in needing to handle "liveness holes"--uses before defs.

When identifying blocks which are originally live, the algorithm starts
from consuming blocks and walks backwards until a condition is met.

Previously, that condition was finding blocks which were originally
live.  That makes sense in the single-def case: if a block is originally
live, either it was already walked through or else it was one of the
blocks discovered by liveness.  In either case, its predecessors have
already been visited if appropriate.

However, in the multi-def case, this condition is too stringent.  It
fails to account for the possibility of a block with has a "liveness
hole".  Only stop the backwards walk if the predecessor not only (1) was
in originally live but additionally (2) "kills liveness"--doesn't have a
use before a def.

rdar://111221183
2023-06-23 12:50:04 -07:00
Michael Gottesman
b8a4132af7 Merge pull request #66783 from gottesmm/pr-9c93f4322f46013f6053b162d35adfe4b4252b8f
[move-only] Remove use after move in CopiedLoadBorrowEliminationVisitor.
2023-06-21 10:53:55 -07:00
Joe Groff
282a9a7364 Merge pull request #66792 from jckarter/nonescaping-closure-conversion-moveonly-checker
MoveOnlyChecker: Look through `convert_function` of nonescaping closures.
2023-06-21 09:36:33 -07:00
Joe Groff
26d8d84270 Merge pull request #66651 from jckarter/noncopyable-address-only-borrowed-capture
ClosureLifetimeFixup: Remove copy of borrowed move-only nonescaping captures when possible.
2023-06-21 09:36:18 -07:00
Joe Groff
8f30a0097a MoveOnlyChecker: Look through convert_function of nonescaping closures.
Like a nested partial_apply reabstraction, but without the thunk, these change
the representation of the function but can't escape it without breaking the
nonescaping closure promotion. rdar://111060678
2023-06-20 18:20:45 -07:00
Michael Gottesman
b4092c4572 [move-only] Remove use after move in CopiedLoadBorrowEliminationVisitor.
Specifically, we were calling process on a visitor that was already moved. To
fix this I created a separate state structure that the visitor initializes and
moved the post-processing step onto the state data structure.

This seems to not be causing any problems today, but could in the future.

rdar://111060475
2023-06-20 13:36:10 -07:00
Joe Groff
ed2cbca04f ClosureLifetimeFixup: Remove copy of borrowed move-only nonescaping captures when possible.
SILGen introduces a copy of the capture, because the semantics of escaping partial_apply's
requires the closure to take ownership of the parameters. We don't know when a closure is
strictly nonescaping or its final lifetime until ClosureLifetimeFixup runs, but that replaces
the consume of the copy with a borrow of the copy normally, hoping later passes fix it up.
We can't wait that long for move-only types, which can't be copied, so try to remove the
copy up front when the copy lives long enough and has no interfering uses other than the
partial_apply. rdar://110137169
2023-06-20 12:10:31 -07:00
Andrew Trick
a8c45c55c4 Fix MoveOnlyAddressChecker to handle value deinits.
Track liveness of self so we don't accidentally think that such types
can be memberwise reinitialized.

Fixes rdar://110232973 ([move-only] Checker should distinguish in
between field of single field struct vs parent field itself (was:
mutation of field in noncopyable struct should not trigger deinit))
2023-06-19 18:38:03 -07:00
Nate Chandler
66867c02d1 [MoveOnlyAddressChecker] Fix used fields repr.
The address checker records uses in its livenessUses map.  Previously,
that map mapped from an instruction to a range of fields of the type.
But an instruction can use multiple discontiguous fields of a single
value.  Here, such instructions are properly recorded by fixing the map
to store a bit vector for each instruction.

rdar://110676577
2023-06-17 16:04:43 -07:00
Nate Chandler
2bfa723951 [MoveOnlyAddressChecker] Added extension flag.
Passing

```
-Xllvm -move-only-address-checker-disable-lifetime-extension=true
```

will skip the maximization of unconsumed field lifetimes.
2023-06-16 21:13:10 -07:00
Nate Chandler
eaf4560cd7 [MoveOnlyAddressChecker] Maximize lifetimes.
Previously, the checker inserted destroys after each last use.  Here,
extend the lifetimes of fields as far as possible within their original
(unchecked) limits.

rdar://99681073
2023-06-16 21:13:09 -07:00
Nate Chandler
b97712c422 [MoveOnlyAddressChecker] NFC: Promoted assertion.
Dumped more info and called llvm_unreachable on bad state.
2023-06-16 21:13:09 -07:00
Nate Chandler
f4e3292a2f [FieldSensitivePL] Fix vectorization.
FieldSensitivePrunedLiveness is used as a vectorization of
PrunedLiveness.  An instance of FSPL with N elements needs to be able to
represent the same states as N instances of PL.

Previously, it failed to do that in two significant ways:

(1) It attempted to save space for which elements were live by using
    a range.  This failed to account for instructions which are users of
    non-contiguous fields of an aggregate.

    apply(
      @owned (struct_element_addr %s, #S.f1),
      @owned (struct_element_addr %s, #S.f3)
    )

(2) It used a single bit to represent whether the instruction was
    consuming.  This failed to account for instructions which consumed
    some fields and borrowed others.

    apply(
      @owned (struct_element_addr %s, #S.f1),
      @guaranteed (struct_element_addr %s, #S.f2)
    )

The fix for (1) is to use a bit vector to represent which elements
are used by the instruction.  The fix for (2) is to use a second bit
vector to represent which elements are _consumed_ by the instruction.

Adapted the move-checker to use the new representation.

rdar://110909290
2023-06-16 21:13:07 -07:00
Michael Gottesman
59c8cff917 [borrowing] Add support for borrowing/consuming copyable types to be a noimplicitcopy type.
rdar://108383660
2023-06-06 18:12:29 -04:00
Kavon Farvardin
bd253c602f prevent reinitialization of self after discard
The value `self` is mutable (i.e., var-bound) in
a `consuming` method. Since you're allowed to
reinitialize a var after consuming, that means
you were also naturally allowed to reinitialize
self after `discard self`. But that capability was
not intended; after you discard self you shouldn't
be reinitializing it, as that's probably a mistake.

This change makes reinitialization of `self`
reachable from a `discard self` statement an error.

rdar://106098163
2023-06-05 19:25:50 -07:00
Kavon Farvardin
88d35a00b3 emit error on implicit destruction of self in discard context
As part of SE-390, you're required to write either:

  - `consume self`
  - pass self as a `consuming` parameter to a function
  - `discard self`

before the function ends in a context that contains a
`discard self` somewhere. This prevents people from accidentally
invoking the deinit due to implicit destruction of `self` before
exiting the function.

rdar://106099027
2023-06-04 18:45:22 -07:00
Michael Gottesman
c9edaee18c [move-only] Make sure that we handle load [take] that are actually borrows correctly.
Before the previous commit, we didn't see load [take] very often since it occurs
mostly on temporaries where we treat the copy_addr as the relevant take. Now
that we are checking temporaries though, we need to support this behavior.
2023-05-26 12:01:37 -07:00
Joe Groff
9db359985d Emit updated debug info when inout parameters are consumed and reinitialized.
Change SILGen to emit the `debug_value` instruction using the original inout
parameter address, instead of the `mark_must_check` inserted for move-only
parameters, because code in the MoveOnlyAddressChecker did not expect to
find the debug_value anywhere but on the original address. Update move-only
diagnostics so that they pick up the declaration name for a memory location
from any debug_value instruction if there are more than one. rdar://109740281
2023-05-24 12:15:53 -07:00
Michael Gottesman
ec28aa4949 [move-only] Ban destructuring of noncopyable address only types like we do for loadable types.
rdar://109686285
2023-05-23 16:26:16 -07:00
Joe Groff
31032b9cae Merge pull request #65992 from jckarter/debug-info-for-move-only-reinitialization
MoveOnlyAddressChecker: Reintroduce debug info for variables after reassignment.
2023-05-19 09:51:42 -07:00
Joe Groff
51f75c99a4 MoveOnlyAddressChecker: Reintroduce debug info for variables after reassignment.
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
2023-05-18 15:08:59 -07:00
Michael Gottesman
07979f0f80 [move-only] Do not attempt to process mark_must_check if we detect they have a partial_apply that was identified by an earlier diagnostic as escaping.
Previously, we would emit a "compiler doesn't understand error" since we would
detect the escape and fail. That is the correct behavior here if the
partial_apply is not already identified as escaping by an earlier pass. But in
the case where we see that the partial_apply's callee was marked with
semantics::NO_MOVEONLY_DIAGNOSTICS, then we:

1. Suppress the "compiler doesn't understand error" for this specific
   mark_must_check.

2. Suppress function wide the "copy of noncopyable type" error. Since we stopped
   processing the mark_must_check that was passed to the partial_apply, we may
   have left copies of noncopyable types on that mark_must_check value. This is
   ok since the user will get the error, will recompile, and if any further show
   up after they fix the inout escaping issue, they will be emitted
   appropriately.
2023-05-14 14:57:56 -07:00
Michael Gottesman
7d86bf0480 [move-only] Teach the move checker how to find the uses of a non-escaping partial apply and use that to emit diagnostics.
The previous commits in this series of changes reverted the allocbox to stack
change. Even with that though, we were treating the forming of the partial apply
and the destroys of the partial apply as the liveness requiring uses. This is
not the correct semantics for the non-escaping let closures. Instead, we want to
treat the passing off of the partial apply to another function or the invocation
of the partial apply as the liveness requiring uses. This makes sense since when
we capture a noncopyable type in the closure, we capture them as
inout_aliasable, that is as a pointer, so we are not going to actually use the
value until we call the partial_apply.
2023-05-14 14:57:56 -07:00
swift-ci
121b372275 Merge pull request #65892 from gottesmm/pr-14860f6cced1de4e2a6c4ebcf07577c0d56525b8
[move-only] Eliminate dead field.
2023-05-12 15:36:25 -07:00
Michael Gottesman
d252902414 [move-only] Eliminate dead field.
Originally this was a method to determine if we had emitted a diagnostic when
running our gather visitor. It was pretty footgunny since one could easily
forget to set it. Instead of doing that, we now maintain a counter in the
diagnostic emitter that counts how many diagnostics we have emitted and use that
to determine if during the walk if we emitted any additional diagnostics.
2023-05-12 12:49:20 -07:00
Michael Gottesman
a4fcdd893e [move-only] Fix a thinko where we are treating inout convention as a consuming use instead of liveness use.
rdar://109217216
2023-05-11 10:56:42 -07:00
Michael Gottesman
7f0ef3daf7 [move-only] When assigning a var that escapes into a closure into another local, emit the correct error message.
With some of the changes that I have made, we began to emit a mark_must_check
[no_copy] on a copy_addr here. This change teaches the move address checker how
to recognize that in this case if we have a project_box it is actually b/c we
have something captured by an escaping closure.
2023-05-04 13:07:17 -07:00
Michael Gottesman
be7667b6e5 [move-only] Teach the move checker how to correctly check an address only type used by escaping closures.
When we have a loadable type, SILGen always eagerly loads the value, so the move
checker handled checking those cases by just looking for loads and emitting the
error based off of a load. Of course for address only types, the codegen looks
slightly different (we consume the value directly rather than load it). So this
change just teaches the checker how to do that.

rdar://105106470
2023-05-02 16:30:33 -07:00
Michael Gottesman
d10fdf79a5 [move-only] Do not treat accessing copyable fields of a moveonly address only type as consuming the address only type.
rdar://105106470
2023-05-02 16:30:29 -07:00
Nate Chandler
868dfd8366 [SILOptimizer] Use BitfieldRef, not invalidate.
`SSAPrunedLiveness::invalidate` is used as though it reset the state of
the instance it is called on.  Clients then reuse the instance with the
expectation that it has been reset.  But since it has not been reset,
this results in unexpected liveness results.

rdar://108627366
2023-04-27 16:16:13 -07:00
Michael Gottesman
c577055100 [move-only] Instead of using AccessUseVisitor to visit addresses use TransitiveAddressVisitor.
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
2023-04-25 10:51:03 -07:00
Michael Gottesman
811824019e [move-only] Change the destructure through deinit error to lookup the deinit at the AST level rather than the SIL level.
I also added a note telling the user where the deinit is.

rdar://101651138
2023-04-13 12:49:28 -07:00
Michael Gottesman
76e93828ef [move-only] Make it an error if we attempt to destructure/partially invalidate through a field with a deinit.
If one has a type with a deinit, if one were to partially invalidate the value,
the checker will clean up the remaining parts of the value but not the actual
underlying value. This then would cause the deinit of the actual type to be
called.

rdar://101651138
2023-04-12 15:18:56 -07:00
Joe Groff
8e21bfcc47 MoveOnlyAddressChecker: Confine analysis to current formal access.
Code can only locally interact with a mutable memory location within a
formal access, and is only responsible for maintaining its invariants
during that access, so the move-only address checker does not need to,
and should not, observe operations that occur outside of the access
marked with the `mark_must_check` instruction. And for immutable
memory locations, although there are no explicit formal accesses, that's
because every access must be read-only, so although individual
accesses are not delimited, they are all compatible as far as
move-only checking is concerned. So we can back out the changes to SILGen
to re-project a memory location from its origin on every access, a
change which breaks invariants assumed by other SIL passes.
2023-04-02 16:33:57 -07:00
Michael Gottesman
43d8ab24f4 [move-only] Add a new type of mark_must_check initable_but_not_consumable.
This is used to teach the checker that the thing being checked is supposed to be
uninitialized at the mark_must_check point so that we don't put a destroy_addr
there.

The way this is implemented is that we always initially add
assignable_but_not_consumable but in DI once we discover that the assign we are
guarding is an init, we convert the assignable to its initable variant.

rdar://106525988
2023-03-31 17:32:58 -07:00
Michael Gottesman
1957f57a92 [move-only] Handle terminator users like yield when converting borrow -> destructure.
rdar://106164128
2023-03-28 16:01:01 -07:00
Andrew Trick
cbe856e53a Cleanup PrunedLiveBlocks
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.
2023-03-22 02:36:57 -07:00
Andrew Trick
ae64ff5cb0 Rename PrunedLiveness.clear() to invalidate()
Because SILBitfield cannot be cleared.
2023-03-22 01:36:48 -07:00
Andrew Trick
15796e3ff9 PrunedLiveness: add a SILFunction argument
So that liveness can migrate to using a SILBitfield.
2023-03-22 01:36:48 -07:00
Michael Gottesman
bbd2ad4de9 [move-only] Wire up proper debug info for addresses.
I included here SIL tests and in a separate PR against lldb included lldb tests
that validate as we step that the values are validated/invalidated as
appropriate.

rdar://106767457
2023-03-19 16:37:08 -07:00