In the future, we may not have this requirement, but for now it is a really
convenient way to track down places in SILGen where I have missed converting
from copyable to moveonlywrapped types.
The reason why this makes sense is that this method is attempting to return the
current SILType but with a different category. So using getASTType() here and by
mistake removing move only would break semantics. Additionally, not making this
change breaks the expectation that this API would be idempotent.
The use of the SWIFT_INLINE_BITFIELD macros in SILNode were a constant source of confusion and bugs.
With this refactoring I tried to simplify the definition of "shared fields" in SILNode, SILValue and SILInstruction classes:
* Move `kind`, `locationKindAndFlags` and the 32-bit fields out of the 64-bitfield into their own member variables. This avoids _a lot_ of manual bit position computations.
* Now we have two separate "shared fields": an 8-bit field (e.g. for boolean flags) and a 32-bit field (e.g. for indices, which can potentially get large). Both fields can be used independently. Also, they are not "bit fields" per se. Instructions can use the field e.g. as a `bool`, `uint32_t`, or - if multiple flags are to be stored - as a packed bit field.
* With these two separate fields, we don't have the need for defining bitfields both in a base class _and_ in a derived value/instruction class. We can get rid of the complex logic which handles such cases. Just keep a check to catch accidental overlaps of fields in base and derived classes.
* Still use preprocessor macros for the implementation, but much simpler ones than before.
* Add documentation.
For performance annotations we need the generic specializer to trop non-generic metatype argumentrs
(which we don't do in general). For this we need a separate mangling.
[Distributed] generic and inner test; without one edge case
[Distributed] fix distributed_thunk test; unsure about those extra hops, could remove later
[Distributed] Remove type pretending in getSILFunctionType; it is not needed
It seems our constant replacement in the earlier phases is enough, and
we don't need this trick at all.
[Distributed] Use thunk when calling cross-actor on DA protocols
Since I am beginning to prepare for adding real move only types to the language,
I am renaming everything that has to do with copyable types "move only wrapped"
values instead of move only. The hope is this reduces/prevents any confusion in
between the two.
* move the source file to SILOptimizer/IRGenTransforms
* add a file level comment
* document and verify that the pass runs after serialization
* catch overflows when truncating a constant value
The function prologue of async funclets inherits its source location
from the hop_to_executor instruction. This makes it easier to produce
logical backtraces, since the PC in logical frames will always point
to the start if the function.
rdar://89776340
This pass lowers moveonly-ness from the IR after we have finished move only
checking. The transform can be configured in two ways: such that it only handles
trivial types and such that it does trivial and non-trivial types. For ease of
use, I created two top level transforms (TrivialMoveOnlyTypeEliminator and
MoveOnlyTypeElimintor) that invoke the two behaviors by configuring the
underlying transform slightly differently.
For now, I am running first the trivial-only and then the all of the above
lowering. The trivial only pass will remain at this part of the pipeline
forever, but with time we are going to move the lower everything pass later into
the pipeline once I have audited the optimizer pipeline to just not perform any
work on move only types. That being said, currently we do not have this
guarantee and this patch at least improves the world and lets us codegen no
implicit copy code again.
Before the introduction of parameterized existential types, there
was no generic structure under these types. Now that there is, we'll
need to recurse into them to pick up any latent generic types
and lower them appropriately.
rdar://94320481
The main fixes are:
1. MoveOnlyWrapperToCopyableValue needed to be marked as a
FirstArgOwnershipForwardingSingleValueInst instead of just as being an
Ownership mixin. I discovered that in certain cases I was treating it that
way (in the isa check for FirstArgOwnershipForwardingSingleValueInst), but we
were inconsistent. Now we are consistent.
2. MoveOnlyWrapperToCopyableValue is always specified as being initialized as
owned or guaranteed. What is key to understand though is that the
owned/guaranteed property here is more a semantic property around whether the
lifetime of the move only value is ending or if we are allowing it to escape
as an moveonlywrapped unwrapped guaranteed parameter to a function. The main
implication of this is that we can not just use the actual ownership kind to
determine the type of moveonlywrapper_to_copyable we are using. This is b/c
after ownership lowering, the resulting ownership kind will be none, meaning
the instruction will be in an invalid state. Thus the need to represent this
as a separate bit in the instruction. It may make sense to rename the forms
of this instruction to be `[lifetime end]` and `[guaranteed function arg]`
that way it is semantically clear. But I am going to do that change at
another time.
Just forgot to change these when I changed the name of the SILType methods. In
summary:
1. withoutMoveOnly -> removingMoveOnlyWrapper
2. withMoveOnly -> addingMoveOnlyWrapper
These instructions have the following attributes:
1. copyably_to_moveonlywrapper takes in a 'T' and maps it to a '@moveOnly
T'. This is semantically used when initializing a new moveOnly binding from a
copyable value. It semantically destroys its input @owned value and returns a
brand new independent @owned @moveOnly value. It also is used to convert a
trivial copyable value with type 'Trivial' into an owned non-trivial value of
type '@moveOnly Trivial'. If one thinks of '@moveOnly' as a monad, this is how
one injects a copyable value into the move only space.
2. moveonlywrapper_to_copyable takes in a '@moveOnly T' and produces a new 'T'
value. This is a 'forwarding' instruction where at parse time, we only allow for
one to choose it to be [owned] or [guaranteed].
* moveonlywrapper_to_copyable [owned] is used to signal the end of lifetime of
the '@moveOnly' wrapper. SILGen inserts these when ever a move only value has
its ownership passed to a situation where a copyable value is needed. Since it
is consuming, we know that the no implicit copy checker will ensure that if we
need a copy for it, the program will emit a diagnostic.
* moveonlywrapper_to_copyable [guaranteed] is used to pass a @moveOnly T value
as a copyable guaranteed parameter with type 'T' to a function. In the case of
using no-implicit-copy checking this is always fine since no-implicit-copy is a
local pattern. This would be an error when performing no escape
checking. Importantly, this instruction also is where in the case of an
@moveOnly trivial type, we convert from the non-trivial representation to the
trivial representation.
Some important notes:
1. In a forthcoming commit, I am going to rebase the no implicit copy checker on
top of these instructions. By using '@moveOnly' in the type system, we can
ensure that later in the SIL pipeline, we can have optimizations easily ignore
the code.
2. Be aware of is that due to SILGen only emitting '@moveOnly T' along immediate
accesses to the variable and always converts to a copyable representation when
calling other code, we can simply eliminate from the IR all moveonly-ness from
the IR using a lowering pass (that I am going to upstream). In the evil scheme
we are accomplishing here, we perform lowering of trivial values right after
ownership lowering and before diagnostics to simplify the pipeline.
On another note, I also fixed a few things in SILParsing around getASTType() vs
getRawASTType().