1 //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__ 11 #define CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__ 12 #include "llvm/IR/Constants.h" 13 #include "llvm/IR/DebugInfo.h" 14 #include "llvm/MC/MachineLocation.h" 15 #include "llvm/MC/MCSymbol.h" 16 17 namespace llvm { 18 class MDNode; 19 /// \brief This struct describes location entries emitted in the .debug_loc 20 /// section. 21 class DebugLocEntry { 22 // Begin and end symbols for the address range that this location is valid. 23 const MCSymbol *Begin; 24 const MCSymbol *End; 25 26 public: 27 /// A single location or constant. 28 struct Value { 29 Value(const MDNode *Var, int64_t i) 30 : Variable(Var), EntryKind(E_Integer) { 31 Constant.Int = i; 32 } 33 Value(const MDNode *Var, const ConstantFP *CFP) 34 : Variable(Var), EntryKind(E_ConstantFP) { 35 Constant.CFP = CFP; 36 } 37 Value(const MDNode *Var, const ConstantInt *CIP) 38 : Variable(Var), EntryKind(E_ConstantInt) { 39 Constant.CIP = CIP; 40 } 41 Value(const MDNode *Var, MachineLocation Loc) 42 : Variable(Var), EntryKind(E_Location), Loc(Loc) { 43 } 44 45 // The variable to which this location entry corresponds. 46 const MDNode *Variable; 47 48 // Type of entry that this represents. 49 enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; 50 enum EntryType EntryKind; 51 52 // Either a constant, 53 union { 54 int64_t Int; 55 const ConstantFP *CFP; 56 const ConstantInt *CIP; 57 } Constant; 58 59 // Or a location in the machine frame. 60 MachineLocation Loc; 61 62 bool isLocation() const { return EntryKind == E_Location; } 63 bool isInt() const { return EntryKind == E_Integer; } 64 bool isConstantFP() const { return EntryKind == E_ConstantFP; } 65 bool isConstantInt() const { return EntryKind == E_ConstantInt; } 66 int64_t getInt() const { return Constant.Int; } 67 const ConstantFP *getConstantFP() const { return Constant.CFP; } 68 const ConstantInt *getConstantInt() const { return Constant.CIP; } 69 MachineLocation getLoc() const { return Loc; } 70 const MDNode *getVariableNode() const { return Variable; } 71 DIVariable getVariable() const { return DIVariable(Variable); } 72 bool isVariablePiece() const { return getVariable().isVariablePiece(); } 73 friend bool operator==(const Value &, const Value &); 74 friend bool operator<(const Value &, const Value &); 75 }; 76 77 private: 78 /// A nonempty list of locations/constants belonging to this entry, 79 /// sorted by offset. 80 SmallVector<Value, 1> Values; 81 82 public: 83 DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val) 84 : Begin(B), End(E) { 85 Values.push_back(std::move(Val)); 86 } 87 88 /// \brief If this and Next are describing different pieces of the same 89 // variable, merge them by appending Next's values to the current 90 // list of values. 91 // Return true if the merge was successful. 92 bool MergeValues(const DebugLocEntry &Next) { 93 if (Begin == Next.Begin && Values.size() > 0 && Next.Values.size() > 0) { 94 DIVariable Var(Values[0].Variable); 95 DIVariable NextVar(Next.Values[0].Variable); 96 if (Var.getName() == NextVar.getName() && 97 Var.isVariablePiece() && NextVar.isVariablePiece()) { 98 addValues(Next.Values); 99 End = Next.End; 100 return true; 101 } 102 } 103 return false; 104 } 105 106 /// \brief Attempt to merge this DebugLocEntry with Next and return 107 /// true if the merge was successful. Entries can be merged if they 108 /// share the same Loc/Constant and if Next immediately follows this 109 /// Entry. 110 bool MergeRanges(const DebugLocEntry &Next) { 111 // If this and Next are describing the same variable, merge them. 112 if ((End == Next.Begin && Values == Next.Values)) { 113 End = Next.End; 114 return true; 115 } 116 return false; 117 } 118 119 const MCSymbol *getBeginSym() const { return Begin; } 120 const MCSymbol *getEndSym() const { return End; } 121 const ArrayRef<Value> getValues() const { return Values; } 122 void addValues(ArrayRef<DebugLocEntry::Value> Vals) { 123 Values.append(Vals.begin(), Vals.end()); 124 sortUniqueValues(); 125 assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){ 126 return V.isVariablePiece(); 127 }) && "value must be a piece"); 128 } 129 130 // Sort the pieces by offset. 131 // Remove any duplicate entries by dropping all but the first. 132 void sortUniqueValues() { 133 std::sort(Values.begin(), Values.end()); 134 Values.erase(std::unique(Values.begin(), Values.end(), 135 [](const Value &A, const Value &B) { 136 return A.getVariable() == B.getVariable(); 137 }), Values.end()); 138 } 139 }; 140 141 /// Compare two Values for equality. 142 inline bool operator==(const DebugLocEntry::Value &A, 143 const DebugLocEntry::Value &B) { 144 if (A.EntryKind != B.EntryKind) 145 return false; 146 147 if (A.getVariable() != B.getVariable()) 148 return false; 149 150 switch (A.EntryKind) { 151 case DebugLocEntry::Value::E_Location: 152 return A.Loc == B.Loc; 153 case DebugLocEntry::Value::E_Integer: 154 return A.Constant.Int == B.Constant.Int; 155 case DebugLocEntry::Value::E_ConstantFP: 156 return A.Constant.CFP == B.Constant.CFP; 157 case DebugLocEntry::Value::E_ConstantInt: 158 return A.Constant.CIP == B.Constant.CIP; 159 } 160 llvm_unreachable("unhandled EntryKind"); 161 } 162 163 /// Compare two pieces based on their offset. 164 inline bool operator<(const DebugLocEntry::Value &A, 165 const DebugLocEntry::Value &B) { 166 return A.getVariable().getPieceOffset() < B.getVariable().getPieceOffset(); 167 } 168 169 } 170 171 #endif 172