-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[LifetimeSafety] Add loan expiry analysis #148712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[LifetimeSafety] Add loan expiry analysis #148712
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
880cf3b
to
ed73e3b
Compare
c217d0d
to
702d255
Compare
ed73e3b
to
a50b00e
Compare
7e098b0
to
793d58e
Compare
a50b00e
to
a9f1e8d
Compare
793d58e
to
2bff132
Compare
6ce3173
to
9265536
Compare
2253ff0
to
c073ef3
Compare
9265536
to
9da8f3a
Compare
c073ef3
to
51afc3e
Compare
9da8f3a
to
04d6193
Compare
51afc3e
to
7b26a72
Compare
04d6193
to
2073937
Compare
5f09913
to
aca68c2
Compare
b109b6a
to
7502ee5
Compare
@llvm/pr-subscribers-clang-analysis @llvm/pr-subscribers-clang Author: Utkarsh Saxena (usx95) ChangesThis PR adds the This is a very light weight dataflow analysis and is expected to reach fixed point in ~2 iterations. Full diff: https://github.com/llvm/llvm-project/pull/148712.diff 1 Files Affected:
diff --git a/clang/lib/Analysis/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety.cpp
index 829da3ceb4c83..217b02b416c1a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -777,6 +777,65 @@ class LoanPropagationAnalysis
}
};
+// ========================================================================= //
+// Expired Loans Analysis
+// ========================================================================= //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+ LoanSet Expired;
+
+ ExpiredLattice() : Expired(nullptr) {};
+ explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+ bool operator==(const ExpiredLattice &Other) const {
+ return Expired == Other.Expired;
+ }
+ bool operator!=(const ExpiredLattice &Other) const {
+ return !(*this == Other);
+ }
+
+ void dump(llvm::raw_ostream &OS) const {
+ OS << "ExpiredLattice State:\n";
+ if (Expired.isEmpty())
+ OS << " <empty>\n";
+ for (const LoanID &LID : Expired)
+ OS << " Loan " << LID << " is expired\n";
+ }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+ : public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice,
+ Direction::Forward> {
+
+ LoanSet::Factory &Factory;
+
+public:
+ ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+ LifetimeFactory &SF)
+ : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+ using Base::transfer;
+
+ StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+ Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+ /// Merges two lattices by taking the union of the expired loan sets.
+ Lattice join(Lattice L1, Lattice L2) const {
+ return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+ }
+
+ Lattice transfer(Lattice In, const ExpireFact &F) {
+ return Lattice(Factory.add(In.Expired, F.getLoanID()));
+ }
+
+ Lattice transfer(Lattice In, const IssueFact &F) {
+ return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+ }
+};
+
// ========================================================================= //
// TODO:
// - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -809,5 +868,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
LoanPropagation.run();
DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+ ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+ ExpiredLoans.run();
}
} // namespace clang
|
aca68c2
to
8bbae58
Compare
7502ee5
to
9475733
Compare
8bbae58
to
037a7ec
Compare
Looks good, but what's the plan for tests? |
Good question :) I think adding tests for each analyses to the current llvm-lit tests is quite a pain for the eyes at this point. Also I want to test things at specific program points (is loan expired here, does origin contain loan here, etc). I am exploring a couple of options, primarily https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Testing/TestAST.h, https://github.com/llvm/llvm-project/blob/main/clang/unittests/Analysis/FlowSensitive/TestingSupport.h and something like https://github.com/llvm/llvm-project/blob/main/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp#L874-L900 This will likely take some more time. Happy to hold this off until I add something like this for unit tests! I would still rely on llvm-lit tests for final diagnostic reporting (or maybe that also can be done through unit testing) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once the testing story is figured out this looks good to me.
}; | ||
|
||
/// The analysis that tracks which loans have expired. | ||
class ExpiredLoansAnalysis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we have the expectation that we have a tight bound on this analysis. I wonder if there is a way to somehow add an assert to verify that the reality matches our expectations. Not super important but if it is not too complicated it could be nice.
We can also defer this to a later PR since we want to be able to add strict bounds to the number of iterations in the future and that might be required for us to easily assert on this.
Alright. I will add some unit test infra separately before this PR then! |
037a7ec
to
a4cba20
Compare
9475733
to
7762a38
Compare
Refactored the lifetime safety analysis to use a generic dataflow framework with a policy-based design. ### Changes - Introduced a generic `DataflowAnalysis` template class that can be specialized for different analyses - Renamed `LifetimeLattice` to `LoanPropagationLattice` to better reflect its purpose - Created a `LoanPropagationAnalysis` class that inherits from the generic framework - Moved transfer functions from the standalone `Transferer` class into the analysis class - Restructured the code to separate the dataflow engine from the specific analysis logic - Updated debug output and test expectations to use the new class names ### Motivation In order to add more analyses, e.g. [loan expiry](#148712) and origin liveness, the previous implementation would have separate, nearly identical dataflow runners for each analysis. This change creates a single, reusable component, which will make it much simpler to add subsequent analyses without repeating boilerplate code. This is quite close to the existing dataflow framework!
4a23369
to
b76c916
Compare
a4cba20
to
7365fc4
Compare
Refactored the lifetime safety analysis to use a generic dataflow framework with a policy-based design. ### Changes - Introduced a generic `DataflowAnalysis` template class that can be specialized for different analyses - Renamed `LifetimeLattice` to `LoanPropagationLattice` to better reflect its purpose - Created a `LoanPropagationAnalysis` class that inherits from the generic framework - Moved transfer functions from the standalone `Transferer` class into the analysis class - Restructured the code to separate the dataflow engine from the specific analysis logic - Updated debug output and test expectations to use the new class names ### Motivation In order to add more analyses, e.g. [loan expiry](llvm/llvm-project#148712) and origin liveness, the previous implementation would have separate, nearly identical dataflow runners for each analysis. This change creates a single, reusable component, which will make it much simpler to add subsequent analyses without repeating boilerplate code. This is quite close to the existing dataflow framework!
7365fc4
to
a7d03b1
Compare
This PR adds the
ExpiredLoansAnalysis
class to track which loans have expired. The analysis uses a dataflow lattice (ExpiredLattice
) to maintain the set of expired loans at each program point.This is a very light weight dataflow analysis and is expected to reach fixed point in ~2 iterations.
In principle, this does not need a dataflow analysis but is used for convenience in favour of lean code.