@@ -502,6 +502,13 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
502502
503503enum class Direction { Forward, Backward };
504504
505+ // / A `ProgramPoint` identifies a location in the CFG by pointing to a specific
506+ // / `Fact`. identified by a lifetime-related event (`Fact`).
507+ // /
508+ // / A `ProgramPoint` has "after" semantics: it represents the location
509+ // / immediately after its corresponding `Fact`.
510+ using ProgramPoint = const Fact *;
511+
505512// / A generic, policy-based driver for dataflow analyses. It combines
506513// / the dataflow runner and the transferer logic into a single class hierarchy.
507514// /
@@ -524,14 +531,20 @@ template <typename Derived, typename LatticeType, Direction Dir>
524531class DataflowAnalysis {
525532public:
526533 using Lattice = LatticeType;
527- using Base = DataflowAnalysis<Derived, LatticeType , Dir>;
534+ using Base = DataflowAnalysis<Derived, Lattice , Dir>;
528535
529536private:
530537 const CFG &Cfg;
531538 AnalysisDeclContext &AC;
532539
540+ // / The dataflow state before a basic block is processed.
533541 llvm::DenseMap<const CFGBlock *, Lattice> InStates;
542+ // / The dataflow state after a basic block is processed.
534543 llvm::DenseMap<const CFGBlock *, Lattice> OutStates;
544+ // / The dataflow state at a Program Point.
545+ // / In a forward analysis, this is the state after the Fact at that point has
546+ // / been applied, while in a backward analysis, it is the state before.
547+ llvm::DenseMap<ProgramPoint, Lattice> PerPointStates;
535548
536549 static constexpr bool isForward () { return Dir == Direction::Forward; }
537550
@@ -577,6 +590,8 @@ class DataflowAnalysis {
577590 }
578591 }
579592
593+ Lattice getState (ProgramPoint P) const { return PerPointStates.lookup (P); }
594+
580595 Lattice getInState (const CFGBlock *B) const { return InStates.lookup (B); }
581596
582597 Lattice getOutState (const CFGBlock *B) const { return OutStates.lookup (B); }
@@ -590,18 +605,23 @@ class DataflowAnalysis {
590605 getOutState (&B).dump (llvm::dbgs ());
591606 }
592607
608+ private:
593609 // / Computes the state at one end of a block by applying all its facts
594610 // / sequentially to a given state from the other end.
595- // / TODO: We might need to store intermediate states per-fact in the block for
596- // / later analysis.
597611 Lattice transferBlock (const CFGBlock *Block, Lattice State) {
598612 auto Facts = AllFacts.getFacts (Block);
599- if constexpr (isForward ())
600- for (const Fact *F : Facts)
613+ if constexpr (isForward ()) {
614+ for (const Fact *F : Facts) {
601615 State = transferFact (State, F);
602- else
603- for (const Fact *F : llvm::reverse (Facts))
616+ PerPointStates[F] = State;
617+ }
618+ } else {
619+ for (const Fact *F : llvm::reverse (Facts)) {
620+ // In backward analysis, capture the state before applying the fact.
621+ PerPointStates[F] = State;
604622 State = transferFact (State, F);
623+ }
624+ }
605625 return State;
606626 }
607627
@@ -769,6 +789,10 @@ class LoanPropagationAnalysis
769789 Factory.OriginMapFactory .add (In.Origins , DestOID, SrcLoans));
770790 }
771791
792+ LoanSet getLoans (OriginID OID, ProgramPoint P) {
793+ return getLoans (getState (P), OID);
794+ }
795+
772796private:
773797 LoanSet getLoans (Lattice L, OriginID OID) {
774798 if (auto *Loans = L.Origins .lookup (OID))
@@ -779,7 +803,6 @@ class LoanPropagationAnalysis
779803
780804// ========================================================================= //
781805// TODO:
782- // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
783806// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
784807// - Modify origin liveness analysis to answer `bool isLive(Origin O, Point P)`
785808// - Using the above three to perform the final error reporting.
0 commit comments