Sometimes when building the SwiftCompilerSources with a host compiler, linking fails with unresolved symbols for DenseMap and unique_ptr destroys.
This looks like a problem with C++ interop: the compiler thinks that destructors for some Analysis classes are materialized in the SwiftCompilerSources, but they are not.
Explicitly defining those destructors fixes the problem.
This is code that I am fairly familiar with but it still took a day of
investigation to figure out how it is supposed to be used now in the
presence of bridging.
This primarily involved ruling out the possibity that the mid-level
Swift APIs could at some point call into the lower-level C++ APIs.
The biggest problem was that AliasAnalysis::getMemoryBehaviorOfInst()
was declared as a public interface, and it's name indicates that it
computes the memory behavior. But it is just a wrapper around a Swift
API and never actually calls into any of the C++ logic that is
responsible for computing memory behavior!
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
The `isEscaping` function is called a lot from ARCSequenceOpt and ReleaseHoisting.
To avoid quadratic complexity for large functions, limit the amount of work what the EscapeUtils are allowed to to.
This keeps the complexity linear.
The arbitrary limit is good enough for almost all functions.
It lets the EscapeUtils do several hundred up/down walks which is much more than needed in most cases.
Fixes a compiler hang
https://github.com/apple/swift/issues/63846
rdar://105795976
Although nonescaping closures are representationally trivial pointers to their
on-stack context, it is useful to model them as borrowing their captures, which
allows for checking correct use of move-only values across the closure, and
lets us model the lifetime dependence between a closure and its captures without
an ad-hoc web of `mark_dependence` instructions.
During ownership elimination, We eliminate copy/destroy_value instructions and
end the partial_apply's lifetime with an explicit dealloc_stack as before,
for compatibility with existing IRGen and non-OSSA aware passes.
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`
The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.
rdar://102362022
This invalidation kind is used when a compute-effects pass changes function effects.
Also, let optimization passes which don't change effects only invalidate the `FunctionBody` and not `Everything`.
Added new C++-to-Swift callback for isDeinitBarrier.
And pass it CalleeAnalysis so it can depend on function effects. For
now, the argument is ignored. And, all callers just pass nullptr.
Promoted to API the mayAccessPointer component predicate of
isDeinitBarrier which needs to remain in C++. That predicate will also
depends on function effects. For that reason, it too is now passed a
BasicCalleeAnalysis and is moved into SILOptimizer.
Also, added more conservative versions of isDeinitBarrier and
maySynchronize which will never consider side-effects.
In theory, the analysis invalidation notifications should assure that every function has a CallerAnalysis::FunctionInfo in `funcInfos`.
But it's not unlikely that we are missing some of those notifications.
We got some not-reproducible crash reports because of missing function infos in CallerAnalysis.
With this change the analysis accepts missing function infos and does the right thing if such an info is missing.
In the long term we should replace CallerAnalysis by FunctionUses, anyway.
rdar://99653954
We had two notions of canonical types, one is the structural property
where it doesn't contain sugared types, the other one where it does
not contain reducible type parameters with respect to a generic
signature.
Rename the second one to a 'reduced type'.
IterableBackwardReachability just requires an iterable list of gens.
ShrinkBorrowScope, LexicalDestroyHoisting, and SSADestroyHoisting all
need to be able to check whether a given instruction is scope ending
quickly. Use a SmallSetVector rather than a SmallVector for the gens in
all three.
The new utility finds access scopes which are barriers by finding access
scopes which themselves contain barriers. This is necessary to (1)
allow hoisting through access scopes when possible (i.e. not simply
treating all end_access instructions as barriers) and (2) not hoist into
access scopes that contain barriers and in so doing introduce
exclusivity violations.
The new optimistic, iterative backward reachability is optimized to do
as little work as possible. Only blocks not all of whose successors are
kills participate in the worklist at all. The blocks within that
discovered set are visited via a worklist which tracks blocks which have
been found to be unreachable at begin and whose
unreachable-at-begin-ness must be propagated into
unreachable-at-end-ness of its predecessors.
rdar://92545900
* C++: add a function `getDestructors(SILType type, bool isExactType)’: if the type is a final class or `isExactType` is true, then return the one and only destructor of that class.
* swift: add `getDestructor(ofExactType type: Type)` and `getIncompleteCallees`
* swift: remove `getDestructor` from the PassContext. The API of the `calleeAnalysis` can be used instead.
Handle recursive non-escaping local functions.
Previously, it was thought that recursion would force a closure to be
escaping. This is not necessarilly true.
Update AccessEnforcementSelection to conservatively handle closure cycles.
Fixes rdar://88726092 (Compiler hangs when building)
Previously, Reachability assumed that phis were not barriers. Here,
handling for barrier phis is added. To that end, a new delegate
callback `checkReachableBarrier(PhiValue)` is added. Before marking the
beginning of a block as reached (or any of its predecessors), check
whether each argument that is a phi is a barrier. If any is, then
reachability is done.
Implemented the new method in SSADestroyHoisting by splitting apart the
classification of an instruction and the work to do in response to
visiting an instruction. Then, when visiting a PhiValue, just check
whether any of the predecessors terminators are classified as barriers.
That way, seeing that they're classified that way doesn't result in
noting down that those terminators had been reached (which indeed they
will not have been if any of the terminators from which the values are
flowing into the phi are barriers).
Pessimistic, non-iterative data flow for analyzing backward reachability
from a set of last uses to their dominating def or nearest barrier.
Meet: ReachableEnd(predecessor) = intersection(ReachableBegin, successors)
Intended for frequently called utilities where minimizing the cost of
data flow is more important than analyzing reachability across
loops. Expected to visit very few blocks because barriers often occur
close to a last use.
Note: this does not require initializing bitsets for all blocks in the
function for each SSA value being analyzed.