mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[move-only] Refactor CanonicalizeOSSALifetime::canonicalizeValueLifetime into an API that computes liveness and a second API that rewrites copies/destroys and fix up MoveOnly checkers to use it.
For those who are unaware, CanonicalizeOSSALifetime::canonicalizeValueLifetime() is really a high level driver routine for the functionality of CanonicalizeOSSALifetime that computes liveness and then rewrites copies using boundary information. This change introduces splits the implementation of canonicalizeValueLifetime into two parts: a first part called computeLiveness and a second part called rewriteLifetimes. Internally canonicalizeValueLifetime still just calls these two methods. The reason why I am doing this is that it lets the move only object checker use the raw liveness information computed before the rewriting mucks with the analysis information. This information is used by the checker to compute the raw liveness boundary of a value and use that information to determine the list of consuming uses not on the boundary, consuming uses on the boundary, and non-consuming uses on the boundary. This is then used by later parts of the checker to emit our errors. Some additional benefits of doing this are: 1. I was able to eliminate callbacks in the rewriting stage of CanonicalOSSALifetimes which previously gave the checker this information. 2. Previously the move checker did not have access to the non-consuming boundary uses causing us to always fail appropriately, but sadly not emit a note showing the non-consuming use. I am going to wire this up in a subsequent commit. The other change to the implementation of the move checker that this caused is that I needed to add an extra diagnostic check for instructions that consume the value twice or consume the value and use the value. The reason why this must be done is that liveness does not distinguish in between different operands on the same instruction meaning such an error would be lost.
This commit is contained in:
@@ -132,8 +132,10 @@
|
||||
#include "swift/SIL/OwnershipUtils.h"
|
||||
#include "swift/SIL/SILBasicBlock.h"
|
||||
#include "swift/SIL/SILFunction.h"
|
||||
#include "swift/SIL/SILInstruction.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace swift {
|
||||
@@ -542,6 +544,47 @@ public:
|
||||
return useIter->second ? LifetimeEndingUse : NonLifetimeEndingUse;
|
||||
}
|
||||
|
||||
using ConstUserRange =
|
||||
iterator_range<const std::pair<SILInstruction *, bool> *>;
|
||||
ConstUserRange getAllUsers() const {
|
||||
return llvm::make_range(users.begin(), users.end());
|
||||
}
|
||||
|
||||
/// A namespace containing helper functors for use with various mapped
|
||||
/// ranges. Intended to be used to hide these noise types when working in an
|
||||
/// IDE.
|
||||
struct LifetimeEndingUserIteratorHelpers {
|
||||
struct MapFunctor {
|
||||
SILInstruction *
|
||||
operator()(const std::pair<SILInstruction *, bool> &pair) const {
|
||||
// Strip off the const to ease use with other APIs.
|
||||
return const_cast<SILInstruction *>(pair.first);
|
||||
}
|
||||
};
|
||||
|
||||
struct FilterFunctor {
|
||||
bool operator()(const std::pair<SILInstruction *, bool> &pair) const {
|
||||
return pair.second;
|
||||
}
|
||||
};
|
||||
|
||||
using MapFilterIter = llvm::mapped_iterator<
|
||||
llvm::filter_iterator<const std::pair<SILInstruction *, bool> *,
|
||||
FilterFunctor>,
|
||||
MapFunctor>;
|
||||
};
|
||||
using LifetimeEndingUserRange =
|
||||
llvm::iterator_range<LifetimeEndingUserIteratorHelpers::MapFilterIter>;
|
||||
|
||||
/// Return a range consisting of the current set of consuming users fed into
|
||||
/// this PrunedLiveness instance.
|
||||
LifetimeEndingUserRange getLifetimeEndingUsers() const {
|
||||
return map_range(
|
||||
llvm::make_filter_range(
|
||||
getAllUsers(), LifetimeEndingUserIteratorHelpers::FilterFunctor()),
|
||||
LifetimeEndingUserIteratorHelpers::MapFunctor());
|
||||
}
|
||||
|
||||
void print(llvm::raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user