* Allow normal function results of @yield_once coroutines
* Address review comments
* Workaround LLVM coroutine codegen problem: it assumes that unwind path never returns.
This is not true to Swift coroutines as unwind path should end with error result.
Don't attempt a SILCombine transform on `select_enum` that inserts a copy when an
enum is noncopyable. Adjust the cleanup handling for a consuming optional chain to
ensure a `destroy_value` still gets emitted on the `none` path; this shouldn't
actually matter since `none` is a trivial case, but the memory verifier isn't
that fancy during OSSA, and we can optimize it later. Fixes rdar://124426918.
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
We want to preserve the borrow scope during switch dispatch so that move-only
checking doesn't try to analyze destructures or consumes out of it. SILGen
should mark anywhere that's a potential possibility with its own marker so that
it gets borrow checked independently.
Relax some existing pattern matches and add some unhandled instructions to the
walkers so that borrowing switches over address-only enums are properly analyzed
for incorrect consumption. Add a `[strict]` flag to `mark_unresolved_move_only_value`
to indicate a borrow access that should remain a borrow access even if the subject
is later stack-promoted from a box.
In preparation for inserting mark_dependence instructions for lifetime
dependencies early, immediately after SILGen. That will simplify the
implementation of borrowed arguments.
Marking them unresolved is needed to make OSSA verification
conservative until lifetime dependence diagnostics runs.
This adds SIL-level support and LLVM codegen for normal results of a coroutine.
The main user of this will be autodiff as VJP of a coroutine must be a coroutine itself (in order to produce the yielded result) and return a pullback closure as a normal result.
For now only direct results are supported, but this seems to be enough for autodiff purposes.
Optionally, the dependency to the initialization of the global can be specified with a dependency token `depends_on <token>`.
This is usually a `builtin "once"` which calls the initializer for the global variable.
The instruction exists to express the atomic initialization of a
tuple-typed address in address-lowered mode. In opaque-values mode,
this is expressed as an assign/store.
The dependent 'value' may be marked 'nonescaping', which guarantees that the
lifetime dependence is statically enforceable. In this case, the compiler
must be able to follow all values forwarded from the dependent 'value', and
recognize all final (non-forwarded, non-escaping) use points. This implies
that `findPointerEscape` is false. A diagnostic pass checks that the
incoming SIL to verify that these use points are all initially within the
'base' lifetime. Regular 'mark_dependence' semantics ensure that
optimizations cannot violate the lifetime dependence after diagnostics.
Some notes:
This is not emitted by SILGen. This is just intended to be used so I can write
SIL test cases for transfer non sendable. I did this by adding an
ActorIsolationCrossing field to all FullApplySites rather than adding it into
the type system on a callee. The reason that this makes sense from a modeling
perspective is that an actor isolation crossing is a caller concept since it is
describing a difference in between the caller's and callee's isolation. As a
bonus it makes this a less viral change.
For simplicity, I made it so that the isolation is represented as an optional
modifier on the instructions:
apply [callee_isolation=XXXX] [caller_isolation=XXXX]
where XXXX is a printed representation of the actor isolation.
When neither callee or caller isolation is specified then the
ApplyIsolationCrossing is std::nullopt. If only one is specified, we make the
other one ActorIsolation::Unspecified.
This required me to move ActorIsolationCrossing from AST/Expr.h ->
AST/ActorIsolation.h to work around compilation issues... Arguably that is where
it should exist anyways so it made sense.
rdar://118521597
* `alloc_vector`: allocates an uninitialized vector of elements on the stack or in a statically initialized global
* `vector`: creates an initialized vector in a statically initialized global
This commit just introduces the instruction. In a subsequent commit, I am going
to add support to SILGen to emit this. This ensures that when we assign into a
tuple var we initialize it with one instruction instead of doing it in pieces.
The problem with doing it in pieces is that when one is emitting diagnostics it
looks semantically like SILGen actually is emitting code for initializing in
pieces which could be an error.
This instruction was given forwarding ownership in the original OSSA
implementation. That will obviously lead to memory leaks. Remove
ownership from this instruction and verify that it is never used for
non-trivial types.
This instructions marks the point where all let-fields of a class are initialized.
This is important to ensure the correctness of ``ref_element_addr [immutable]`` for let-fields,
because in the initializer of a class, its let-fields are not immutable, yet.
Codegen is the same, but `begin_dealloc_ref` consumes the operand and produces a new SSA value.
This cleanly splits the liferange to the region before and within the destructor of a class.