Having added these, I'm not entirely sure we couldn't just use
alloc_stack and dealloc_stack. Well, if we find ourselves adding
a lot of redundancy with those instructions (e.g. around DI), we
can always go back and rip these out.
- SILPackType carries whether the elements are stored directly
in the pack, which we're not currently using in the lowering,
but it's probably something we'll want in the final ABI.
Having this also makes it clear that we're doing the right
thing with substitution and element lowering. I also toyed
with making this a scalar type, which made it necessary in
various places, although eventually I pulled back to the
design where we always use packs as addresses.
- Pack boundaries are a core ABI concept, so the lowering has
to wrap parameter pack expansions up as packs. There are huge
unimplemented holes here where the abstraction pattern will
need to tell us how many elements to gather into the pack,
but a naive approach is good enough to get things off the
ground.
- Pack conventions are related to the existing parameter and
result conventions, but they're different on enough grounds
that they deserve to be separated.
With f9861ec9c0 we consider SILPhiArgument in a
block with no predecessors as phis, remove assert that we expect non-empt predecessors
to reflect this change.
I've also fixed this so that it should work on instructions that
define multiple values. Someday we'll change all the open_existential
instructions to produce different values for the type dependency and
the value result; today is not that day, though.
Add TermInst::forwardedOperand.
Add SILArgument::forwardedTerminatorResultOperand. This API will be
moved into a proper TerminatorResult abstraction.
Remove getSingleTerminatorOperand, which could be misused because it's
not necessarilly forwarding ownership.
Remove the isTransformationTerminator API, which is not useful or well
defined.
Rewrite several instances of complex logic to handle block arguments
with the simple terminator result API. This defines away potential
bugs where we don't detect casts that perform implicit conversion.
Replace uses of the SILPhiArgument type and code that explicitly
handle block arguments. Control flow is irrelevant in these
situations. SILPhiArgument needs to be deleted ASAP. Instead, use
simple APIs like SILArgument::isTerminatorResult(). Eventually this
will be replaced by a TerminatorResult type.
For yielded, nontrivial addresses, verify based on convention:
- guaranteed -> must be initialized at end_apply/abort_apply
- owned -> must be deinitialized at end_apply/abort_apply
- inout -> must be initialized at end_apply/abort_apply
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`
The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.
rdar://102362022
Previously, logging of the actually problematic instruction was guarded
by LLVM_DEBUG. Meanwhile the verifier's require method prints an
instruction (usually one different from that at which the non-contiguous
scope was encountered).
Here, instead, the problematic instruction and the instruction which
defined the previous scope are printed to llvm::errs always (i.e.
whenever verification is actually run).
Additionally, debug-info logging is forcibly set on upon failure so that
the logs clearly show both what the previous scope was, what the current
scope is, and what instructions defined them.
We can't verify that store borrows aren't nested until we can reliably
compute liveness.
This can be fixed in two ways, both of which we plan to do ASAP:
(1) With complete lifetimes, this no longer needs to perform transitive
liveness at all.
(2) findInnerTransitiveGuaranteedUses, which ends up being called on the
load_borrow to compute liveness, can be taught to transitively process
InteriorPointer uses instead of returning PointerEscape. We need to make
sure all uses of the utility need to handle this first.