Previously, we based it off of whether or not the original apply had a nothrow
bit. This is incorrect in the case where we added an error result to a function
without an error result. In such a case, we need to /not/ put on the nothrow
bit. This commit generalizes this idea slightly by assuming that if we are asked
to perform this transformation we should just match what the underlying
function_ref (i.e. setting nothrow if the underlying function type has an error
result and not setting nothrow if the underlying function type does not have an
error result).
rdar://47828439
This code was force casting the address of the opened existential to
the lowered SIL type of the known conformance. This is superficially
incorrect because values are stored in existentials with maximal
reabstraction.
Bail on any concrete types that require reabstraction. I don't think
we will hit this currently because there is an earlier check that
prevents optimizing a conformance on a generic types. In theory
someone could add that functionality later for internal generic types
with a single instantiation.
More importantly, we don't want anyone copying this logic and assuming
it's generally correct.
Generalizes the ConcreteExistentialInfo abstraction so it can be used
both by the ExistentialSpecializer and SILCombine, allowing redundant
code in ExistentialSpecializer.cpp to be deleted.
Splits OpenedArchetypeInfo from ConcreteExistentialInfo. Adds a
ConcreteOpenedArchetypeInfo convenience wrapper around them both, for
use wherever we were originally using ConcreteExistentialInfo.
Splits getAddressOfStackInit into getStackInitInst, This is cleaner and
allows both the ExistentialSpecializer and SILCombine to handle more
interesting cases in the future, like unconditional_checked_cast.
Creates utilities, initializeSubstitutionMap, and
initializeConcreteTypeDef to simplify an generalize
ConcreteExistentialInfo.
While rewriting ExistentialSpecializer to use the new
abstraction, I fixed a latent bug in which is was using a SIL
argument index as a function type parameter index (this would
have broken up if/when we decide to enable calls with indirect
results).
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.
Patch produced by
for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
This allows Swift code to implement a fast path via a protocol type
check as follows:
if let existentialVal = genericVal as? SomeProtocol {
// do something fast.
}
Fixes <rdar://problem/46322928> Failure to devirtualize a protocol
method applied to an opened existential blocks implemention of
DataProtocol.
Note: the approach of devirtualization via backward pattern matching
is fundamentally wrong and will never be fully general. It should be a
forward type propagation.
A SIL argument index was being passed as an AST function type
parameter index. Don't do this.
I also cleaned up the peephole to avoid processing indirect results as
parameter indices, but that part is NFC.
Fixes rdar://45415719 Assertion failed: (Index < Length && "Invalid index!")
Fixes <rdar://40555427> [SR-7773]:
SILCombiner::propagateConcreteTypeOfInitExistential fails to full propagate type
substitutions.
Fixes <rdar://problem/40923849>
SILCombiner::propagateConcreteTypeOfInitExistential crashes on protocol
compositions.
This rewrite fixes several fundamental bugs in the SILCombiner optimization that
propagates concrete types. In particular, the pass needs to handle:
- Arguments of callee Self type in non-self position.
- Indirect and direct return values of Self type.
- Types that indirectly depend on Self within callee function signature.
- Protocol composition existentials.
- All of the above need to work for protocol extensions as well as witness methods.
- For protocol extensions, conformance lookup should be based on the existential's conformance list.
Additionally, the optimization should not depend on a SILFunction's DeclContext,
which is not serialized. (In fact, we should prevent SIL passes from using
DeclContext). Furthermore, the code needs to be expressed in a way that one can
reason about correctness and invariants.
The root cause of these bugs is that SIL passes are written based on untested
assumptions of Swift type system. A SIL pass needs to handle all verifiable SIL
input because passes need to be composable. Bail-out logic can be added to
simplify the design; however, _the bail-out logic itself cannot make any
assumptions about the language or type system_ that aren't clearly and
explicitly enforced in the SIL verifier. This is a common mistake and major
source of bugs.
I created as many unit tests as I reasonably could to prevent this code from
regressing. Creating enough unit tests to cover all corner cases that were
broken in the original code would be intractable. But the code has been
simplified such that many corner cases disappear.
This opens up some oportunity for generalizing the optimization and eliminating
special cases. However, I want this PR to be limited to fixing correctness
issues only. In the long term, it would be preferable to replace this
optimization entirely with a much more powerful general type propagation pass.
Introduced during the bring-up of the generics system in July, 2012,
Substitution (and SubstitutionList) has been completely superseded by
SubstitutionMap. R.I.P.
This is a property of an instruction and should be a member
function of `SILInstruction` and not a free function in
`DebugUtils`. Discussed with Adrian.
Certain patterns of directly applied partial_apply's were not being
inlined. This can happen when a closure is defined in the
implementation of a generic witness method. I noticed this issue while
debugging SR-6254: "Fix (or explain) strange ways to make code >3
times faster/slower".
After the witness method is devirtualization and specialized, the
closure application looks like this:
%pa = partial_apply [callee_guaranteed] %fn() : $@convention(thin) (@in Int) -> @out Int
%cvt = convert_escape_to_noescape %pa
apply %cvt(...)
SILCombine already removes the partial_apply and convert_escape_to_noescape generating:
%thick = thin_to_thick %fn
apply %thick(...)
However, surprisingly, neither the inliner nor SILCombine can handle this.
I cleaned up the code in SILCombine's apply visitor that handles
thin_to_thick and generalized it to handle this and other patterns.
I also added a restriction to this code so that it doesn't break SIL
ownership in the future, as I discussed with Arnold.
Certain patterns of directly applied partial_apply's were not being
inlined. This can happen when a closure is defined in the
implementation of a generic witness method. I noticed this issue while
debugging SR-6254: "Fix (or explain) strange ways to make code >3
times faster/slower".
After the witness method is devirtualization and specialized, the
closure application looks like this:
%pa = partial_apply [callee_guaranteed] %fn() : $@convention(thin) (@in Int) -> @out Int
%cvt = convert_escape_to_noescape %pa
apply %cvt(...)
SILCombine already removes the partial_apply and convert_escape_to_noescape generating:
%thick = thin_to_thick %fn
apply %thick(...)
However, surprisingly, neither the inliner nor SILCombine can handle this.
I cleaned up the code in SILCombine's apply visitor that handles
thin_to_thick and generalized it to handle this and other patterns.
I also added a restriction to this code so that it doesn't break SIL
ownership in the future, as I discussed with Arnold.
This patch both makes debug variable information it optional on
alloc_stack and alloc_box instructions, and forced variable
information on debug_value and debug_value_addr instructions. The
change of the interface uncovered a plethora of bugs in SILGen,
SILTransform, and IRGen's LoadableByAddress pass.
Most importantly this fixes the previously commented part of the
DebugInfo/local-vars.swift.gyb testcase.
rdar://problem/37720555
Create helpers in InstructionUtils.h wherever we need a guarantee that the diagnostics cover the same patterns as the verifier. Eventually this will be called from both SILVerifier and the diagnostic pass:
- findAccessedAddressBase
- isPossibleFormalAccessBase
- isPartialApplyOfReabstractionThunk
- findClosureForAppliedArg
- visitAccessedAddress
Add partial_apply verification assert.
This applies the normal "find a closure" logic inside the "find all partial_apply uses" verification. Making the verifier round-trip ensures that we don't have holes in exclusivity enforcement related to this logic.
The bug was introduced recently:
commit ac8a48b2
Date: Fri Oct 6 12:34:14 2017 -0700
Fixes <rdar://35800315> (crash using freed OpenedArchetypesTracker).
This is not NFC because the isUseAfterFree helper and surrounding code
is rewritten. The previous code's intention is unclear, but it was at
best imprecise and unsafe w.r.t. future SIL changes.
Pattern matching code that becomes highly complicated should
be commented with motivating SIL examples.