Specifically:
1. I removed an extra defensive copy that we put in place some time ago that
isn't really warranted. We know that we have an @owned value, so can safely just
pass the value as a @guaranteed parameter. This also eliminates an ownership
error that would occur due to my not having updated this code for ownership in
tree.
2. I also ensured that if we are performing a loadable address bridging cast ->
value bridging cast that we store the loadable value back into memory after we
perform the cast. Otherwise, it appears to leak to the ownership verifier.
I also centralized the non-ownership tests for this into one place
(const_fold_objc_bridge.sil => constant_propagation_objc.sil).
Specifically, in this part of the cast optimizer we are trying to optimize casts
that can be done in two parts. As an example consider: NSObject ->
Array<Any>. In this case, we first cast from NSObject -> NSArray and then try to
conditionally bridge to Array<Any> from NSArray.
The problem is we did not destroy the NSObject correctly if the first cast
failed. I couldn't figure out how to create an actual swift test case that
produces this problem since we are pretty conservative about triggering this
code path. But in SIL it is pretty easy and in ossa, we trigger the ownership
verifier.
This is another victory for the ownership verifier!
rdar://51753580
The specific problem here is that we are setting the insertion point of a
SILBuilder and not unsetting it. I fixed the problem by creating a separate
builder so the original builder stays put.
I originally came across this in my work on moving ownership stripping after the
diagnostic passes. This patch fixes it without my other changes to ease
cherry-picking to 5.1.
I also added more test coverage by expanding the test case to also handle
copy_on_success and take_always.
rdar://51093557
This is a large patch; I couldn't split it up further while still
keeping things working. There are four things being changed at
once here:
- Places that call SILType::isAddressOnly()/isLoadable() now call
the SILFunction overload and not the SILModule one.
- SILFunction's overloads of getTypeLowering() and getLoweredType()
now pass the function's resilience expansion down, instead of
hardcoding ResilienceExpansion::Minimal.
- Various other places with '// FIXME: Expansion' now use a better
resilience expansion.
- A few tests were updated to reflect SILGen's improved code
generation, and some new tests are added to cover more code paths
that previously were uncovered and only manifested themselves as
standard library build failures while I was working on this change.
The ownership kind is Any for trivial types, or Owned otherwise, but
whether a type is trivial or not will soon depend on the resilience
expansion.
This means that a SILModule now uniques two SILUndefs per type instead
of one, and serialization uses two distinct sentinel IDs for this
purpose as well.
For now, the resilience expansion is not actually used here, so this
change is NFC, other than changing the module format.
This could probably be an error, but I am leaving it to preserve previous
behavior. The reason I am hoisting this is that I am hoisting it before we
potentially split a basic block. When we evaluate if we can early exit, we
should never do work before we know that we will emit /something/.
This code today only handles the following two instructions:
1. checked_cast_addr_br
2. unconditional_checked_cast_addr
We were asserting that the source/dest of these values were addresses... but
they are obviously are!
I think that this is a result of previous refactorings. This code has a long
time assert in it that Src (since 2016) is an address and for a long time the bridged type has
always been an object (since 2015). So, thus we know that the following is always true.
SILBridgedTy != Src->getType()
I also removed a level of indentation. NFC.
The 2015 commit hash is: 2dd38eee0e (the original commit).
The 2016 commit hash is: 506ab9809f
I am going to use this to refactor a bunch of the goop in the cast optimizer. At
a high level, we are really just performing a giant switch over the casts to
grab different state. We then take that state and we pass it into the bridge
cast optimizer.
To make such code more compact/easier to understand, I am adding in this commit
a type erased dynamic cast instruction type called "SILDynamicCastInst". In
subsequent commits, I wire up each of the individual instructions to it one at a
time.
As an additional advantage it will enable us to take advantage of covered
switches when ever in the future we introduce new casts.