@@ -727,12 +727,14 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
727727// ========================================================================= //
728728
729729using 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.
733734struct 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
9421020LoanSet LifetimeSafetyAnalysis::getLoansAtPoint (OriginID OID,
0 commit comments