Skip to content

Commit e940cf0

Browse files
committed
add-liveness-finally
1 parent c29040a commit e940cf0

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

clang/include/clang/Analysis/Analyses/LifetimeSafety.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class Fact;
3434
class FactManager;
3535
class LoanPropagationAnalysis;
3636
class ExpiredLoansAnalysis;
37+
class LiveOriginAnalysis;
3738
struct LifetimeFactory;
3839

3940
/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
@@ -114,6 +115,7 @@ class LifetimeSafetyAnalysis {
114115
std::unique_ptr<FactManager> FactMgr;
115116
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
116117
std::unique_ptr<ExpiredLoansAnalysis> ExpiredLoans;
118+
std::unique_ptr<LiveOriginAnalysis> LiveOrigins;
117119
};
118120
} // namespace internal
119121
} // namespace clang::lifetimes

clang/lib/Analysis/LifetimeSafety.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,12 +727,14 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
727727
// ========================================================================= //
728728

729729
using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>;
730+
using OriginSet = llvm::ImmutableSet<OriginID>;
730731

731732
/// An object to hold the factories for immutable collections, ensuring
732733
/// that all created states share the same underlying memory management.
733734
struct LifetimeFactory {
734735
OriginLoanMap::Factory OriginMapFactory;
735736
LoanSet::Factory LoanSetFactory;
737+
OriginSet::Factory OriginSetFactory;
736738

737739
/// Creates a singleton set containing only the given loan ID.
738740
LoanSet createLoanSet(LoanID LID) {
@@ -833,6 +835,78 @@ class LoanPropagationAnalysis
833835
}
834836
};
835837

838+
// ========================================================================= //
839+
// Live Origins Analysis
840+
// ========================================================================= //
841+
842+
/// The dataflow lattice for origin liveness analysis.
843+
/// It tracks the set of origins that are live at a given program point.
844+
struct LivenessLattice {
845+
OriginSet LiveOrigins;
846+
847+
LivenessLattice() : LiveOrigins(nullptr) {};
848+
explicit LivenessLattice(OriginSet S) : LiveOrigins(S) {}
849+
850+
bool operator==(const LivenessLattice &Other) const {
851+
return LiveOrigins == Other.LiveOrigins;
852+
}
853+
bool operator!=(const LivenessLattice &Other) const {
854+
return !(*this == Other);
855+
}
856+
857+
void dump(llvm::raw_ostream &OS) const {
858+
OS << "LivenessLattice State:\n";
859+
if (LiveOrigins.isEmpty())
860+
OS << " <empty>\n";
861+
for (const OriginID &OID : LiveOrigins)
862+
OS << " Origin " << OID << " is live\n";
863+
}
864+
};
865+
866+
/// The analysis that tracks which origins are live. This is a backward
867+
/// analysis.
868+
class LiveOriginAnalysis
869+
: public DataflowAnalysis<LiveOriginAnalysis, LivenessLattice,
870+
Direction::Backward> {
871+
872+
OriginSet::Factory &SetFactory;
873+
874+
public:
875+
LiveOriginAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
876+
OriginSet::Factory &SF)
877+
: DataflowAnalysis(C, AC, F), SetFactory(SF) {}
878+
879+
using DataflowAnalysis<LiveOriginAnalysis, Lattice,
880+
Direction::Backward>::transfer;
881+
882+
StringRef getAnalysisName() const { return "LiveOrigins"; }
883+
884+
Lattice getInitialState() { return Lattice(SetFactory.getEmptySet()); }
885+
886+
/// Merges two lattices by taking the union of the live origin sets.
887+
Lattice join(Lattice L1, Lattice L2) const {
888+
return Lattice(utils::join(L1.LiveOrigins, L2.LiveOrigins, SetFactory));
889+
}
890+
891+
/// An assignment `p = q` kills the liveness of `p` and generates liveness
892+
/// for `q`.
893+
Lattice transfer(Lattice In, const AssignOriginFact &F) {
894+
OriginSet S = SetFactory.remove(In.LiveOrigins, F.getDestOriginID());
895+
S = SetFactory.add(S, F.getSrcOriginID());
896+
return Lattice(S);
897+
}
898+
899+
/// Issuing a new loan to an origin kills its liveness.
900+
Lattice transfer(Lattice In, const IssueFact &F) {
901+
return Lattice(SetFactory.remove(In.LiveOrigins, F.getOriginID()));
902+
}
903+
904+
/// A return statement generates liveness for the returned origin.
905+
Lattice transfer(Lattice In, const ReturnOfOriginFact &F) {
906+
return Lattice(SetFactory.add(In.LiveOrigins, F.getReturnedOriginID()));
907+
}
908+
};
909+
836910
// ========================================================================= //
837911
// Expired Loans Analysis
838912
// ========================================================================= //
@@ -937,6 +1011,10 @@ void LifetimeSafetyAnalysis::run() {
9371011
ExpiredLoans =
9381012
std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory);
9391013
ExpiredLoans->run();
1014+
1015+
LiveOrigins = std::make_unique<LiveOriginAnalysis>(Cfg, AC, *FactMgr,
1016+
Factory->OriginSetFactory);
1017+
LiveOrigins->run();
9401018
}
9411019

9421020
LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,

0 commit comments

Comments
 (0)