1 #ifndef LLVM_CODEGEN_ASSIGNMENTTRACKINGANALYSIS_H
2 #define LLVM_CODEGEN_ASSIGNMENTTRACKINGANALYSIS_H
3 
4 #include "llvm/IR/DebugInfoMetadata.h"
5 #include "llvm/IR/DebugLoc.h"
6 #include "llvm/IR/IntrinsicInst.h"
7 #include "llvm/Pass.h"
8 
9 namespace llvm {
10 class Function;
11 class Instruction;
12 class raw_ostream;
13 } // namespace llvm
14 class FunctionVarLocsBuilder;
15 
16 namespace llvm {
17 /// Type wrapper for integer ID for Variables. 0 is reserved.
18 enum class VariableID : unsigned { Reserved = 0 };
19 /// Variable location definition used by FunctionVarLocs.
20 struct VarLocInfo {
21   llvm::VariableID VariableID;
22   DIExpression *Expr = nullptr;
23   DebugLoc DL;
24   RawLocationWrapper Values = RawLocationWrapper();
25 };
26 
27 /// Data structure describing the variable locations in a function. Used as the
28 /// result of the AssignmentTrackingAnalysis pass. Essentially read-only
29 /// outside of AssignmentTrackingAnalysis where it is built.
30 class FunctionVarLocs {
31   /// Maps VarLocInfo.VariableID to a DebugVariable for VarLocRecords.
32   SmallVector<DebugVariable> Variables;
33   /// List of variable location changes grouped by the instruction the
34   /// change occurs before (see VarLocsBeforeInst). The elements from
35   /// zero to SingleVarLocEnd represent variables with a single location.
36   SmallVector<VarLocInfo> VarLocRecords;
37   /// End of range of VarLocRecords that represent variables with a single
38   /// location that is valid for the entire scope. Range starts at 0.
39   unsigned SingleVarLocEnd = 0;
40   /// Maps an instruction to a range of VarLocs that start just before it.
41   DenseMap<const Instruction *, std::pair<unsigned, unsigned>>
42       VarLocsBeforeInst;
43 
44 public:
45   /// Return the DILocalVariable for the location definition represented by \p
46   /// ID.
47   DILocalVariable *getDILocalVariable(const VarLocInfo *Loc) const {
48     VariableID VarID = Loc->VariableID;
49     return getDILocalVariable(VarID);
50   }
51   /// Return the DILocalVariable of the variable represented by \p ID.
52   DILocalVariable *getDILocalVariable(VariableID ID) const {
53     return const_cast<DILocalVariable *>(getVariable(ID).getVariable());
54   }
55   /// Return the DebugVariable represented by \p ID.
56   const DebugVariable &getVariable(VariableID ID) const {
57     return Variables[static_cast<unsigned>(ID)];
58   }
59 
60   ///@name iterators
61   ///@{
62   /// First single-location variable location definition.
63   const VarLocInfo *single_locs_begin() const { return VarLocRecords.begin(); }
64   /// One past the last single-location variable location definition.
65   const VarLocInfo *single_locs_end() const {
66     const auto *It = VarLocRecords.begin();
67     std::advance(It, SingleVarLocEnd);
68     return It;
69   }
70   /// First variable location definition that comes before \p Before.
71   const VarLocInfo *locs_begin(const Instruction *Before) const {
72     auto Span = VarLocsBeforeInst.lookup(Before);
73     const auto *It = VarLocRecords.begin();
74     std::advance(It, Span.first);
75     return It;
76   }
77   /// One past the last variable location definition that comes before \p
78   /// Before.
79   const VarLocInfo *locs_end(const Instruction *Before) const {
80     auto Span = VarLocsBeforeInst.lookup(Before);
81     const auto *It = VarLocRecords.begin();
82     std::advance(It, Span.second);
83     return It;
84   }
85   ///@}
86 
87   void print(raw_ostream &OS, const Function &Fn) const;
88 
89   ///@{
90   /// Non-const methods used by AssignmentTrackingAnalysis (which invalidate
91   /// analysis results if called incorrectly).
92   void init(FunctionVarLocsBuilder &Builder);
93   void clear();
94   ///@}
95 };
96 
97 class AssignmentTrackingAnalysis : public FunctionPass {
98   std::unique_ptr<FunctionVarLocs> Results;
99 
100 public:
101   static char ID;
102 
103   AssignmentTrackingAnalysis();
104 
105   bool runOnFunction(Function &F) override;
106 
107   static bool isRequired() { return true; }
108 
109   void getAnalysisUsage(AnalysisUsage &AU) const override {
110     AU.setPreservesAll();
111   }
112 
113   const FunctionVarLocs *getResults() { return Results.get(); }
114 };
115 
116 } // end namespace llvm
117 #endif // LLVM_CODEGEN_ASSIGNMENTTRACKINGANALYSIS_H
118