Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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/Pass.h" |
||
| 7 | |||
| 8 | namespace llvm { |
||
| 9 | class Function; |
||
| 10 | class Instruction; |
||
| 11 | class Value; |
||
| 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 | Value *V = nullptr; // TODO: Needs to be value_s_ for variadic expressions. |
||
| 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 |