Commit Graph

176 Commits

Author SHA1 Message Date
Andrew Trick
049d7856f4 Add visitAccessPathBaseUses API
For the move-only checker
2023-02-09 15:34:56 -08:00
John McCall
d25a8aec8b Add explicit lowering for value packs and pack expansions.
- SILPackType carries whether the elements are stored directly
  in the pack, which we're not currently using in the lowering,
  but it's probably something we'll want in the final ABI.
  Having this also makes it clear that we're doing the right
  thing with substitution and element lowering.  I also toyed
  with making this a scalar type, which made it necessary in
  various places, although eventually I pulled back to the
  design where we always use packs as addresses.

- Pack boundaries are a core ABI concept, so the lowering has
  to wrap parameter pack expansions up as packs.  There are huge
  unimplemented holes here where the abstraction pattern will
  need to tell us how many elements to gather into the pack,
  but a naive approach is good enough to get things off the
  ground.

- Pack conventions are related to the existing parameter and
  result conventions, but they're different on enough grounds
  that they deserve to be separated.
2023-01-29 03:29:06 -05:00
Konrad `ktoso` Malawski
f8b85015c1 prepare flags
wip on options

implement discardResults as a flag passed to grout init
2023-01-05 16:19:05 +09:00
Andrew Trick
0a9484597f Add findEnclosingDefs and findBorrowIntroducers utilities.
These APIs are essential for complete OSSA liveness analysis.  The
existing ad-hoc OSSA logic always misses some of the cases handled by
these new utilities. We need to start replacing that ad-hoc logic with
new utilities built on top of these APIs to define away potential
latent bugs.

Add FIXMEs to the inverse API: visitAdjacentBorrowsOfPhi. It should
probably be redesigned in terms of these new APIs.
2023-01-03 09:33:39 -08:00
Andrew Trick
c2ae7e0359 Add visitForwardedGuaranteedOperands utility.
Factors a mess of code in MemAccessUtils to handle forwarding
instruction types into a simpler utility. This utility is also needed
for ownership APIs, which need to be extended to handle these cases.
2023-01-03 09:33:39 -08:00
Andrew Trick
f9861ec9c0 Add APIs for terminator results that forward ownership.
Add TermInst::forwardedOperand.

Add SILArgument::forwardedTerminatorResultOperand. This API will be
moved into a proper TerminatorResult abstraction.

Remove getSingleTerminatorOperand, which could be misused because it's
not necessarilly forwarding ownership.

Remove the isTransformationTerminator API, which is not useful or well
defined.

Rewrite several instances of complex logic to handle block arguments
with the simple terminator result API. This defines away potential
bugs where we don't detect casts that perform implicit conversion.

Replace uses of the SILPhiArgument type and code that explicitly
handle block arguments. Control flow is irrelevant in these
situations. SILPhiArgument needs to be deleted ASAP. Instead, use
simple APIs like SILArgument::isTerminatorResult(). Eventually this
will be replaced by a TerminatorResult type.
2022-12-12 12:37:35 -08:00
Nate Chandler
8d8577e5b0 [SIL] Removed Indirect_In_Constant convention.
It is no different from @in.

