Commit Graph

218 Commits

Author SHA1 Message Date
Joe Groff 097b0d3400 SIL: Split unchecked_*_enum_data_addr according to ownership and effects.
We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:

- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
  projection. It is only allowed for enums whose projection operation is
  nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
  invalidating the enum and leaving the payload to be further consumed.
  This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
  The instruction takes a second operand for "scratch" space, which the
  enum representation may be copied into in order to avoid invalidating the
  enum value, so the result is dependent on the lifetime of both the
  original enum and the scratch buffer. This allows for borrowing switches
  over resilient enums.

`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.

Fixes rdar://174952822.
2026-04-27 15:40:37 -07:00
Slava Pestov 819738c83e AST: Rename mapTypeIntoContext() => mapTypeIntoEnvironment(), mapTypeOutOfContext() => mapTypeOutOfEnvironment() 2025-11-12 14:48:19 -05:00
Kavon Farvardin 3b0e77390e AddressLowering: support typed throws
Out of SILGen, we'll get the non-indirect SSA for throwing
the error. AddressLowering then converts a `throw` into
`throw_addr` to match the function convention. Similarly, a
try_apply gets rewritten to pass the error address to the
error successor block.

resolves rdar://158171053
2025-10-08 15:59:13 -07:00
Kavon Farvardin 0a81f7fbec AddressLowering: handle ignored_use
resolves rdar://158175192
2025-09-30 13:59:30 -07:00
Doug Gregor bc4cf1236b [SIL] Generalize CastingIsolatedConformances to CheckedCastInstOptions
We are going to need to add more flags to the various checked cast
instructions. Generalize the CastingIsolatedConformances bit in all of
these SIL instructions to an "options" struct that's easier to extend.

Precursor to rdar://152335805.
2025-06-04 17:12:28 -07:00
Doug Gregor e0b52cd20e [SIL] Extend checked-cast instructions with "prohibit isolated conformances" flag
When performing a dynamic cast to an existential type that satisfies
(Metatype)Sendable, it is unsafe to allow isolated conformances of any
kind to satisfy protocol requirements for the existential. Identify
these cases and mark the corresponding cast instructions with a new flag,
`[prohibit_isolated_conformances]` that will be used to indicate to the
runtime that isolated conformances need to be rejected.
2025-03-26 22:31:47 -07:00
Andrew Trick 4612728581 [NFC] Add BeginApplyInst::getEndApplyUses() API.
A begin_apply token may be used by operands that do not end the coroutine:
mark_dependence.

We need an API that gives us only the coroutine-ending uses. This blocks
~Escapable accessors.

end_borrow is considered coroutine-ending even though it does not actually
terminate the coroutine.

We cannot simply ask isLifetimeEnding, because end_apply and abort_apply do not
end any lifetime.
2024-11-18 01:37:00 -08:00
Nate Chandler 812891cf81 [NFC] PrunedLiveness: Clarified boundary API.
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.
2024-07-23 13:38:35 -07:00
Akira Hatanaka 42bc49d3fe Add a new parameter convention @in_cxx for non-trivial C++ classes that are passed indirectly and destructed by the caller (#73019)
This corresponds to the parameter-passing convention of the Itanium C++
ABI, in which the argument is passed indirectly and possibly modified,
but not destroyed, by the callee.

@in_cxx is handled the same way as @in in callers and @in_guaranteed in
callees. OwnershipModelEliminator emits the call to destroy_addr that is
needed to destroy the argument in the caller.

rdar://122707697
2024-06-27 09:44:04 -07:00
Tim Kientzle 1098054291 Merge branch 'main' into tbkka-assertions2 2024-06-18 17:52:00 -07:00
Akira Hatanaka d92f181ace Create two versions (for caller and callee) of the functions that answer questions about parameter convention (#74124)
Create two versions of the following functions:

isConsumedParameter
isGuaranteedParameter
SILParameterInfo::isConsumed
SILParameterInfo::isGuaranteed
SILArgumentConvention::isOwnedConvention
SILArgumentConvention::isGuaranteedConvention

These changes will be needed when we add a new convention for
non-trivial C++ types as the functions will return different answers
depending on whether they are called for the caller or the callee. This
commit doesn't change any functionality.
2024-06-18 09:06:09 -07:00
Tim Kientzle 1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
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)
2024-06-05 19:37:30 -07:00
Nate Chandler 06921cfe84 [SIL] Hollow out Builtin.copy, deprecate _copy.
The copy operator has been implemented and doesn't use it.  Remove
`Builtin.copy` and `_copy` as much as currently possible.

Source compatibility requires that `_copy` remain in the stdlib.  It is
deprecated here and just uses the copy operator.

Handling old swiftinterfaces requires that `Builtin.copy` be defined.
Redefine it here as a passthrough--SILGen machinery will produce the
necessary copy_addr.

rdar://127502242
2024-05-03 15:56:25 -07:00
Michael Gottesman 11f0ff6e32 [sil] Ensure that all SILValues have a parent function by making it so that SILUndef is uniqued at the function instead of module level.
For years, optimizer engineers have been hitting a common bug caused by passes
assuming all SILValues have a parent function only to be surprised by SILUndef.
Generally we see SILUndef not that often so we see this come up later in
testing. This patch eliminates that problem by making SILUndef uniqued at the
function level instead of the module level. This ensures that it makes sense for
SILUndef to have a parent function, eliminating this possibility since we can
define an API to get its parent function.

rdar://123484595
2024-02-27 13:14:47 -08:00
Nate Chandler d538894203 [AddressLowering] Handle copyable_to_moveonly.
The _value version of the instruction lowers to the _address version.
2024-01-18 07:30:23 -08:00
Nate Chandler 99df40a6d1 [AddressLowering] Handle moveonly_to_copyable.
The _value version of the instruction lowers to the _address version.
2024-01-18 07:30:23 -08:00
Nate Chandler c4a393cbf7 [AddressLowering] Handle mark_unresolved... inst.
In the fullness of time, AddressLowering should never see such
instructions because they will be eliminated after diagnostics.  Until
that time, though they need to be handled.
2024-01-17 15:16:59 -08:00
Nate Chandler 48f4b5aac4 [AddressLowering] Allow use-projection into phi.
Resolves numerous regressions when enabling AddressLowering early in the
pipeline.

Previously, if a value incoming into a phi had storage which itself was
a use-projection out of some other storage, PhiStorageOptimizer bailed
out.  The result was unnecessary "moves" (i.e. `copy_addr [take] [init]`
instructions).

Here, this bailout is removed.  In order to do this, it is necessary to
find (1) all values whose storage recursively project out of an incoming
value (such a value may have storage which is either a use _or_ a def
projection) and (2) the block which dominates the defs of all these
values.

Together, these values are used to compute liveness to determine
interference.  Previously, the live region was that between the uses of
an incoming value and its defining block.  Now, it is that between the
uses of any of the values found in (1) and the dominating block found in
(2).
2023-10-23 16:18:57 -07:00
Nate Chandler 4d3c32d261 [AddressLowering] NFC: Added print.
Allow in-IR tests to print to stdout.
2023-10-20 18:16:38 -07:00
Nate Chandler 69aaeb6682 [AddressLowering] Move into secondary use.
If a value's storage is a use projection out of some use,
AddressLowering correctly does not move into that storage when
initializing the composing use of the operand for the user into whose
storage it projects.

Previously, however, it was only checked that the value's storage was a
use projection at all.  When initializing the composing use of the
operand of some _other_ user of the value (i.e. a user into whose
storage it does _not_ project), the result was a missing move.

Here, this is fixed by only skipping the move when the value's storage
is a projection _and_ it projects into the storage of the user of the
operand at hand.
2023-10-19 09:00:52 -07:00
Nate Chandler 09511a726e [AddressLowering] NFC: Marked dump const. 2023-10-19 09:00:52 -07:00
Nate Chandler efc9c6df10 [AddressLowering] Consider all local archetypes.
When determining where the "latest opening instruction" is, consider not
just `OpenedArchetypeType`s but any `LocalArchetypeType` which includes
`PackArchetypeType`s.
2023-08-21 13:46:11 -07:00
Nate Chandler 84ab0eb548 [AddressLowering] Handle tuple_pack_extract.
By analogy with tuple_extract, transform the new instruction to
tuple_pack_element_addr.
2023-08-16 17:28:00 -07:00
Nate Chandler 35113d8a80 [AddressLowering] Fix partial_apply arg indexing.
When rewriting arguments, the index used is into the callee's argument
list.  For full applies, that is identical to the index into the
instruction's argument list.  For partial applies, it is not.

Previously, though, the index was used as if it were an index into the
instruction's argument list to get an argument ref.  Here, use instead
the newly added convenience to get the argument ref using the index into
the callee's arguments.
2023-08-15 13:06:32 -07:00
Nate Chandler 5c31339028 [AddressLowering] Loosen assert for partial_apply.
Full apply instructions have the same number of arguments as the callee
has parameters.  Partial apply instructions have some number less than
or equal to the number of callee parameters.
2023-08-15 13:06:32 -07:00
Nate Chandler 16bd80d945 [AddressLowering] Rewrite indirect partial_apply.
In opaque values mode, all arguments are passed to a partial_apply (just
like all other flavors of apply) directly.  AddressLowering needs to
rewrite the operands whose convention is indirect as it does for other
applies.
2023-08-14 10:40:40 -07:00
Nate Chandler fa98212420 [AddressLowering] Look through opaque result type.
A function which returns a value of opaque result type

    func f() -> some P { S() }

has a lowered, substituted signature

    @convention(thin) () -> @out @_opaqueReturnTypeOf("$s4main1fQryF", 0) opaque

featuring an _opaqueReturnTypeOf attr.  The SILFunctionArgument for that
@out result, however, must be of the type that the opaque result
substitutes to in the expansion context of the function.
2023-08-11 08:10:38 -07:00
Nate Chandler 57c7c9e730 [AddressLowering] Handle unowned copies.
Lower the `strong_copy_unowned_value` and `unowned_copy_value` to
`load_unowned` and `store_unowned` respectively.
2023-08-08 15:49:17 -07:00
Nate Chandler 390d02f114 [AddressLowering] Handle weak copies.
Lower the `strong_copy_weak_value` and `weak_copy_value` to `load_weak`
and `store_weak` respectively.
2023-08-08 15:47:13 -07:00
Nate Chandler 6aa44d83c9 [AddressLowering] Rewrite lifetime-ends last.
Previously, `end_borrow`s were rewritten last in order to be able to
find them when inserting `end_borrow`s on behalf of newly created
`load_borrow`s. Generalize this to rewriting all lifetime-ending users
last.  This is necessary for the lifetime utilities used by `isLoadCopy`
to remain accurate when rewriting a `copy_value` previously determined
to be from a load-copy pair.
2023-08-01 14:51:00 -07:00
Nate Chandler a27b3909d4 [AddressLowering] Sink projections to uses.
Visit the tree of projections in post-order, sinking each to the lowest
position in the least common ancestor of all uses.
2023-07-26 16:41:57 -07:00
Nate Chandler 604150c194 [AddressLowering] Place projections below types.
Projections may involve opened archetypes.  They must be dominated by
the instructions which open those archetypes.

When determining the earliest storage point for a value and the point at
which to insert its projections, look for such obstructions in the
projection chain.  The first one found is the earliest storage point.
2023-07-26 16:41:57 -07:00
Nate Chandler c9d84295eb [AddressLowering] Project at storage.
The pass rewrites opaque values in reverse post order of their
definitions.  When an opaque value is rewritten, both its definition and
its uses are rewritten.  When a def or a use is rewritten, in order to
materialize an address with which to rewrite, projection instructions
are created.  Previously, these projections were created at the site of
the def or use.  Some of these projection instructions may be reused when
rewriting later opaque values.

As a result, it's possible to have two opaque values `A` and `B` (which
are rewritten in that order) such that rewriting a use of `A` which
occurs "after" the def (or a use) of `B` creates a projection `P` which
is then used by that "earlier" def (or use) of `B`:

    ```
    A =
    B =     // relies on P
    use B
    use A   // creates some projection P
    ```

When rewriting the def (or that use, respectively) of `B`, the
projection which was created for the use of `A` will be reused.  And
previously, the projection would be created at the use of A.  But that
projection instruction was "after" the place where it is used when
rewriting the def or use of `B`.  That's invalid!

To address this, rather than creating projections at the instruction
being rewritten, instead create them "as early as possible".  The
locations where they will be created are chosen so as to dominate all
uses.
2023-07-26 16:41:57 -07:00
Nate Chandler de8e1829c3 [AddressLowering] Prevent existential multi-init. 2023-07-25 08:41:07 -07:00
Nate Chandler 5076e7be3c [AddressLowering] NFC: Moved assert above NPE.
Moved the assert that the value which opens an archetype exists before
the call to get its defining instruction which would be an NPE if the
value were in fact null.
2023-07-25 08:40:53 -07:00
Nate Chandler a23bcef5f3 [AddressLowering] NFC: Extracted function.
Promoted the functionality from createStackAllocation to a named member
AddressLoweringState::getLatestOpeningInst  so that it can be employed
elsewhere.
2023-07-25 08:40:50 -07:00
Nate Chandler e3428aeb95 [AddressLowering] NFC: Add more dump functions. 2023-07-25 08:40:39 -07:00
Nate Chandler 053cc775a3 [AddressLowering] Gardening: Undefaulted argument.
That there was a default wasn't used anywhere.
2023-07-24 16:57:14 -07:00
Nate Chandler 64ac0bda85 [AddressLowering] Gardening: Removed comment.
Per Andrew Trick, its author.
2023-07-24 16:57:14 -07:00
Nate Chandler 473985ff12 [AddressLowering] Gardening: Detypo'd. 2023-07-24 16:57:14 -07:00
Nate Chandler c9768e612f [AddressLowering] Gardening: Detypo'd. 2023-07-24 16:57:14 -07:00
Nate Chandler a1d10997da [SIL] Promoted least-common ancestor to Dominance.
It's a general purpose helper and there will soon be another user.
2023-07-24 16:57:14 -07:00
Nate Chandler 253cd4b055 [AddressLowering] NFC: Removed loop of length 1. 2023-07-20 16:02:01 -07:00
nate-chandler 8cb61d1b04 Merge pull request #67423 from nate-chandler/opaque-values/20230719/2/all_stores_within_guaranteed_argument_lifetime
[AddressLowering] Exit range check for args early.
2023-07-20 06:58:16 -07:00
nate-chandler b1c5631519 Merge pull request #67384 from nate-chandler/opaque-values/20230718/1/emit_end_borrows/destructure_and_extract
[AddressLowering] End borrow scopes for extracts/destructures at enclosing guaranteed boundary.
2023-07-20 06:57:44 -07:00
Nate Chandler 52dd6a54ec [AddressLowering] Exit range check for args early.
When determining whether a copy_value is part of a copy->store pair, if
the value being copied is guaranteed, it is checked whether the store is
within the lifetime of all its guaranteed roots.  If one of those
guaranteed roots is a function argument, the store is certainly within
the lifetime, so exit early.
2023-07-19 17:34:28 -07:00
Nate Chandler 4c5ce62c7f [AddressLowering] Fix extract's end_borrows.
An extract may have users that have escaping operand ownership.
Consequently, we can't rely on findInnerTransitiveGuaranteedUses as used
by emitEndBorrows.
2023-07-19 16:07:21 -07:00
Nate Chandler 04978e2cd0 [AddressLowering] Fixed destructures' end_borrows.
A destructure may have users that have escaping operand ownership.
Consequently, we can't rely on findInnerTransitiveGuaranteedUses as used
by emitEndBorrows.
2023-07-19 16:06:52 -07:00
Nate Chandler d98994e64f [AddressLowering] Fix begin_apply's end_borrows.
When a `load_borrow` is created on behalf of a `begin_apply`, it's
possible that it may have escaping users.  When it does,
`findInnerTransitiveGuaranteedUses` returns `false` and the uses it
finds are incomplete.  As a result the boundary computed in
`emitEndBorrows` will be incomplete.
2023-07-19 08:04:01 -07:00
Nate Chandler d3461e58c0 [AddressLowering] Gardening: De-typo'd. 2023-07-19 08:00:08 -07:00