When a conformance becomes part of a value, and that conformance could
potentially be isolated, the value cannot leave that particular
isolation domain. For example, if we perform a runtime lookup for a
conformance to P as part of a dynamic cast `as? any P`, the
conformance to P used in the cast could be isolated. Therefore, it is
not safe to transfer the resulting value to another concurrency domain.
Model this in region analysis by considering whether instructions that
add conformances could end up introducing isolated conformances. In
such cases, merge the regions with either the isolation of the
conformance itself (if known) or with the region of the task (making
them task-isolated). This prevents such values from being sent.
Note that `@concurrent` functions, which never dynamically execute on
an actor, cannot pick up isolated conformances.
Fixes issue #82550 / rdar://154437489
In OSSA, the result of an `unchecked_bitwise_cast` must immediately be
copied or `unchecked_bitwise_cast`'d again. In particular, it is not
permitted to borrow it. For example, the result can't be borrowed for
the purpose of performinig additional projections (`struct_extract`,
`tuple_extract`) on the borrowed value. Consequently, we cannot promote
an address if such a promotion would result in such a pattern. That
means we can't promote an address `%addr` which is used like
`struct_element_addr(unchecked_addr_cast(%addr))` or
`tuple_element_addr(unchecked_addr_cast(%addr))`. We can still promote
`unchecked_addr_cast(unchecked_addr_cast(%addr))`.
In ownership-lowered SIL, this doesn't apply and we can still promote
address with such projections.
rdar://153693915
Specifically in terms of printing, if NonisolatedNonsendingByDefault is enabled,
we print out things as nonisolated/task-isolated and @concurrent/@concurrent
task-isolated. If said feature is disabled, we print out things as
nonisolated(nonsending)/nonisolated(nonsending) task-isolated and
nonisolated/task-isolated. This ensures in the default case, diagnostics do not
change and we always print out things to match the expected meaning of
nonisolated depending on the mode.
I also updated the tests as appropriate/added some more tests/added to the
SendNonSendable education notes information about this.
I am doing this so that I can change how we emit the diagnostics just for
SendNonSendable depending on if NonisolatedNonsendingByDefault is enabled
without touching the rest of the compiler.
This does not actually change any of the actual output though.
We were effectively working around this previously at the SIL level. This caused
us not to obey the semantics of the actual evolution proposal. As an example of
this, in the following, x should not be considered main actor isolated:
```swift
nonisolated(nonsending) func useValue<T>(_ t: T) async {}
@MainActor func test() async {
let x = NS()
await useValue(x)
print(x)
}
```
we should just consider this to be a merge and since useValue does not have any
MainActor isolated parameters, x should not be main actor isolated and we should
not emit an error here.
I also fixed a separate issue where we were allowing for parameters of
nonisolated(nonsending) functions to be passed to @concurrent functions. We
cannot allow for this to happen since the nonisolated(nonsending) parameters
/could/ be actor isolated. Of course, we have lost that static information at
this point so we cannot allow for it. Given that we have the actual dynamic
actor isolation information, we could dynamically allow for the parameters to be
passed... but that is something that is speculative and is definitely outside of
the scope of this patch.
rdar://154139237
To get equivalent test coverage in asserts and noasserts builds, enable
the code that triggers executing only specified subpasses in noasserts
builds.
rdar://154499140
This results in wrong argument/return calling conventions.
First, the method call must be specialized. Only then the call can be de-virtualized.
Usually, it's done in this order anyway, because the `class_method` instruction is located before the `apply`.
But when inlining functions, the order (in the worklist) can be the other way round.
Fixes a compiler crash.
rdar://154631438
Narrowly fix a long-standing bug where destroy_addrs would be hoisted
into read access scopes, leaving the scope as a read despite the fact
that it modifies memory. This is a problem for utilities which expect
access scopes to provide correct summaries. Do this by refusing to fold
into access scopes which are marked `[read]`.
In a follow-up, we can reenable this folding, promoting each access
scope to a modify. Doing so requires checking that there are no access
scopes which overlap with any of the access scopes which would be
promoted to modify.
rdar://154407327
Bail if the closure captures an ObjectiveC block which might _not_ be copied onto the heap, i.e optimized by SimplifyCopyBlock.
We can't do this because the optimization inserts retains+releases for captured arguments.
That's not possible for stack-allocated blocks.
Fixes a mis-compile
rdar://154241245
Handle the presence of mark_dependence instructions after a begin_apply.
Fixes a compiler crash:
"copy of noncopyable typed value. This is a compiler bug. ..."
Extract the special pattern matching logic that is otherwise unrelated to the
check() function. This makes it obvious that the implementation was failing to
set the 'changed' flag whenever needed.
This pass replaces `alloc_box` with `alloc_stack` if the box is not escaping.
The original implementation had some limitations. It could not handle cases of local functions which are called multiple times or even recursively, e.g.
```
public func foo() -> Int {
var i = 1
func localFunction() { i += 1 }
localFunction()
localFunction()
return i
}
```
The new implementation (done in Swift) fixes this problem with a new algorithm.
It's not only more powerful, but also simpler: the new pass has less than half lines of code than the old pass.
The pass is invoked in the mandatory pipeline and later in the optimizer pipeline.
The new implementation provides a module-pass for the mandatory pipeline (whereas the "regular" pass is a function pass).
This is required because the mandatory pass needs to remove originals of specialized closures, which cannot be done from a function-pass.
In the old implementation this was done with a hack by adding a semantic attribute and deleting the function later in the pipeline.
I still kept the sources of the old pass for being able to bootstrap the compiler without a host compiler.
rdar://142756547
* add `cloneFunctionBody` without an `entryBlockArguments` argument
* remove the `swift::ClosureSpecializationCloner` from the bridging code and replace it with a more general `SpecializationCloner`
Originally this was a "private" utility for the ClosureSpecialization pass.
Now, make it a general utility which can be used for all kind of function specializations.
OSSA lifetime canonicalization can take a very long time in certain
cases in which there are large basic blocks. to mitigate this, add logic
to skip walking the liveness boundary for extending liveness to dead
ends when there aren't any dead ends in the function.
Updates `DeadEndBlocks` with a new `isEmpty` method and cache to
determine if there are any dead-end blocks in a given function.
Ideally we'd be able to use the llvm interleave2 and deinterleave2
intrinsics instead of adding these, but deinterleave currently isn't
available from Swift, and even if you hack that in, the codegen from
LLVM is worse than what shufflevector produces for both x86 and arm. So
in the medium-term we'll use these builtins, and hope to remove them in
favor of [de]interleave2 at some future point.
LifetimeDependenceInsertion inserts mark_dependence on token result of a begin_apply
when it yields a lifetime dependent value. When such a begin_apply gets inlined,
the inliner can crash because of the remaining uses of the token result.
Fix this by inserting mark_dependence on parameter operands that are lifetime dependence sources
and deleting the mark_dependence on token results in the inliner.
Fixes rdar://151568816
The reason I am doing this is that we have gotten reports about certain test
cases where we are emitting errors about self being captured in isolated
closures where the sourceloc is invalid. The reason why this happened is that
the decl returned by getIsolationCrossing did not have a SourceLoc since self
was being used implicitly.
In this commit I fix that issue by using SIL level information instead of AST
level information. This guarantees that we get an appropriate SourceLoc. As an
additional benefit, this fixed some extant errors where due to some sort of bug
in the AST, we were saying that a value was nonisolated when it was actor
isolated in some of the error msgs.
rdar://151955519
Defer visiting an instruction until its operands have been visited. Otherwise,
this pass will crash during ownership verification with invalid operand
ownership.
Fixes rdar://152879038 ([moveonly] MoveOnlyWrappedTypeEliminator ownership
verifier crashes on @_addressableSelf)
* re-implement the pass in swift
* support alloc_stack liveranges which span over multiple basic blocks
* support `load`-`store` pairs, copying from the alloc_stack (in addition to `copy_addr`)
Those improvements help to reduce temporary stack allocations, especially for InlineArrays.
rdar://151606382
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.