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 |