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. getDILocalVariable(const VarLocInfo * Loc)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. getDILocalVariable(VariableID ID)52 DILocalVariable *getDILocalVariable(VariableID ID) const { 53 return const_cast<DILocalVariable *>(getVariable(ID).getVariable()); 54 } 55 /// Return the DebugVariable represented by \p ID. getVariable(VariableID 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. single_locs_begin()63 const VarLocInfo *single_locs_begin() const { return VarLocRecords.begin(); } 64 /// One past the last single-location variable location definition. single_locs_end()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. locs_begin(const Instruction * 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. locs_end(const Instruction * 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 isRequired()107 static bool isRequired() { return true; } 108 getAnalysisUsage(AnalysisUsage & AU)109 void getAnalysisUsage(AnalysisUsage &AU) const override { 110 AU.setPreservesAll(); 111 } 112 getResults()113 const FunctionVarLocs *getResults() { return Results.get(); } 114 }; 115 116 } // end namespace llvm 117 #endif // LLVM_CODEGEN_ASSIGNMENTTRACKINGANALYSIS_H 118