Continue parse @in_constant in textual and serialized SIL, but just as
an alias for @in.
2022-12-09 21:54:00 -08:00
Nate Chandler
e1cb0b5522 [MemAccessUtils] Look thru nested for guar roots.
Previously, findGuaranteedReferenceRoots always stopped searching when
finding a begin_borrow, because it's not an ownership-forwarding
instruction.  Here, it is conditionally allowed to keep search through
the borrowee of that begin_borrow if it itself is guaranteed.
2022-12-08 18:29:14 -08:00
Erik Eckstein
ab1b343dad use new llvm::Optional API
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`

The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.

rdar://102362022
2022-11-21 19:44:24 +01:00
Allan Shortlidge
0a24042cdd SIL: Introduce the has_symbol SIL instruction. 2022-11-16 16:07:26 -08:00
Nate Chandler
f98917b1fe Removed workaround for missing Swift sources.
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++.
2022-10-24 08:47:18 -07:00
Nate Chandler
7ea336367d [NFC] Port isDeinitBarrier to Swift.
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.
2022-10-18 21:23:22 -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
Hamish Knight
b12015c343 [SIL] Introduce the increment_profiler_counter instruction
This is a dedicated instruction for incrementing a
profiler counter, which lowers to the
`llvm.instrprof.increment` intrinsic. This
replaces the builtin instruction that was
previously used, and ensures that its arguments
are statically known. This ensures that SIL
optimization passes do not invalidate the
instruction, fixing some code coverage cases in
`-O`.

rdar://39146527
2022-09-07 17:55:13 +01:00
Michael Gottesman
4dc6e6ecc4 [move-keyword] Remove old implementation.
By using the keyword instead of the function, we actually get a much simpler
implementation since we avoid all of the machinery of SILGenApply. Given that we
are going down that path, I am removing the old builtin implementation since it
is dead code.

The reason why I am removing this now is that in a subsequent commit, I want to
move all of the ownership checking passes to run /before/ mandatory inlining. I
originally placed the passes after mandatory inlining since the function version
of the move keyword was transparent and needing to be inlined before we could
process it. Since we use the keyword now, that is no longer an issue.
2022-09-04 01:19:01 -07:00
Michael Gottesman
36893aa260 Merge pull request #60717 from gottesmm/pr-00503aff6555a1f03b7b992c1db47b30ca05eaa9
[move-only] Add support for explicit_copy_addr in a few places in MemAccessUtils that I missed when introducing the instruction.
2022-08-22 23:37:58 -07:00
Michael Gottesman
7361639a85 [move-only] Add support for explicit_copy_addr in a few places in MemAccessUtils that I missed when introducing the instruction.
I discovered these were missing when using explicit_copy_addr with the move only
address checker.
2022-08-22 17:29:52 -07:00
Nate Chandler
e2698edb7c [MemAccessUtils] Non-trivial Cxx node is leaf.
Nodes which are non-trivial C++ decls must be destroyed, they cannot be
destroyed by way of destroying their subobjects.  This was exposed by
producing more non-lexical alloc_stacks which enjoy more aggressive
destroy_addr hoisting.
2022-08-22 15:28:00 -07:00
Michael Gottesman
3e52007562 [builtin] Remove "unsafeGuaranteed" and related code since Unmanaged now has an Ownership SSA based implementation that works completely in SILGen.
This isn't used in the stdlib anymore as well.
2022-08-21 01:22:36 -07:00
Meghana Gupta
f374f2bad3 Handle store_borrow in MemAccessUtils 2022-08-17 16:26:17 -07:00
Michael Gottesman
1e6187c4f4 [sil] Update all usages of old API SILValue::getOwnershipKind() in favor of new ValueBase::getOwnershipKind().
Andy some time ago already created the new API but didn't go through and update
the old occurences. I did that in this PR and then deprecated the old API. The
tree is clean, so I could just remove it, but I decided to be nicer to
downstream people by deprecating it first.
2022-07-26 11:46:23 -07:00
Michael Gottesman
9b625588f0 [sil] Make copyable_to_moveonlywrapper forwarding like moveonlywrapper_to_copyable.
Specifically this means that rather than always being owned, we now have owned
and guaranteed versions of copyable_to_moveonlywrapper. Similar to
moveonlywrapper_to_copyable, one chooses which variant one gets by using
specific SILBuilder APIs:
create{Owned,Guaranteed}CopyableToMoveOnlyWrapperValueInst. It is still
forwarding and the rest of the forwarding APIs work as expected except that the
forwarding ownership is fixed (and an assertion will result if one attempts to
do so).

NOTE: It is assumed that trivial operands are always passed to the owned
variant.
2022-07-19 14:39:59 -07:00
Nate Chandler
34c08b8344 [TaskToThread] Add Task.runInline.
The new intrinsic, exposed via static functions on Task<T, Never> and
Task<T, Error> (rethrowing), begins an asynchronous context within a
synchronous caller's context.  This is only available for use under the
task-to-thread concurrency model, and even then only under SPI.
2022-07-08 08:44:18 -07:00
Michael Gottesman
e1006c62f9 [move-only] Add copyable_to_moveonlywrapper and moveonlywrapper_to_copyable instructions.
These instructions have the following attributes:

1. copyably_to_moveonlywrapper takes in a 'T' and maps it to a '@moveOnly
T'. This is semantically used when initializing a new moveOnly binding from a
copyable value. It semantically destroys its input @owned value and returns a
brand new independent @owned @moveOnly value. It also is used to convert a
trivial copyable value with type 'Trivial' into an owned non-trivial value of
type '@moveOnly Trivial'. If one thinks of '@moveOnly' as a monad, this is how
one injects a copyable value into the move only space.

2. moveonlywrapper_to_copyable takes in a '@moveOnly T' and produces a new 'T'
value. This is a 'forwarding' instruction where at parse time, we only allow for
one to choose it to be [owned] or [guaranteed].

* moveonlywrapper_to_copyable [owned] is used to signal the end of lifetime of
the '@moveOnly' wrapper. SILGen inserts these when ever a move only value has
its ownership passed to a situation where a copyable value is needed. Since it
is consuming, we know that the no implicit copy checker will ensure that if we
need a copy for it, the program will emit a diagnostic.

* moveonlywrapper_to_copyable [guaranteed] is used to pass a @moveOnly T value
as a copyable guaranteed parameter with type 'T' to a function. In the case of
using no-implicit-copy checking this is always fine since no-implicit-copy is a
local pattern. This would be an error when performing no escape
checking. Importantly, this instruction also is where in the case of an
@moveOnly trivial type, we convert from the non-trivial representation to the
trivial representation.

Some important notes:

1. In a forthcoming commit, I am going to rebase the no implicit copy checker on
top of these instructions. By using '@moveOnly' in the type system, we can
ensure that later in the SIL pipeline, we can have optimizations easily ignore
the code.

2. Be aware of is that due to SILGen only emitting '@moveOnly T' along immediate
accesses to the variable and always converts to a copyable representation when
calling other code, we can simply eliminate from the IR all moveonly-ness from
the IR using a lowering pass (that I am going to upstream). In the evil scheme
we are accomplishing here, we perform lowering of trivial values right after
ownership lowering and before diagnostics to simplify the pipeline.

On another note, I also fixed a few things in SILParsing around getASTType() vs
getRawASTType().
2022-06-09 19:47:31 -07:00
Nate Chandler
3e2efa59b7 [MemAccessUtils] Resilient node is a product leaf.
To visit the nodes of a type that is formed by repeated product
operations (struct and tuple), visitProductLeafAccessPathNodes is used.
The caller provides a TypeExpansionContext to this function.

Previously, though, visitProductLeafAccessPathNodes didn't respect the
TypeExpansionContext when visiting struct types.  Specifically, it
looked through resilient structs to their fields.  For a caller, such as
SSADestroyHoisting, that cares about the number of non-trivial nodes,
that is wrong--each resilient struct is a non-trivial node for its
purposes.

Here, this is corrected by having visitProductLeafAccessPathNodes
consider whether a struct type is resilient in the specified
TypeExpansionContext.  Resilient structs are now correctly recognized as
leaf nodes and the caller-provided lambda is invoked with each.

rdar://92460184
2022-04-30 17:07:25 -07:00
Andrew Trick
699e464e4b Merge pull request #42624 from atrick/fix-copy-unmanaged
Extend deinit barriers to handle conversion to strong reference.
2022-04-27 11:52:43 -07:00
Andrew Trick
7d5e6b5998 Extend deinit barriers to handle conversion to strong reference.
Plug a hole in the semantics of deinitialization barriers.

Adds strong_copy_(unowned|unmanaged)_value to mayLoadWeakOrUnowned.
Deinitialization barriers includes loads from weak references.
Converting an unowned or unmanaged reference to a strong reference
is the moral equivalent.

Fixes rdar://90909833 (Extend deinit barriers to handle conversion to
strong reference)
2022-04-24 18:58:54 -07:00
Josh Soref
d767912be2 Spelling sil (#42471)
* spelling: accessible

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: accessories

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: allocated

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: amortizes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: are

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: arguments

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: cacheable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: check

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: clazz

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: compatible

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: compilation

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: completely

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: construct

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: conversion

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: declarations

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: derivation

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: deserialization

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: destroyed

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: determined

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: different

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: doesn't

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: equality

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: equivalent

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: formation

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: forwards

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: global

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: guaranteed

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: have

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: identify

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: inaccessible

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: indeterminate

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: indices

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: inefficient

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: inheritance

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: instantaneous

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: instruction

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: intentionally

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: interior

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: intrinsic

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: introducing

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: irrelevant

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: message

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: multi

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: necessarily

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: object

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: one

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: optimization

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: otherwise

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: overridden

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: parameter

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: pattern

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: pipeline

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: possibility

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: postdominance

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: providing

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: reached

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: recognized

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: refrigerator

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: remaining

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: resilient

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: retrieve

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: scavenge

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: scheduled

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: separately

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: serializable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: signature

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: simplicity

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: specifically

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: substituted

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: substitution

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: subtypes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: supplement

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: syntax

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: there

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: these

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: this

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: though

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: through

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transitively

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transpose

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: trivial

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: value

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: verification

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: visibility

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: weird

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: whole

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2022-04-22 15:11:09 -07:00
Andrew Trick
64ec981f3b Rename isDirectlyForwarding to preservesOwnership. 2022-04-12 22:23:17 -07:00
Erik Eckstein
e2970155e8 MemAccessUtils: handle the case of enum with no operand in findOwnershipReferenceAggregate
This fixes a crash when trying to compute the immutable scope of an address which comes from an `Optional.none`.

rdar://90119694
2022-03-31 09:53:50 +02:00
Andrew Trick
2fd4de411e [SIL-opaque] Removed [Unconditional]CheckedCastValue 2022-03-22 17:04:13 -07:00
Andrew Trick
5e36a2a689 Fix an AccessedStorage assert for SIL global variables.
Allow round-tripping access to global variables. Previously,
AccessedStorage asserted that global variables were always associated
with a VarDecl. This was to ensure that AccessEnforcmentWMO always
recognized the global. Failing to recognize access to a global will
cause a miscompile.

SILGlobalVariable now has all the information needed by
SIL. Particularly, the 'isLet' flag. Simply replace VarDecl with
SILGlobalVariable in AccessEnforcmentWMO to eliminate the need for the
assert.
2022-03-21 08:51:23 -07:00
Nate Chandler
a1c1b32a8c [MemAccessUtils] Added RelativeAccessStorageWithBase.
The new "relative" version of AccessStorageWithBase carries additional
information about the walk from the specified address back to the base.
For now, that includes the original address and the most transformative
sort of cast that was encountered.
2022-03-14 09:46:02 -07:00
Nate Chandler
6b6e585d54 [MemAccessUtils] Visit product type tree of addr.
Added a function that visits the leaves of the type/projection tree of
the specified address and calls its visitor with the path node to and
type of each.
2022-03-14 09:45:47 -07:00
Nate Chandler
c1adf24abc [MemAccessUtils] Returned visitor's return. 2022-03-09 10:12:10 -08:00
Nate Chandler
6226fa7f5c [MemAccessUtils] Regard end/abort_apply as use.
Unique storage use visitor was not previously considering end_apply and
abort_apply as uses of an address even when the begin_apply took that
address as an argument.  They are uses of it though because the address
may be stored into the coroutine's frame and used when the second
partial function is invoked.
2022-02-25 07:17:09 -08:00
Nate Chandler
8a81d41514 [MemAccessUtils] Corrected inverted condition.
The function mayAccessPointer is attempting to determine whether the
specified instruction accesses a raw/unsafe pointer of unknown
provenance.  To do that, it visits all the address operands and checks
whether any of them have an ::Unidentified access representation kind.

Previously, the condition was inverted: all address uses _except_ those
whose kinds were unidentified were judged to be potential accessors to
raw/unsafe pointers.  Here that's fixed by inverting the condition.  To
help clarify things, the variable name is changed too.
2022-02-24 13:06:27 -08:00
Nate Chandler
d227cef874 [MemAccessUtils] Visit access as unique storage uses.
Add a new member functino UniqueStorageUseVisitor::visitBeginAccess and
call it when GatherUniqueStorageUses runs.
2022-02-18 10:10:17 -08:00
Andrew Trick
83b01d8ebe Improve the SILPhiArgument API
This subclass of SILArgument should be eliminated--it's not always a
phi, and whether it is a "phi argument" has nothing whatsoever to do
with the opcode. That is a property of a value's uses, not a property of the
value.

Until then, provide a logical and useful API within the type. This
often avoids the need to explicitly cast to a SILPhiArgument type and
avoids a lot of boilerplate in code that deals with phis.

Note: PhiOperand and PhiValue are improved abstractions on top of this
API. But the SILArgument-level API is still an important bridge
between SILArgument and other phi abstractions.
2022-02-15 13:28:46 -08:00
Nate Chandler
e91b08b2fb [MemAccessUtils] Bailed when visitor bailed.
Previously, in GatherUniqueStorageUses::visiteUse, the results of calls
to visit#### on the visitor were not used.  Here, they are returned from
the function.
2022-02-10 20:17:37 -08:00
Andrew Trick
782ce7cddb Minor latent bug fix in findGuaranteedReferenceRoots.
Fix an obvious mistake that happens to not break anything in practice.

Note that the argument index of a terminator result is not the same as
an operand index for the terminator instruction.
2022-01-25 17:32:14 -08:00
Andrew Trick
547d87f347 Add a UniqueAddressUses utility.
Analyze and classify the leaf uses of unique storage.

Storage that has a unique set of roots within this function includes
alloc_stack, alloc_box, exclusive argument, and global variables. All access
to the storage within this function is derived from these roots.

Gather the kinds of uses that are typically relevant to algorithms:
- loads	      (including copies out of, not including inout args)
- stores      (including copies into and inout args)
- destroys    (of the entire aggregate)
- debugUses   (only populated when preserveDebugInfo == false)
2021-12-22 01:54:05 -08:00
Andrew Trick
0836b6af61 MemAccessUtils comments 2021-12-22 01:54:05 -08:00
Andrew Trick
0325e296fe Add an isDeinitBarrier() utility.
Needs to be common across ShrinkBorrowScopes and SSADestroyHoisting.
2021-12-22 01:54:05 -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
Michael Gottesman
3c411cbc14 [mem-access-utils] Teach memInstMustInitialize that indirect out parameters are initializing.
Just something I noticed while reading the code.
2021-12-03 11:36:08 -08:00
Michael Gottesman
8e5fb2164a [sil] Ban casting AnyObject with a guaranteed ownership forwarding checked_cast_br and fix up semantic-arc-opts given that.
The reason why I am doing this is that currently checked_cast_br of an AnyObject
may return a different value due to boxing. As an example, this can occur when
performing a checked_cast_br of a __SwiftValue(AnyHashable(Klass())).

To model this in SIL, I added to OwnershipForwardingMixin a bit of information
that states if the instruction directly forwards ownership with a default value
of true. In checked_cast_br's constructor though I specialize this behavior if
the source type is AnyObject and thus mark the checked_cast_br as not directly
forwarding its operand. If an OwnershipForwardingMixin directly forwards
ownership, one can assume that if it forwards ownership, it will always do so in
a way that ensures that each forwarded value is rc-identical to whatever result
it algebraically forwards ownership to. So in the context of checked_cast_br, it
means that the source value is rc-identical to the argument of the success and
default blocks.

I added a verifier check to CheckedCastBr that makes sure that it can never
forward guaranteed ownership and have a source type of AnyObject.

In SemanticARCOpts, I modified the code that builds extended live ranges of
owned values (*) to check if a OwnershipForwardingMixin is directly
forwarding. If it is not directly forwarding, then we treat the use just as an
unknown consuming use. This will then prevent us from converting such an owned
value to guaranteed appropriately in such a case.

I also in SILGen needed to change checked_cast_br emission in SILGenBuilder to
perform an ensurePlusOne on the input operand (converting it to +1 with an
appropriate cleanup) if the source type is an AnyObject. I found this via the
verifier check catching this behavior from SILGen when compiling libswift. This
just shows how important IR verification of invariants can be.

(*) For those unaware, SemanticARCOpts contains a model of an owned value and
all forwarding uses of it called an OwnershipLiveRange.

rdar://85710101
2021-11-29 15:39:00 -08:00
Andrew Trick
76b30e30f5 SILVerifier - allow rebind_memory token to cross functions
Remove a completely unnecessary assertion to handle reasonable use
cases.
2021-11-15 19:10:40 -08:00
Michael Gottesman
f9122a79b7 [moveOnly] Implement a new _copy function that performs an explicit copy value.
The key thing is that the move checker will not consider the explicit copy value
to be a copy_value that can be rewritten, ensuring that any uses of the result
of the explicit copy_value (consuming or other wise) are not checked.

Similar to the _move operator I recently introduced, this is a transparent
function so we can perform one level of specialization and thus at least be
generic over all concrete types.
2021-10-29 15:37:46 -07:00
nate-chandler
03361671be Merge pull request #39939 from nate-chandler/dce/keep-outer-borrow-scope-alive-when-reborrowing
[DCE] Keep outer borrows alive when reborrowing.
2021-10-28 15:31:29 -07:00