It lowers let property accesses of classes.
Lowering consists of two tasks:
* In class initializers, insert `end_init_let_ref` instructions at places where all let-fields are initialized.
This strictly separates the life-range of the class into a region where let fields are still written during
initialization and a region where let fields are truly immutable.
* Add the `[immutable]` flag to all `ref_element_addr` instructions (for let-fields) which are in the "immutable"
region. This includes the region after an inserted `end_init_let_ref` in an class initializer, but also all
let-field accesses in other functions than the initializer and the destructor.
This pass should run after DefiniteInitialization but before RawSILInstLowering (because it relies on `mark_uninitialized` still present in the class initializer).
Note that it's not mandatory to run this pass. If it doesn't run, SIL is still correct.
Simplified example (after lowering):
bb0(%0 : @owned C): // = self of the class initializer
%1 = mark_uninitialized %0
%2 = ref_element_addr %1, #C.l // a let-field
store %init_value to %2
%3 = end_init_let_ref %1 // inserted by lowering
%4 = ref_element_addr [immutable] %3, #C.l // set to immutable by lowering
%5 = load %4
Codegen is the same, but `begin_dealloc_ref` consumes the operand and produces a new SSA value.
This cleanly splits the liferange to the region before and within the destructor of a class.
In order to support lazy typechecking during module emission for modules
containing specialized functions, the computation of generic signatures for
`@_specialized` attributes must be requestified.
Resolves rdar://115569606
Although by analogy with def instructions as barrier instructions one
could understand how a block where the def appears as a phi could be
regarded as a barrier block, the analogy is nonobvious.
Reachability knows the difference between an initial block and a barrier
block. Although most current clients don't care about this distinction,
one does. Here, Reachability calls back with visitInitialBlock for the
former and visitBarrierBlock for the latter.
Most clients are updated to have the same implementation in both
visitBarrierBlock and visitInitialBlock. The findBarriersBackward
client is updated to retain the distinction and pass it on to its
clients. Its one client, CanonicalizeOSSALifetime is updated to have a
simpler handling for barrier edges and to ignore the initial blocks.
- VTableSpecializer, a new pass that synthesizes a new vtable per each observed concrete type used
- Don't use full type metadata refs in embedded Swift
- Lazily emit specialized class metadata (LazySpecializedClassMetadata) in IRGen
- Don't emit regular class metadata for a class decl if it's generic (only emit the specialized metadata)
We allow none values to be stored to a non-trivial enum.
For such store_borrow, `LiveValues::forValues` used
an Owned storage type, but endLexicalLifetime expected Guaranteed
storage type, leading to a compiler crash.
For store_borrow, use the LiveValues::forGuaranteed and for store
use LiveValues::forOwned to avoid this.
Fixes rdar://114390472
I was originally hoping to reuse mark_must_check for multiple types of checkers.
In practice, this is not what happened... so giving it a name specifically to do
with non copyable types makes more sense and makes the code clearer.
Just a pure rename.
When the differentiating a function containing loops, we allocate a linear map context object on the heap. This context object may store non-trivial objects, such as closures, that need to be released explicitly. Fix the autodiff linear map context allocation builtins to correctly release such objects and not just free the memory they occupy.
Owned lifetime canonicalization bails on move-only values.
Previously, though, every value that was fed to canonicalization was
then attempted to be deleted. For dead move-only values, the result
could be to shorten move-only lifetimes, which is illegal per language
rules.
Here, this is fixed by not attempting to delete owned values for which
canonicalization bailed.
rdar://114323803
To eliminate copies which become newly spurious, Mem2Reg canonicalizes
the lifetimes of values that are stored and of newly introduced phis
after rewriting.
It's possible, however, for the values that are stored to be deleted
during canonicalization if a value and its copy are both stored to the
address. Such values must not be canonicalized. So check whether
values have been erased before canonicalizing them.
rdar://113762355
There is no implementation to handle insertion of compensating releases of the non-trivial store's src for this case.
This never really happens, because destructor analysis is very limited and we end up banning alloc_ref with ref count instructions.