@@ -675,12 +675,14 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
675675// TODO(opt): Consider using a bitset to represent the set of loans.
676676using LoanSet = llvm::ImmutableSet<LoanID>;
677677using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>;
678+ using OriginSet = llvm::ImmutableSet<OriginID>;
678679
679680// / An object to hold the factories for immutable collections, ensuring
680681// / that all created states share the same underlying memory management.
681682struct LifetimeFactory {
682683 OriginLoanMap::Factory OriginMapFactory;
683684 LoanSet::Factory LoanSetFactory;
685+ OriginSet::Factory OriginSetFactory;
684686
685687 // / Creates a singleton set containing only the given loan ID.
686688 LoanSet createLoanSet (LoanID LID) {
@@ -778,6 +780,78 @@ class LoanPropagationAnalysis
778780 }
779781};
780782
783+ // ========================================================================= //
784+ // Live Origins Analysis
785+ // ========================================================================= //
786+
787+ // / The dataflow lattice for origin liveness analysis.
788+ // / It tracks the set of origins that are live at a given program point.
789+ struct LivenessLattice {
790+ OriginSet LiveOrigins;
791+
792+ LivenessLattice () : LiveOrigins(nullptr ) {};
793+ explicit LivenessLattice (OriginSet S) : LiveOrigins(S) {}
794+
795+ bool operator ==(const LivenessLattice &Other) const {
796+ return LiveOrigins == Other.LiveOrigins ;
797+ }
798+ bool operator !=(const LivenessLattice &Other) const {
799+ return !(*this == Other);
800+ }
801+
802+ void dump (llvm::raw_ostream &OS) const {
803+ OS << " LivenessLattice State:\n " ;
804+ if (LiveOrigins.isEmpty ())
805+ OS << " <empty>\n " ;
806+ for (const OriginID &OID : LiveOrigins)
807+ OS << " Origin " << OID << " is live\n " ;
808+ }
809+ };
810+
811+ // / The analysis that tracks which origins are live. This is a backward
812+ // / analysis.
813+ class LiveOriginAnalysis
814+ : public DataflowAnalysis<LiveOriginAnalysis, LivenessLattice,
815+ Direction::Backward> {
816+
817+ OriginSet::Factory &SetFactory;
818+
819+ public:
820+ LiveOriginAnalysis (const CFG &C, AnalysisDeclContext &AC, FactManager &F,
821+ OriginSet::Factory &SF)
822+ : DataflowAnalysis(C, AC, F), SetFactory(SF) {}
823+
824+ using DataflowAnalysis<LiveOriginAnalysis, Lattice,
825+ Direction::Backward>::transfer;
826+
827+ StringRef getAnalysisName () const { return " LiveOrigins" ; }
828+
829+ Lattice getInitialState () { return Lattice (SetFactory.getEmptySet ()); }
830+
831+ // / Merges two lattices by taking the union of the live origin sets.
832+ Lattice join (Lattice L1, Lattice L2) const {
833+ return Lattice (utils::join (L1.LiveOrigins , L2.LiveOrigins , SetFactory));
834+ }
835+
836+ // / An assignment `p = q` kills the liveness of `p` and generates liveness
837+ // / for `q`.
838+ Lattice transfer (Lattice In, const AssignOriginFact &F) {
839+ OriginSet S = SetFactory.remove (In.LiveOrigins , F.getDestOriginID ());
840+ S = SetFactory.add (S, F.getSrcOriginID ());
841+ return Lattice (S);
842+ }
843+
844+ // / Issuing a new loan to an origin kills its liveness.
845+ Lattice transfer (Lattice In, const IssueFact &F) {
846+ return Lattice (SetFactory.remove (In.LiveOrigins , F.getOriginID ()));
847+ }
848+
849+ // / A return statement generates liveness for the returned origin.
850+ Lattice transfer (Lattice In, const ReturnOfOriginFact &F) {
851+ return Lattice (SetFactory.add (In.LiveOrigins , F.getReturnedOriginID ()));
852+ }
853+ };
854+
781855// ========================================================================= //
782856// Expired Loans Analysis
783857// ========================================================================= //
@@ -873,5 +947,9 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
873947 ExpiredLoansAnalysis ExpiredLoans (Cfg, AC, FactMgr, Factory);
874948 ExpiredLoans.run ();
875949 DEBUG_WITH_TYPE (" LifetimeExpiredLoans" , ExpiredLoans.dump ());
950+
951+ LiveOriginAnalysis Liveness (Cfg, AC, FactMgr, Factory.OriginSetFactory );
952+ Liveness.run ();
953+ DEBUG_WITH_TYPE (" LifetimeLiveOrigins" , Liveness.dump ());
876954}
877955} // namespace clang
0 commit comments