These instructions model a conversion in between ownership kinds without the result actually being owned by anything. As a result:
1. From an operand perspective, the instruction is treated like a pointer escape.
2. From a value perspective, the instruction returns a value with
OwnershipKind::Unowned (to force the value to be copied before it can be used
in an owned or guaranteed way) and
Example:
```
sil @example : $@convention(thin) (@owned Klass) -> @owned @sil_unowned Klass {
bb0(%0 : @owned $Klass):
// Note that the ref_to_unowned does not consume %0 but instead converts %0
// from a "strong" value to a "safe unowned" value. A "safe unowned" value is
// a value that corresponds to an 'unowned' value at the Swift level that use
// unowned reference counting. At the SIL level these values can be recognized
// by their types having the type attribute @sil_unowned. We have not
// incremented the unowned ref count of %1 so we must treat %1 as unowned.
%1 = ref_to_unowned %0 : $Klass
// Then before we can use %2 in any way as a "safe unowned" value we need to
// bump its unowned ref count by making a copy of the value. %2 will be a
// "safe unowned" value with OwnershipKind::Owned ensuring that we decrement
// the unowned ref count and do not leak said ref count.
%2 = copy_value %1 : $@sil_unowned $Klass
// Then since the original ref_to_unowned did not consume %0, we need to
// destroy it here.
destroy_value %0 : $Klass
// And then return out OwnershipKind::Owned @sil_unowned Klass.
return %2 : $@sil_unowned $Klass
}
```
It is illegal to borrow an unowned value. Unowned values are only
allowed to have specific instantaneous uses.
In this case, an unchecked conversion is valid because there is an
assumption that within a destructor, self is guaranteed.
It's against the principles of pass design to check the driver mode
within the pass. A pass always needs to do the same thing regardless
of where it runs in the pass pipeline. It also needs to be possible to
test passes in isolation.
The `try await` ordering is both easier to read and indicates the order
of operations better, because the suspension point occurs first and
then one can observe a thrown error.
Add README files explaining the differentiable programming test suite.
Add lit.local.cfg files so individual tests do not need to add
`REQUIRES: asserts` in these directories:
- test/AutoDiff/compiler_crashers
- test/AutoDiff/compiler_crashers_fixed
Motivation: it is important for compiler crasher tests to require assertions
enabled, because many of these tests crash on compiler assertions.
These are always safe in OSSA since what we are doing here is hoisting the
ref_to_raw_pointer up the def-use chain without deleting any instructions unless
we know that they do not have any uses (in a strict sense so destroy_value is
considered a use). E.x.:
```
%0 = ...
%1 = unchecked_ref_cast %0
%2 = ref_to_raw_pointer %1
```
->
```
%0 = ...
%1 = unchecked_ref_cast %0
%2 = ref_to_raw_pointer %0
```
Notice, how we are actually not changing %1 at all. Instead we are just moving
an instantaneous use earlier. One thing that is important to realize is that
this /does/ cause us to need to put the ref_to_raw_pointer at the insert
location of %0 since %0's lifetime ends at the unchecked_ref_cast if the value
is owned.
NOTE: I also identified the tests from sil_combine.sil that had to do with these
simplifications and extracted them into sil_combine_casts.sil and did the
ossa/non-ossa tests side by side. I am trying to fix up the SILCombine tests as
I update stuff, so if I find opportunities to move tests into a more descriptive
sub-file, I am going to do so.
As an aside, to make it easier to transition SILCombine away from using a
central builder, I added a withBuilder method that creates a new SILBuilder at a
requested insertPt and uses the same context as the main builder of
SILCombine. It also through the usage of auto makes really concise pieces of
code. Today to do this just using builder, we would do:
```
SILBuilderWithScope builder(insertPt, Builder);
builder.createInst1(insertPt->getLoc(), ...);
builder.createInst2(insertPt->getLoc(), ...);
builder.createInst3(insertPt->getLoc(), ...);
auto *finalValue = builder.createInst4(insertPt->getLoc(), ...);
```
Thats a lot of typing and wastes a really commonly used temp name (builder) in
the local scope! Instead, using this API, one can write:
auto *finalValue = withBuilder(insertPt, [&](auto &b, auto l) {
b.createInst1(l, ...);
b.createInst2(l, ...);
b.createInst3(l, ...);
return b.createInst4(l, ...);
});
There is significantly less to type and auto handles the types for us. The
withBuilder construct is just syntactic since we always inline it.
Improve data-race detection for local variables and global/static variables
* Only diagnose these cases at all, not (e.g.) class instance members
* For local functions, they run concurrently if they were referenced somewhere
that runs concurrently
The latter required moving checking of both actor isolation and effects
for local functions to the point at which their enclosing (non-local)
functions are checked, because we need to reason about the
type-checked bodies of local functions.
Synthesizing the body of a throwing main didn't take into account the
implicit try. We were creating one, then just leaving it off. This patch
actually passes the modified AST branch through to the emitted return
statement, rather than just keeping the call.
As a separate note, I hit an assert saying that a source range must
either be completely invalid or completely valid when just passing the
invalid SourceLoc to the TryExpr. I've changed it to just take the
SourceLoc from the implicit CallExpr, which should be the same as the
invalid SourceLoc, but seems to inherit it from another place.
The one opt we perform here is that we promote fix_lifetime on loadable
alloc_stack addresses to fix_lifetimes on objects by loading the underlying
value and putting the fix lifetime upon it.