This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
Properties that are marked as initialized are printed as `[assign=<index>]`
where `<index>` point to the property position in `getInitializedProperties()`
list.
Some properties from `initializes(...)` list could be already initialized,
which means that Raw SIL lowering has to emit `destroy_addr` for them
before calling init accessor.
This instruction is similar to AssignByWrapperInst, but instead of having
a destination operand, the initialization is fully factored into the init
function operand. Like AssignByWrapper, AssignOrInit has partial application
operands of both the initializer and the setter, and DI will lower the
instruction to a call based on whether the assignment is initialization or
a setter call.
Just the $*T -> $*@moveOnly T variant for addresses. Unlike the object version
this acts like a cast rather than something that provides semantics from the
frontend to the optimizer.
The reason why I am using a different instruction for addresses and objects here
is that the object checker doesnt have to deal with things like initialization.
The new alloc_pack_metadata and dealloc_pack_metadata are inserted as
part of IRGen lowering. The former indicates that the next instruction
might result in on-stack pack metadata being emitted. The latter
indicates that this is the position at which metadata emitted on behalf
of its operand should be cleaned up.
User code should not be diagnosed as "unreachable" by the SIL optimizer when
the no-return function that made the code unreachable is a compiler inserted
call to `_diagnoseUnavailableCodeReached()`.
Part of rdar://107388493
When eliminating lexical lifetimes, also eliminate the lifetimes
introduced by move_values in addition to those introduced by
begin_borrow and communicated via alloc_stack.
This is used to teach the checker that the thing being checked is supposed to be
uninitialized at the mark_must_check point so that we don't put a destroy_addr
there.
The way this is implemented is that we always initially add
assignable_but_not_consumable but in DI once we discover that the assign we are
guarding is an init, we convert the assignable to its initable variant.
rdar://106525988
This is in preparation for wiring up debug info support for noncopyable
values. Originally this flag name made sense since it was set when we performed
consume operator checking. Now I am going to use it for noncopyable types as
well. I think the new name uses_moveable_value_debuginfo actually describes what
the flag is supposed to do, tell IRGen that the value may be moved since it
needs to use moveable value debug info emission.
`isSuccessorBlock` and `isPredecessorBlock` are dangerous because they can easily lead to quadratic behavior.
Fortunately they are not used anywhere (except in one place for verification, which I rewrote).
CSE relies on OSSA RAUW for lifetime extension when replacing a redundant instruction.
OSSA RAUW however does not handle lifetime extension for escaped base values.
Values escape from ownership via pointer escape, bitwise escape, forwarding unowned operations
and have none or unowned ownership. For all such values do not look through ownership instructions
while determining equality. It is possible to CSE such values with equivalent operands, because the
operand use guarantees lifetime of the base operand.
It's need to correctly maintain dependencies from an open-existential instruction to a `keypath` instruction which uses the opened type.
Fixes a SILVerifier crash.
rdar://105517521
Although nonescaping closures are representationally trivial pointers to their
on-stack context, it is useful to model them as borrowing their captures, which
allows for checking correct use of move-only values across the closure, and
lets us model the lifetime dependence between a closure and its captures without
an ad-hoc web of `mark_dependence` instructions.
During ownership elimination, We eliminate copy/destroy_value instructions and
end the partial_apply's lifetime with an explicit dealloc_stack as before,
for compatibility with existing IRGen and non-OSSA aware passes.
This is used to model global_addr/ref_element_addr/escaping closure captures
where we do not want to allow the user to consume the memory (leaving the memory
in a potentially uninitialized state), but we do want to allow for the user to
assign over the memory all at once.
Consider a situation like the following:
```
@_moveOnly
struct FileDescriptor {
var state: CInt = ...
}
final class Klass {
var descriptor = ...
}
func consumeDescriptor(_ x: __owned FileDescriptor) {}
// Eventually both of these will point at the same class.
var globalKlass = ...
var globalKlass2 = ...
func memoryUnsafe() {
consumeDescriptor(globalKlass.descriptor)
consumeDescriptor(globalKlass2.descriptor)
}
func callMemoryUnsafe() {
globalKlass2 = globalKlass()
memoryUnsafe()
}
```
Notice how in the above in memoryUnsafe, locally the compiler has no way of
knowing that globalKlass and globalKlass2 actually point at the same class and
thus we are attempting to consume the same descriptor twice. This is even
allowed by exclusivity. If descriptor was not move only, this would be safe
since we would just copy the value when we consume it. But b/c we ar3e using
move only, we must take from the memory.
This fits the name of the check better. The reason I am doing this renaming is
b/c I am going to add a nonconsumable but assignable check for
global_addr/ref_element_addr/captures with var semantics.
This reflects better the true meaning of this check which is that a value marked
with this check cannot be consumed on its boundary at all (when performing
let/var checking) and cannot be assigned over when performing var checking.
This instruction can be inserted by Onone optimizations as a replacement for deleted instructions to
ensure that it's possible to single step on its location.
This allows dynamically indexing into tuples. IRGen not yet
implemented.
I think I'm going to need a type_refine_addr instruction in
order to handle substitutions into the operand type that
eliminate the outer layer of tuple-ness. Gonna handle that
in a follow-up commit.
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.