Fixes <rdar://60046018> assert: (v->getType().isAddress())
in getAccessedAddress.
MemBehavior compares known memory accesses with some arbitrary value,
which may not be an address. However, we should not call utilities
that work on accessed addresses with an arbitrary value.
This assert is a result of very recent changes to gradually make
memory access utilities more type safe and introduce the concept of a
canonical accessed address. In the future, we may even have a wrapper
type for such a thing. In the SIL optimizer, there are several
different notions of what constitutes the base of a memory
access. Mismatches can lead to subtle bugs.
In order to allow this, I've had to rework the syntax of substituted function types; what was previously spelled `<T> in () -> T for <X>` is now spelled `@substituted <T> () -> T for <X>`. I think this is a nice improvement for readability, but it did require me to churn a lot of test cases.
Distinguishing the substitutions has two chief advantages over the existing representation. First, the semantics seem quite a bit clearer at use points; the `implicit` bit was very subtle and not always obvious how to use. More importantly, it allows the expression of generic function types that must satisfy a particular generic abstraction pattern, which was otherwise impossible to express.
As an example of the latter, consider the following protocol conformance:
```
protocol P { func foo() }
struct A<T> : P { func foo() {} }
```
The lowered signature of `P.foo` is `<Self: P> (@in_guaranteed Self) -> ()`. Without this change, the lowered signature of `A.foo`'s witness would be `<T> (@in_guaranteed A<T>) -> ()`, which does not preserve information about the conformance substitution in any useful way. With this change, the lowered signature of this witness could be `<T> @substituted <Self: P> (@in_guaranteed Self) -> () for <A<T>>`, which nicely preserves the exact substitutions which relate the witness to the requirement.
When we adopt this, it will both obviate the need for the special witness-table conformance field in SILFunctionType and make it far simpler for the SILOptimizer to devirtualize witness methods. This patch does not actually take that step, however; it merely makes it possible to do so.
As another piece of unfinished business, while `SILFunctionType::substGenericArgs()` conceptually ought to simply set the given substitutions as the invocation substitutions, that would disturb a number of places that expect that method to produce an unsubstituted type. This patch only set invocation arguments when the generic type is a substituted type, which we currently never produce in type-lowering.
My plan is to start by producing substituted function types for accessors. Accessors are an important case because the coroutine continuation function is essentially an implicit component of the function type which the current substitution rules simply erase the intended abstraction of. They're also used in narrower ways that should exercise less of the optimizer.
This just eliminates -enable-sil-ownership from all target-swift-frontend and
target-swift-emit-silgen RUN lines. Both of those now include
enable-sil-ownership in their expansion.
NFC unless -enable-verify-exclusivity is on.
Boxed (indirect) enum loads are not formal accesses so they should not
have access markers. For a while, we used UnenforcedAccess in this
case to signal to the verifier that this is actually a safe load. But
that isn't needed. The verifier just ignores loads from unidentified
storage instead.
There are two code paths that had this UnenforcedAccess marker. One
was cleaned up, and the other was not. So finish the cleanup and add a
unit test for both SILGen code paths.
The bulk of the changes are to SILGenApply. As we must now evaluate the
payload ArgumentSource to an RValue, we follow the example of subscripts
and lie to the argument emitter. This evaluates arguments at +1 which
can lead to slightly worse codegen at -Onone.
In a previous commit, I banned in the verifier any SILValue from producing
ValueOwnershipKind::Any in preparation for this.
This change arises out of discussions in between John, Andy, and I around
ValueOwnershipKind::Trivial. The specific realization was that this ownership
kind was an unnecessary conflation of the a type system idea (triviality) with
an ownership idea (@any, an ownership kind that is compatible with any other
ownership kind at value merge points and can only create). This caused the
ownership model to have to contort to handle the non-payloaded or trivial cases
of non-trivial enums. This is unnecessary if we just eliminate the any case and
in the verifier separately verify that trivial => @any (notice that we do not
verify that @any => trivial).
NOTE: This is technically an NFC intended change since I am just replacing
Trivial with Any. That is why if you look at the tests you will see that I
actually did not need to update anything except removing some @trivial ownership
since @any ownership is represented without writing @any in the parsed sil.
rdar://46294760
This commit allows the initial switch subject value to be emitted at +0 if we
can emit it that way. As you can imagine since we have +0 normal function
arguments this should tighten up a lot of code around switches on arguments. So
I got to delete a bunch of code in the tests. = ).
Some things to note:
1. If the switch is given a +1 value, we will still try to let it through at +1
until we hit a part of the decision tree where previously we would need to use
TakeOnSuccess. This means that +1 values that go through irrefutable patterns
like tuple splitting should still be emitted at +1.
2. If we are returned an address only type without a cleanup, we copy it and
pass it down at +1 like the old code.
3. I also elided the last ownership check in SILGenPattern in this commit. After
this, there is only 1 specialization for ownership in the swift compiler that is
in Apply emission. Thats my next target.
rdar://29791263
This does not eliminate the entrypoints on SILBuilder yet. I want to do this in
two parts so that it is functionally easier to disentangle changing the APIs
above SILBuilder and changing the underlying instruction itself.
rdar://33440767
Delay allocating the result buffer for an opened Self return until right before it's needed. When a mutating method is invoked on an existential, the Self type won't be opened until late, when the formal access to the mutable value begins. Fixes rdar://problem/43507711.
Most of this patch is just removing special cases for materializeForSet
or other fairly mechanical replacements. Unfortunately, the rest is
still a fairly big change, and not one that can be easily split apart
because of the quite reasonable reliance on metaprogramming throughout
the compiler. And, of course, there are a bunch of test updates that
have to be sync'ed with the actual change to code-generation.
This is SR-7134.
* Make _sanityCheck internal
* Make _debugPrecondition internal
* Make Optional._unsafelyUnwrappedUnchecked internal.
* Make _precondition internal
* Switch Foundation _sanityChecks to assertions
* Update file check tests
* Remove one more _debugPrecondition
* Update Optimization-with-check tests
Now that access marker verification is strict and exhaustive, adjust some code
to handle the extra markers and extra checks produced by -enable-verify-exclusivity.
This causes default arguments to get emitted after formal evaluation of `self`, allowing protocol methods to access the opened `Self` type of an existential receiver. Fixes rdar://problem/39524104
Once the dust settled, this logic was only protecting a single occurrence of
memory access in SILGenLValue.cpp. It's simpler just to emit the begin/end
access markers in that case. The logic to work around it was nasty.
I am going to leave in the infrastructure around this just in case. But there is
no reason to keep this in the tests themselves. I can always just revert this
and I don't think merge conflicts are likely due to previous work I did around
the tooling for this.
We cannot in general use @guaranteed here, otherwise classes will not
be able to conform to protocols with mutable property requirements
(or we could always open-code materializeForSet witness thunks for
classes, but that has its own downsides so its not a clear win).
Fixes <rdar://problem/36867783>.
-enforce-exclusivity=checked now does what it says. It emits checks at -O, not
just -Onone.
This does not change the default.
-Onone default: -enforce-exclusivity=checked
-O default: -enforce-exclusivity=unchecked