Type annotations for instruction operands are omitted, e.g.
```
%3 = struct $S(%1, %2)
```
Operand types are redundant anyway and were only used for sanity checking in the SIL parser.
But: operand types _are_ printed if the definition of the operand value was not printed yet.
This happens:
* if the block with the definition appears after the block where the operand's instruction is located
* if a block or instruction is printed in isolation, e.g. in a debugger
The old behavior can be restored with `-Xllvm -sil-print-types`.
This option is added to many existing test files which check for operand types in their check-lines.
The pass rewrites opaque values in reverse post order of their
definitions. When an opaque value is rewritten, both its definition and
its uses are rewritten. When a def or a use is rewritten, in order to
materialize an address with which to rewrite, projection instructions
are created. Previously, these projections were created at the site of
the def or use. Some of these projection instructions may be reused when
rewriting later opaque values.
As a result, it's possible to have two opaque values `A` and `B` (which
are rewritten in that order) such that rewriting a use of `A` which
occurs "after" the def (or a use) of `B` creates a projection `P` which
is then used by that "earlier" def (or use) of `B`:
```
A =
B = // relies on P
use B
use A // creates some projection P
```
When rewriting the def (or that use, respectively) of `B`, the
projection which was created for the use of `A` will be reused. And
previously, the projection would be created at the use of A. But that
projection instruction was "after" the place where it is used when
rewriting the def or use of `B`. That's invalid!
To address this, rather than creating projections at the instruction
being rewritten, instead create them "as early as possible". The
locations where they will be created are chosen so as to dominate all
uses.
During storage allocation, create all alloc_stacks at the front of the
function entry block, except those for opened existential types. Do not
create any dealloc_stacks, even for opened existential types.
Then, after function rewriting, position the alloc_stacks according to
uses, except those for opened existential types. This means allocating
in the block that's the least common ancestor of all uses. At this
point, create dealloc_stacks on the dominance frontier of the
alloc_stacks, even for allocations for opened existential types.
The behavior for opened existential types diverges from all others in
order to maintain SIL validity (as much as possible) while the pass
runs. It would be invalid to create the alloc_stacks for opened
existential types at the front of the entry block because the type which
is opened is not yet available, but that type's opening must dominate
the corresponding alloc_stack.
All checked casts are emitted as checked_cast_br
instructions. More than just the instructions which produce or consume
an opaque value must be rewritten as checked_cast_addr_br
instructions. In particular, all those instructions for which
canIRGenUseScalarCheckedCastInstructions returns false must be rewritten
as checked_cast_addr_br instructions.
Note the instructions to rewrite like that while visiting values and
then rewrite them near the end of rewriting.
All checked casts are emitted as unconditional_checked_cast
instructions. More than just the instructions which produce or consume
an opaque value must be rewritten as unconditional_checked_cast_addr
instructions. In particular, all those instructions for which
canIRGenUseScalarCheckedCastInstructions returns false must be rewritten
as unconditional_checked_cast_addr instructions.
Note the instructions to rewrite like that while visiting values and
then rewrite them near the end of rewriting.
When branching to the exit block, flatten an @out tuple return value
into its components, as is done for all other return values.
In the exit block, when constructing the @out tuple to return, visit the
tuple-type-tree of the return value to reconstruct the nested tuple
structure: @out tuple returns are not flattened, unlike regular tuple
returns.
When a `begin_borrow [lexical]` is lowered, the lifetime that it
describes can't be shortened (or eliminated) when lowering. In some
cases, though, there will not be an alloc_stack corresponding directly
to the value being borrowed.
In these cases, mark the whole aggregate lexical.