This is necessary because we need to model its stack-allocation
behavior, although I'm not yet doing that in this patch because
StackNesting first needs to be taught to not try to move the
deallocation.
I'm not convinced that `async let` *should* be doing a stack allocation,
but it undoubtedly *is* doing a stack allocation, and until we have an
alternative to that, we will need to model it properly.
We were reusing the SILLocation from return instructions
to generate projections to ultimately destroy values.
This fix improves on what we were doing before, by
converting the insertion point's SILLocation into a
RegularLocation _without dropping_ the source location.
If the SILLocation was tied to an ASTNode, it'll carry
over the line location for this new regular location.
Otherwise, it'll fallback to the prior strategy of
producing a line 0 autogenerated location.
resolves rdar://163281183
SILGen may produce a borrow accessor result from within a local borrow scope. Such as:
```
%ld = load_borrow %self
%fwd = unchecked_ownership %ld
%ex = struct_extract %fwd, #Struct.storedProperty
end_borrow %ld
return %ex
```
This is illegal OSSA, since the return uses a value outside it's borrow scope.
Add a new SILGenCleanup transform, to turn this into valid OSSA:
```
%ld = load_borrow %self
%ex = struct_extract %ld, #Struct.storedProperty
return_borrow %ex from_scopes %ld
```
This instruction can be used to disable ownership verification on it's result and
will be allowed only in raw SIL.
Sometimes SILGen can produce invalid ownership SSA, that cannot be resolved until
mandatory passes run. We have a few ways to piecewise disable verification.
With unchecked_ownership instruction we can provide a uniform way to disable ownership
verification for a value.
Specifically, when TBI is available we use the bottom two bits of the top nibble
(bits 60,61). On platforms without TBI, we use the bottom two tagged pointer
bits (bits 0, 1).
rdar://156525771
NOTE: We are not performing any bitmasking at all now. This is so that we can
transition the code base/tests to expect Builtin.ImplicitActor instead
of Optional<any Actor>.
NOTE: The actual test changes are in the next commit. I did this to make it
easier to review the changes.
This should not have any user visible changes.
This instruction converts Builtin.ImplicitActor to Optional<any Actor>. In the
process of doing so, it masks out the bits we may have stolen from the witness
table pointer of Builtin.ImplicitActor. The bits that we mask out are the bottom
two bits of the top nibble of the TBI space on platforms that support TBI (that
is bit 60,61 on arm64). On platforms that do not support TBI, we just use the
bottom two tagged pointer bits (0,1).
By using an instruction, we avoid having to represent the bitmasking that we are
performing at the SIL level and can instead just make the emission of the
bitmasking an IRGen detail. It also allows us to move detection if we are
compiling for AArch64 to be an IRGen flag instead of a LangOpts flag.
The instruction is a guaranteed forwarding instruction since we want to treat
its result as a borrowed projection from the Builtin.ImplicitActor.
This is subtly different from just checking whether the destination of
an edge is dead-end, because edges *internal* to dead-end regions
generally still need to be treated normally. Fundamentally, such an edge
must be part of a loop.
We need to pass down the generic signature of the caller to correctly
mangle the substitution map, because the replacement types in this
substitution maps are interface types for the caller's generic signature.
Fixes rdar://problem/161968922.
Introduce copy_value + mark_unresolved_non_copyable_value + begin_borrow at the return value of
borrow accessor apply to drive move-only diagnostics.
Also strip the copy_value + mark_unresolved_non_copyable_value + begin_borrow trio in a few places, since
they create an artificial scope out of which we cannot return values in a borrow accessor
without resorting to unsafe SIL operations currently.
Borrow accessor diagnostics allow stripping these instructions safely in the following places:
- return value of a borrow accessor
- self argument reference in the borrow accessor return expression and borrow accessor apply
The intent for `@inline(always)` is to act as an optimization control.
The user can rely on inlining to happen or the compiler will emit an error
message.
Because function values can be dynamic (closures, protocol/class lookup)
this guarantee can only be upheld for direct function references.
In cases where the optimizer can resolve dynamic function values the
attribute shall be respected.
rdar://148608854
This attribute forces programmers to acknowledge every
copy that is required to happen in the body of the
function. Only those copies that make sense according
to Swift's ownership rules should be "required".
The way this is implemented as of now is to flag each
non-explicit copy in a function, coming from SILGen, as
an error through PerformanceDiagnostics.
Based on what I see from OwnershipModelEliminator,
`%x = load [copy] %y` can turn into a plain load
followed by a retain of the loaded value.
See `NonTrivialLoadableTypeLowering::emitLoad`
* move some Cloner utilities from ContextCommon.swift directly into Cloner.swift
* add an `cloneRecursively` overload which doesn't require the `customGetCloned` closure argument
* some small cleanups
Enum types may have incomplete lifetimes in address form for trivial case values. When promoted to value form, they will end up with incomplete ossa lifetimes.
Because we know that the incomplete enum values are trivial enum cases we complete their lifetimes with `end_lifetime` instead of `destroy_value`.
This is especially important for Embedded Swift where we are not allowed to insert destroys which were not there before.
Fixes a compiler crash in Embedded Swift caused by de-virtualizing such an inserted destroy and ending up with a non-specialized generic function.
rdar://158807801
The utility effectively determines whether a value leaks as part of its
work, a subset of the checking done by the ownership verifier. Disable
that checking when the flag that disables the ownership verifier is
passed.
`end_borrow` instructions may end the scopes introduced by `load_borrow`
or `store_borrow` instructions, or those introduced by `begin_borrow`
whose operand's guaranteed root includes a `load_borrow`.
Previously, such scope ending instructions which end the scope
associated with a borrowing load or store were not regarded as accessing
the loaded-from or stored-to address. One consequence of this is that
they were not regarded as accessing pointers and thus not as deinit
barriers; that in turn resulted in `destroy_addr`s being hoisted into
such borrow scopes.
Here this is fixed by regarding such `end_borrow`s to access the
loaded-from or stored-to address of the scope-introducing `load_borrow`
or `store_borrow` respectively.
rdar://157772187
The type is a union of an Operand (a real use) and a SILInstruction (an
implicit use). Such a type is needed to reflect the fact that with
incomplete lifetimes, values can be implicitly destroyed at the
terminators of blocks in dead end regions (along the vaule's
availability boundary).
For historical reasons, the existing function
(`areUsesWithinExtendedScope`) trafficked in operands rather than
instructions. Now that PrunedLiveness has an API that deals with
instructions, add a function (`areWithinExtendedScope`) which does as
well. Factor the existing function through this new function.
For historical reasons, there was an API to check whether operands were
within the boundary which just checked whether those operands' users
were within the buondary. Make a copy of the method deal in
instructions and factor the original API through it.
functions to compute them directly without a TypeLowering object, and
change a lot of getTypeLowering call sites to just use that.
There is one subtle change here that I think is okay: SILBuilder used to
use different TypeExpansionContexts when inserting into a global:
- getTypeLowering() always used a minimal context when inserting into
a global
- getTypeExpansionContext() always returned a maximal context for the
module scope
The latter seems more correct, as AFAIK global initializers are never
inlinable. If they are, we probably need to configure the builder with
an actual context properly rather than making global assumptions.
This is incremental progress towards computing this for most types
without a TypeLowering, and hopefully eventually removing TL entirely.