Commit Graph

30 Commits

Author SHA1 Message Date
Andrew Trick
c588c657f5 SILVerifier - option to verify with or without linear lifetime check
Add a separate 'verifyOwnership()' entry point so it's possible
to check OSSA lifetimes at various points.

Move SILGenCleanup into a SILGen pass pipeline.

After SILGen, verify incomplete OSSA.

After SILGenCleanup, verify ownership.
2023-03-01 21:41:46 -08:00
Meghana Gupta
ce332b9578 LoadBorrowImmutabilityVerifier: Mark is_unique as a write 2022-11-02 12:45:10 -07:00
Meghana Gupta
283f15e418 Remove dead code in LoadBorrowImmutabilityChecker 2022-10-19 19:55:17 -07:00
Meghana Gupta
f7e7fed2df Use AccessPath exact use visitor in LoadBorrowImmutabilityChecker 2022-10-11 15:53:43 -07:00
Andrew Trick
40e03ef782 Update passes to use SSAPrunedLiveness or MultiDefPrunedLiveness 2022-10-04 13:27:47 -07:00
Andrew Trick
ca503b54b7 Redesign PrunedLiveness APIs, introducing live ranges
First restore the basic PrunedLiveness abstraction to its original
intention. Move code outside of the basic abstraction that polutes the
abstraction and is fundamentally wrong from the perspective of the
liveness abstraction.

Most clients need to reason about live ranges, including the def
points, not just liveness based on use points. Add a PrunedLiveRange
layer of types that understand where the live range is
defined. Knowing where the live range is defined (the kill set) helps
reliably check that arbitrary points are within the boundary. This
way, the client doesn't need to be manage this on its own. We can also
support holes in the live range for non-SSA liveness. This makes it
safe and correct for the way liveness is now being used. This layer
safety handles:

- multiple defs
- instructions that are both uses and defs
- dead values
- unreachable code
- self-loops

So it's no longer the client's responsibility to check these things!

Add SSAPrunedLiveness and MultiDefPrunedLiveness to safely handle each
situation.

Split code that I can't figure out into
DiagnosticPrunedLiveness. Hopefully it will be deleted soon.
2022-10-04 13:27:44 -07:00
Michael Gottesman
467b742a5c [move-only] Update the non-address move checker part of the optimizer to handle mark_must_check on addresses. 2022-09-09 13:38:18 -07:00
Meghana Gupta
f2d9bc7bf6 Add dealloc_stack_ref as a non-write in LoadBorrowImmutabilityAnalysis 2022-08-19 09:46:53 -07:00
Meghana Gupta
1761fc2406 Consider store_borrow as a write in LoadBorrowImmutabilityChecker 2022-08-17 16:26:17 -07:00
Meghana Gupta
40d65262e0 Use PrunedLiveness in LoadBorrowImmutabilityChecker instead of LinearLifetimeChecker 2022-06-30 10:31:27 -07:00
Meghana Gupta
b6231d2f1d Fix LoadBorrowImmutabilityChecker to handle reborrows 2022-06-12 06:05:42 -07:00
Michael Gottesman
8f22966ff7 [move-function] Emit mark_unresolved_move_addr when we inline Builtin._move in a generic context.
This turns off the diagnostic that prevented the user from calling _move in such
contexts. I left that in for _copy.
2021-12-06 12:47:31 -08:00
Michael Gottesman
d74299e68d [move-function] Add a new instruction called mark_unresolved_move_addr.
This instruction is similar to a copy_addr except that it marks a move of an
address that has to be checked. In order to keep the memory lifetime verifier
happy, the semantics before the checker runs are the mark_unresolved_move_addr is
equivalent to copy_addr [init] (not copy_addr [take][init]).

The use of this instruction is that Mandatory Inlining converts builtin "move"
to a mark_unresolved_move_addr when inlining the function "_move" (the only
place said builtin is invoked).

This is then run through a special checker (that is later in this PR) that
either proves that the mark_unresolved_move_addr can actually be a move in which
case it converts it to copy_addr [take][init] or if it can not be a move, emit
an error and convert the instruction to a copy_addr [init]. After this is done
for all instructions, we loop back through again and emit an error on any
mark_unresolved_move_addr that were not processed earlier allowing for us to
know that we have completeness.

NOTE: The move kills checker for addresses is going to run after Mandatory
Inlining, but before predictable memory opts and friends.
2021-12-06 12:47:29 -08:00
Andrew Trick
e85228491d Rename AccessedStorage to AccessStorage
to be consistent with AccessPath and AccessBase.

Otherwise, the arbitrary name difference adds constant friction.
2021-09-21 23:18:24 -07:00
Meghana Gupta
4f2d4d5635 Fix LoadBorrowImmutabilityAnalysis in cases it raises false errors on destroy_value
We should only flag an error if there is a destroy_value on the first owned root of the access path.
2021-09-09 17:05:58 -07:00
Michael Gottesman
c972b16c59 [ownership] Teach the load_borrow verifier that value_metatype of an address isn't a write.
Just a case where the verifier was too sensitive. The only places that we use
this in terms of optimization would just not optimize in this case, so no
miscompiles are possible. That being said, we should ensure that SILGen doesn't
hit a verifier error after it emits code.

