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
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.
d971f125d9 added a usage of std::variant and std::holds_alternative to
SILOptimizer/Differentiation/AdjointValue.h, but did not include variant
directly. This caused issues while building on Linux.
Previously, we were not recognizing that a ref_element_addr from an actor object
is equivalent to the actor object and we shouldn't allow for it to be consumed.
rdar://115132118
Really, we should just be using representative values here in general since it
serves the same purpose and makes it easier to trace back values. But this in
the short term makes the output easier to reason about.
Specifically:
1. Converted llvm::errs() -> llvm::dbgs() when using LLVM_DEBUG.
2. Converted a dump method on errs to be a print method on dbgs that is called from dump with print(llvm::dbgs()).
- 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 already use a complexity limit for other functions in AliasAnalysis.
This is a workaround for quadratic complexity in ARCSequenceOpts.
Fixes a compile time problem
rdar://114352817
When serializing modules with `-experimental-skip-all-function-bodies`, this
analysis was eagerly populating a cache that would go unused since there is no
optimization to do. With `-experimental-lazy-typecheck`, this work would also
trigger unnecessary typechecking requests. NFC.
When serializing modules with `-experimental-skip-all-function-bodies`, this
analysis was eagerly populating a cache that would go unused since there is no
optimization to do. With `-experimental-lazy-typecheck`, this work would also
trigger unnecessary typechecking requests. NFC.
Without this fix, the new 'consuming' and 'borrowing' keywords cannot
be used with trivial types. Which means, for example, they can't be
used in macro expansions that work on various types.
Fixes patterns like:
public func test1(i: consuming Int) -> Int {
takeClosure { [i = copy i] in i }
}
public func test2(i: borrowing Int) -> Int {
takeClosure { [i = copy i] in i }
}
public func test3(i: consuming Int) -> Int {
takeClosure { i }
}
// Sadly, test4 is still incorrectly diagnosed.
public func test4(i: borrowing Int) -> Int {
takeClosure { i }
}
Fixes rdar://112795074 (Crash compiling function that has a macro annotation and uses `consuming`)