@@ -502,6 +502,13 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> {
502
502
503
503
enum class Direction { Forward, Backward };
504
504
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
+
505
512
// / A generic, policy-based driver for dataflow analyses. It combines
506
513
// / the dataflow runner and the transferer logic into a single class hierarchy.
507
514
// /
@@ -524,14 +531,20 @@ template <typename Derived, typename LatticeType, Direction Dir>
524
531
class DataflowAnalysis {
525
532
public:
526
533
using Lattice = LatticeType;
527
- using Base = DataflowAnalysis<Derived, LatticeType , Dir>;
534
+ using Base = DataflowAnalysis<Derived, Lattice , Dir>;
528
535
529
536
private:
530
537
const CFG &Cfg;
531
538
AnalysisDeclContext &AC;
532
539
540
+ // / The dataflow state before a basic block is processed.
533
541
llvm::DenseMap<const CFGBlock *, Lattice> InStates;
542
+ // / The dataflow state after a basic block is processed.
534
543
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;
535
548
536
549
static constexpr bool isForward () { return Dir == Direction::Forward; }
537
550
@@ -577,6 +590,8 @@ class DataflowAnalysis {
577
590
}
578
591
}
579
592
593
+ Lattice getState (ProgramPoint P) const { return PerPointStates.lookup (P); }
594
+
580
595
Lattice getInState (const CFGBlock *B) const { return InStates.lookup (B); }
581
596
582
597
Lattice getOutState (const CFGBlock *B) const { return OutStates.lookup (B); }
@@ -590,18 +605,23 @@ class DataflowAnalysis {
590
605
getOutState (&B).dump (llvm::dbgs ());
591
606
}
592
607
608
+ private:
593
609
// / Computes the state at one end of a block by applying all its facts
594
610
// / 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.
597
611
Lattice transferBlock (const CFGBlock *Block, Lattice State) {
598
612
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) {
601
615
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;
604
622
State = transferFact (State, F);
623
+ }
624
+ }
605
625
return State;
606
626
}
607
627
@@ -769,6 +789,10 @@ class LoanPropagationAnalysis
769
789
Factory.OriginMapFactory .add (In.Origins , DestOID, SrcLoans));
770
790
}
771
791
792
+ LoanSet getLoans (OriginID OID, ProgramPoint P) {
793
+ return getLoans (getState (P), OID);
794
+ }
795
+
772
796
private:
773
797
LoanSet getLoans (Lattice L, OriginID OID) {
774
798
if (auto *Loans = L.Origins .lookup (OID))
@@ -779,7 +803,6 @@ class LoanPropagationAnalysis
779
803
780
804
// ========================================================================= //
781
805
// TODO:
782
- // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
783
806
// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
784
807
// - Modify origin liveness analysis to answer `bool isLive(Origin O, Point P)`
785
808
// - Using the above three to perform the final error reporting.
0 commit comments