rdar://78698170 [SR-14680]
2021-06-07 12:51:06 -07:00
Doug Gregor
e77a27e8ed [Concurrency] Introduce runtime detection of data races.
Through various means, it is possible for a synchronous actor-isolated
function to escape to another concurrency domain and be called from
outside the actor. The problem existed previously, but has become far
easier to trigger now that `@escaping` closures and local functions
can be actor-isolated.

Introduce runtime detection of such data races, where a synchronous
actor-isolated function ends up being called from the wrong executor.
Do this by emitting an executor check in actor-isolated synchronous
functions, where we query the executor in thread-local storage and
ensure that it is what we expect. If it isn't, the runtime complains.
The runtime's complaints can be controlled with the environment
variable `SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL`:

  0 - disable checking
  1 - warn when a data race is detected
  2 - error and abort when a data race is detected

At an implementation level, this introduces a new concurrency runtime
entry point `_checkExpectedExecutor` that checks the given executor
(on which the function should always have been called) against the
executor on which is called (which is in thread-local storage). There
is a special carve-out here for `@MainActor` code, where we check
against the OS's notion of "main thread" as well, so that `@MainActor`
code can be called via (e.g.) the Dispatch library's
`DispatchQueue.main.async`.

The new SIL instruction `extract_executor` performs the lowering of an
actor down to its executor, which is implicit in the `hop_to_executor`
instruction. Extend the LowerHopToExecutor pass to perform said
lowering.
2021-04-12 15:19:51 -07:00
Erik Eckstein
7336bfadff SIL: handle hop_to_executor in the LoadBorrowImmutabilityChecker
Fixes a verification failure.

rdar://74660131
2021-02-25 13:31:35 +01:00
Robert Widmann
129f6eb90f [NFC] Silence -Wsuggest-override Warnings 2021-02-02 09:22:18 -08:00
Meghana Gupta
c7b6ec8e92 Merge pull request #35609 from meg-gupta/ossabugs3
Minor bug fixes in SILCombine, Canonicalization and LoadBorrowImmutabilityChecker
2021-01-27 13:55:24 -08:00
Erik Eckstein
ddd0f4d3a9 SIL: replace SmallPtrSet<SILBasicBlock *> with BasicBlockSet in LinearLifetimeChecker
This makes it unnecessary to share a single instance of visited blocks across multiple calls the the checker.
2021-01-27 10:31:17 +01:00
Meghana Gupta
dc9d1327df Treat is_unique as a read in LoadBorrowImmutabilityChecker 2021-01-26 19:55:56 -08:00
Erik Eckstein
4cd3171f35 SIL: support dealloc_ref and dealloc_partial_ref in LoadBorrowImmutabilityChecker
It fixes a verifier crash.

Thanks to @compnerd, who found this by experiment.
2021-01-26 17:47:10 +01:00
Andrew Trick
c4abccb405 Merge pull request #34742 from atrick/fix-unchecked-ownership
Specify the unchecked_ownership_conversion instruction
2020-11-16 21:13:11 -08:00
Meghana Gupta
91b5c4917f Allow a borrowed address to be passed as in_guaranteed arg in partial_apply [on_stack] only (#34736) 2020-11-16 09:59:14 -08:00
Andrew Trick
976be60e01 Don't use report_fatal_error in the LoadBorrowImmutabilityChecker.
That prevents the SILVerifier from printing the context, making it
hard to quickly produce test cases from logs.

Instead, just return the failure status to the SILVerifier so it can
do its diagnostic thing.

An assert or llvm_unreachable would also be fine in addition to the
normal SILVerifier diagnostics, but I don't think that's needed here.
2020-11-13 16:34:42 -08:00
Meghana Gupta
ce218b3f0a Fix LoadBorrowImmutabilityChecker for partial applies (#34658) 2020-11-11 21:34:52 -08:00
Andrew Trick
0f1beedfb7 Reenable load-borrow checker. 2020-10-21 15:02:08 -07:00
Andrew Trick
8e3fb44f2d Rewrite LoadBorrowImmutabilityChecker using AccessPath.
The verification will now be as complete as it can be within the
capability of our SIL utilities. It is much more aggressive with
respect to boxes, references, and pointers. It's more efficient in
that it only considers "overlapping" uses.

It is also now wholly consistent with the utilities that it uses, so
can be reenabled.

We could probably go even further and remove the switch statement
entirely, relying on AccessPath to recognize any operations that
propagate addresses, boxes, or pointers. But I didn't want to
potentially weaken enforcement without more careful consideration.
2020-10-21 15:02:08 -07:00
Andrew Trick
4f05d8a857 LoadBorrowImmutabilityChecker renaming.
Limit names to a straightforward and unambiguous statement of
purpose. They should not pose additional questions which can only be
answered by reading the code. Nuanced meaning belongs in descriptions
and code comments.

These are all examples that legitimately made reading the code very
difficult for me:

- LoadBorrowInvalidationChecker: what does "invalidation" mean in this
  context? How does that extend the meaning of "checker"? How can
  something ever pass a checker and not be invalid?

- constructValuesForKey outside of an ADT does not state purpose at all.

- wellBehavedWriteAccumulator: Raises questions about what writes are
  included and the broader semantics of the parent function. It turns
  out that well-behavedness is handled by the function's return value
  and has nothing to do with the accumulator.
2020-10-21 13:09:40 -07:00