|
23 | 23 | #include "llvm/Support/Debug.h"
|
24 | 24 | #include "llvm/Support/TimeProfiler.h"
|
25 | 25 | #include <cstdint>
|
| 26 | +#include <memory> |
26 | 27 |
|
27 | 28 | namespace clang::lifetimes {
|
28 | 29 | namespace internal {
|
@@ -832,6 +833,65 @@ class LoanPropagationAnalysis
|
832 | 833 | }
|
833 | 834 | };
|
834 | 835 |
|
| 836 | +// ========================================================================= // |
| 837 | +// Expired Loans Analysis |
| 838 | +// ========================================================================= // |
| 839 | + |
| 840 | +/// The dataflow lattice for tracking the set of expired loans. |
| 841 | +struct ExpiredLattice { |
| 842 | + LoanSet Expired; |
| 843 | + |
| 844 | + ExpiredLattice() : Expired(nullptr) {}; |
| 845 | + explicit ExpiredLattice(LoanSet S) : Expired(S) {} |
| 846 | + |
| 847 | + bool operator==(const ExpiredLattice &Other) const { |
| 848 | + return Expired == Other.Expired; |
| 849 | + } |
| 850 | + bool operator!=(const ExpiredLattice &Other) const { |
| 851 | + return !(*this == Other); |
| 852 | + } |
| 853 | + |
| 854 | + void dump(llvm::raw_ostream &OS) const { |
| 855 | + OS << "ExpiredLattice State:\n"; |
| 856 | + if (Expired.isEmpty()) |
| 857 | + OS << " <empty>\n"; |
| 858 | + for (const LoanID &LID : Expired) |
| 859 | + OS << " Loan " << LID << " is expired\n"; |
| 860 | + } |
| 861 | +}; |
| 862 | + |
| 863 | +/// The analysis that tracks which loans have expired. |
| 864 | +class ExpiredLoansAnalysis |
| 865 | + : public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice, |
| 866 | + Direction::Forward> { |
| 867 | + |
| 868 | + LoanSet::Factory &Factory; |
| 869 | + |
| 870 | +public: |
| 871 | + ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, |
| 872 | + LifetimeFactory &Factory) |
| 873 | + : DataflowAnalysis(C, AC, F), Factory(Factory.LoanSetFactory) {} |
| 874 | + |
| 875 | + using Base::transfer; |
| 876 | + |
| 877 | + StringRef getAnalysisName() const { return "ExpiredLoans"; } |
| 878 | + |
| 879 | + Lattice getInitialState() { return Lattice(Factory.getEmptySet()); } |
| 880 | + |
| 881 | + /// Merges two lattices by taking the union of the expired loan sets. |
| 882 | + Lattice join(Lattice L1, Lattice L2) const { |
| 883 | + return Lattice(utils::join(L1.Expired, L2.Expired, Factory)); |
| 884 | + } |
| 885 | + |
| 886 | + Lattice transfer(Lattice In, const ExpireFact &F) { |
| 887 | + return Lattice(Factory.add(In.Expired, F.getLoanID())); |
| 888 | + } |
| 889 | + |
| 890 | + Lattice transfer(Lattice In, const IssueFact &F) { |
| 891 | + return Lattice(Factory.remove(In.Expired, F.getLoanID())); |
| 892 | + } |
| 893 | +}; |
| 894 | + |
835 | 895 | // ========================================================================= //
|
836 | 896 | // TODO:
|
837 | 897 | // - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
|
@@ -872,6 +932,10 @@ void LifetimeSafetyAnalysis::run() {
|
872 | 932 | LoanPropagation =
|
873 | 933 | std::make_unique<LoanPropagationAnalysis>(Cfg, AC, *FactMgr, *Factory);
|
874 | 934 | LoanPropagation->run();
|
| 935 | + |
| 936 | + ExpiredLoans = |
| 937 | + std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory); |
| 938 | + ExpiredLoans->run(); |
875 | 939 | }
|
876 | 940 |
|
877 | 941 | LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
|
|
0 commit comments