Commit Graph

307 Commits

Author SHA1 Message Date
Jamie e6dcb636e4 Merge pull request #88689 from jamieQ/di-let-overwrite
[SILOptimizer]: Improve DI handling of lets & struct self-assigns
2026-05-07 11:24:17 -05:00
Konrad Malawski 003028c17c more rename followups for isNonisolated and the enum change 2026-04-28 09:21:23 -07:00
Konrad Malawski 77ac31d946 Rename to ActorIsolation::Kind::Nonisolated*Concurrent* 2026-04-28 09:21:23 -07:00
Konrad Malawski 3beefe5bd8 Rename CallerIsolationInheriting -> NonisolatedNonsending 2026-04-28 09:21:23 -07:00
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
Jamie c1fc4503dd [SILOptimizer]: Improve DI handling of lets struct self-assigns
Previously DI would error if a struct initializer had initialized a
`let` property and subsequently re-assigned `self` to a new value. This
change adds logic to test for such assigments and suppress the error
that used to be produced.
2026-04-27 13:46:22 -05:00
Jamie 7757cf62d2 [SILOptimizer]: add a (xfail) scale-test for poor DI scaling (#88064) 2026-03-25 05:44:49 -07:00
Slava Pestov aae77c16bb Merge pull request #86412 from slavapestov/shrink-smallvectors
Shrink obscenely large SmallVectors
2026-01-09 20:15:36 -05:00
Tim Kientzle adec1f6cbe Merge pull request #86277 from tbkka/tbkka-rdar149303951-try1
[SE-0474] Implement final `yielding borrow`/`yielding mutate` naming for coroutine accessors
2026-01-09 08:52:21 -08:00
Slava Pestov 72e6b5ba97 SIL: Fix obscenely large SmallVectors 2026-01-09 09:31:58 -05:00
Meghana Gupta cf97c0977e Fix DI diagnostics for empty types
This PR does the following:

- getPathStringToElementRec crashes on tuples with 0 elements, add an early return
- Disable raising diagnostics for empty tuples (tuples with 0 elements or tuples containing other tuples of 0 elements) in init accessors
- Don't crash while emitting diagnostic for empty structs
2026-01-06 16:44:27 -08:00
Tim Kientzle 8eabeeb8ca [SE-0474] Read2/Modify2 => YieldingBorrow/YieldingMutate
This updates a large number of internal symbols, function names,
and types to match the final approved terminology.  Matching the
surface language terminology and the compiler internals should
make the code easier for people to understand into the future.
2026-01-03 16:05:12 -08:00
Jamie c76fad87c6 [NFC][DI]: remove getLivenessAtNonTupleInst method from definite init
The method originally special-cased logic that would provide a
meaningful speedup and simplification, but IIUC the history, this has no
longer been the case for many years, so we might as well remove it to
make the code more straightforward.
2025-11-11 07:17:04 -06:00
eeckstein 1a8d6a8329 Merge pull request #83866 from jamieQ/remove-old-di-comments
[NFC][SILOptimizer]: update outdated docs in DefiniteInit & DRY
2025-09-22 13:54:09 +02:00
Meghana Gupta 9fe489ce22 Introduce borrow and mutate as new accessor kinds
And handle them in various covered switches
2025-09-09 14:30:26 -07:00
Jamie bc12429fc6 [NFC][SILOptimizer]: update outdated docs in DefiniteInit & DRY
A number of existing comments in the DI pass alluded to box to stack
promotion and assign lowering, both of which seem like they are vestiges
of a fairly distant past. Update comments where appropriate. Also DRY a
utility in a local function.
2025-09-07 14:58:24 -05:00
Janat Baig f21eb5375e Merge branch 'main' into temp-branch 2025-09-02 20:23:25 -04:00
Anthony Latsis 2bfe2bd587 SIL: Treat -1 as signed when using it to construct an "all bits set" llvm::APInt
This should enable us to revert
https://github.com/swiftlang/swift/pull/81464/commits/73c70ee338c515fba37baf3faff93c6389558a5c.
2025-08-27 15:22:30 +01:00
JanBaig 52895fefc3 [SIL] Remove AssignByWrapper references from SIL passes 2025-08-22 23:20:53 -04:00
Jamie 10b37530e5 [NFC]: add a FrontendStatsTracer for definite init 2025-02-15 10:41:04 -06:00
Michael Gottesman 7e350bb4ce Revert "[concurrency] Add Concurrent/ConcurrentUnsafe and use it instead of ActorIsolation::Nonisolated."
This reverts commit 0cb64638d0.
2025-02-06 14:05:06 -08:00
Michael Gottesman f05f08c2c0 Revert "[concurrency] Make ActorIsolation::Nonisolated -> CallerIsolationInheriting and delete CallerIsolationInheriting."
This reverts commit 543b1e6ca3.
2025-02-06 14:04:30 -08:00
Michael Gottesman 543b1e6ca3 [concurrency] Make ActorIsolation::Nonisolated -> CallerIsolationInheriting and delete CallerIsolationInheriting. 2025-02-03 10:56:08 -08:00
Michael Gottesman 0cb64638d0 [concurrency] Add Concurrent/ConcurrentUnsafe and use it instead of ActorIsolation::Nonisolated.
This is just the first part of a larger transition.
2025-02-03 10:56:06 -08:00
eeckstein 999669c860 Merge pull request #78441 from stzn/improve-use-before-initialized-diagnostic
[Diagnostics] A self argument implicitly passed as an inout parameter is diagnosed as used before initialized
2025-01-12 16:44:48 +01:00
stzn d429a90ebc [Diagnostics] A self argument implicitly passed as an inout parameter is diagnosed as used before initialized 2025-01-06 05:05:26 +09:00
Michael Gottesman 5d4239af57 [concurrency] Add new isolation kind CallerIsolationInheriting.
Right now it is basically a version of nonisolated beyond a few simple cases
like constructors/destructors where we are pretty sure we want to not support
this.

This is part of my bringup strategy for changing nonisolated/unspecified to be
caller isolation inheriting.
2025-01-02 13:18:30 -08:00
Erik Eckstein e328eee05c DefiniteInitialization: correctly handle upcasts in delegating initializers
Fixes a crash due to a wrong class type when creating a value_metatype instruction

rdar://140926647
2024-12-05 13:12:51 +01:00
John McCall af8115ffa3 Hop to the current isolation properly in delegating async actor initializers.
This requires two major changes.

The first is that we need to teach SILGen that the isolation of an initializer
is essentially dynamic (as far as SILGen is concerned) --- that it needs to emit
code in order to get the isolation reference.  To make this work, I needed to
refactor how we store the expected executor of a function so that it's not
always a constant value; instead, we'll need to emit code that DI will lower
properly.  Fortunately, I can largely build on top of the work that Doug previously
did to support #isolation in these functions.  The SIL we emit here around delegating
initializer calls is not ideal --- the breadcrumb hop ends up jumping to the
generic executor, and then DI actually emits the hop to the actor.  This is a little
silly, but it's hard to eliminate without special-casing the self-rebinding, which
honestly we should consider rather than the weirdly global handling of that in
SILGen today.  The optimizer should eliminate this hop pretty reliably, at least.

The second is that we need to teach DI to handle the pattern of code we get in
delegating initializers, where the builtin actually has to be passed the self var
rather than a class reference.  This is because we don't *have* a class reference
that's consistently correct in these cases.  This ended up being a fairly
straightforward generalization.

I also taught the hop_to_executor optimizer to skip over the initialization of
the default-actor header; there are a lot of simple cases where we still do emit
the prologue generic-executor hop, but at least the most trivial case is handled.
To do this better, we'd need to teach this bit of the optimizer that the properties
of self can be stored to in an initializer prior to the object having escaped, and
we don't have that information easily at hand, I think.

Fixes rdar://87485045.
2024-10-04 22:23:00 -04:00
Nate Chandler 091368ba21 [CoroutineAccessors] Added read.
The name is a placeholder for the mutating single-yield coroutine
accessor.
2024-09-26 18:10:39 -07:00
Nate Chandler 98a2e6a7df [CoroutineAccessors] Added modify.
The name is a placeholder for the mutating single-yield coroutine
accessor.
2024-09-26 18:10:39 -07:00
Holly Borla 34cc7ea081 [Concurrency] Emit a better note when an isolated stored property initializer
cannot be used in an init with mismatching isolation.
2024-08-05 18:38:44 -07:00
Tim Kientzle 1098054291 Merge branch 'main' into tbkka-assertions2 2024-06-18 17:52:00 -07:00
Doug Gregor d1ae73f436 Handle flow-sensitive #isolation in distributed actor initializers.
Distributed actors can be treated as actors by accessing the `asLocalActor`
property. When lowering `#isolation` in a distributed actor initializer,
use a separate builtin `flowSensitiveDistributedSelfIsolation` to
capture the conformance to `DistributedActor`, and have Definite
Initialization introduce the call to the `asLocalActor` getter when
needed.
2024-06-09 22:48:43 -07:00
Doug Gregor 956243cd7e Teach #isolation to respect the flow-sensitive nature of actor initializers
Actor initializers have a flow-sensitive property where they are isolated
to the actor being initialized only after the actor instance itself is
fully-initialized. However, this behavior was not being reflected in
the expansion of `#isolation`, which was always expanding to `self`,
even before `self` is fully formed.

This led to a source compatibility issue with code that used the async
for..in loop within an actor initializer *prior* to the point where the
actor was fully initialized, because the type checker is introducing
the `#isolation` (SE-0421) but Definite Initialization properly rejects
the use of `self` before it is initialized.

Address this issue by delaying the expansion of `#isolation` until
after the actor is fully initialized. In SILGen, we introduce a new
builtin for this case (and *just* this case) called
`flowSensitiveSelfIsolation`, which takes in `self` as its argument
and produces an `(any Actor)?`. Definite initialization does not treat
this as a use of `self`. Rather, it tracks these builtins and
replaces them either with `self` (if it is fully-initialized at this
point) or `nil` (if it is not fully-initialized at this point),
mirroring the flow-sensitive isolation semantics described in SE-0327.

Fixes rdar://127080037.
2024-06-07 14:54:20 -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 5881ea43e7 [DI] Fix unfailable throw during super init.
When deallocating a partially allocated class in the trapping branch of
an unfailable cast, cast back down to the subclass which is being
partially deallocated before emitting the dealloc partial ref
instruction.
2024-04-21 20:56:39 -07:00
Nate Chandler 46ccdd6176 [NFC] DI: Used already existing local variable.
Rather than repeating the same expression that already defines it.
2024-04-19 16:57:20 -07:00
Konrad `ktoso` Malawski 6132386371 [Distributed] Complete handling of protocol calls and witnesses using adjusted mangling scheme (#72416) 2024-03-23 23:54:23 +09:00
Ben Barham ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
John McCall 2f8a33cf0a Experimental type-checking support for @isolated(any) function types. 2024-02-06 22:54:27 -05:00
Holly Borla 47afd21d85 [Concurrency] Remove ActorIsolation::GlobalActorUnsafe. 2024-01-21 21:05:33 -08:00
Nate Chandler 9bb0187be1 [SILGen] Add begin_borrow [var_decl] lifetimes. 2023-11-28 07:26:09 -08:00
Michael Gottesman b1f69030fc [region-isolation] When assigning RValues into memory, use tuple_addr_constructor instead of doing it in pieces.
I also included changes to the rest of the SIL optimizer pipeline to ensure that
the part of the optimizer pipeline before we lower tuple_addr_constructor (which
is right after we run TransferNonSendable) work as before.

The reason why I am doing this is that this ensures that diagnostic passes can
tell the difference in between:

```
x = (a, b, c)
```

and

```
x.0 = a
x.1 = b
x.2 = c
```

This is important for things like TransferNonSendable where assigning over the
entire tuple element is treated differently from if one were to initialize it in
pieces using projections.

rdar://117880194
2023-11-07 15:38:33 -08:00
Sophia Poirier 4c9a726183 nonisolated(unsafe) to opt out of strict concurrency static checking for global variables 2023-10-26 16:22:28 -07:00
swift-ci f0bd604d71 Merge remote-tracking branch 'origin/main' into rebranch 2023-10-02 09:33:57 -07:00
Pavel Yaskevich 24c4fcc10e [DI] Fix check that ignores loads related to assign_or_init and assign_by_wrapper
For cases where init accessor field has a nonmutating set we need
ignore copies and borrows associated with load of "self" because
they are going to be erased together with the setter application
by DI.
2023-09-29 13:18:54 -07:00
swift-ci c2d0ed607a Merge remote-tracking branch 'origin/main' into rebranch 2023-09-19 11:33:34 -07:00
Erik Eckstein 5bc036661c SIL optimizer: add the LetPropertyLowering pass
It lowers let property accesses of classes.
Lowering consists of two tasks:

* In class initializers, insert `end_init_let_ref` instructions at places where all let-fields are initialized.
  This strictly separates the life-range of the class into a region where let fields are still written during
  initialization and a region where let fields are truly immutable.

* Add the `[immutable]` flag to all `ref_element_addr` instructions (for let-fields) which are in the "immutable"
  region. This includes the region after an inserted `end_init_let_ref` in an class initializer, but also all
  let-field accesses in other functions than the initializer and the destructor.

This pass should run after DefiniteInitialization but before RawSILInstLowering (because it relies on `mark_uninitialized` still present in the class initializer).
Note that it's not mandatory to run this pass. If it doesn't run, SIL is still correct.

Simplified example (after lowering):

  bb0(%0 : @owned C):                           // = self of the class initializer
    %1 = mark_uninitialized %0
    %2 = ref_element_addr %1, #C.l              // a let-field
    store %init_value to %2
    %3 = end_init_let_ref %1                    // inserted by lowering
    %4 = ref_element_addr [immutable] %3, #C.l  // set to immutable by lowering
    %5 = load %4
2023-09-19 15:10:30 +02:00
swift-ci e72811e31e Merge remote-tracking branch 'origin/main' into rebranch 2023-09-09 10:13:45 -07:00