@@ -675,12 +675,14 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
675
675
// TODO(opt): Consider using a bitset to represent the set of loans.
676
676
using LoanSet = llvm::ImmutableSet<LoanID>;
677
677
using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>;
678
+ using OriginSet = llvm::ImmutableSet<OriginID>;
678
679
679
680
// / An object to hold the factories for immutable collections, ensuring
680
681
// / that all created states share the same underlying memory management.
681
682
struct LifetimeFactory {
682
683
OriginLoanMap::Factory OriginMapFactory;
683
684
LoanSet::Factory LoanSetFactory;
685
+ OriginSet::Factory OriginSetFactory;
684
686
685
687
// / Creates a singleton set containing only the given loan ID.
686
688
LoanSet createLoanSet (LoanID LID) {
@@ -778,6 +780,78 @@ class LoanPropagationAnalysis
778
780
}
779
781
};
780
782
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
+
781
855
// ========================================================================= //
782
856
// Expired Loans Analysis
783
857
// ========================================================================= //
@@ -872,5 +946,10 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
872
946
873
947
ExpiredLoansAnalysis ExpiredLoans (Cfg, AC, FactMgr, Factory);
874
948
ExpiredLoans.run ();
949
+ 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 ());
875
954
}
876
955
} // namespace clang
0 commit comments