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 LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H 11 #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H 12 #include "llvm/ADT/SmallString.h" 13 #include "llvm/IR/Constants.h" 14 #include "llvm/IR/DebugInfo.h" 15 #include "llvm/MC/MCSymbol.h" 16 #include "llvm/MC/MachineLocation.h" 17 18 namespace llvm { 19 class AsmPrinter; 20 class MDNode; 21 /// \brief This struct describes location entries emitted in the .debug_loc 22 /// section. 23 class DebugLocEntry { 24 /// Begin and end symbols for the address range that this location is valid. 25 const MCSymbol *Begin; 26 const MCSymbol *End; 27 28 public: 29 /// \brief A single location or constant. 30 struct Value { 31 Value(const MDNode *Var, const MDNode *Expr, int64_t i) 32 : Variable(Var), Expression(Expr), EntryKind(E_Integer) { 33 Constant.Int = i; 34 } 35 Value(const MDNode *Var, const MDNode *Expr, const ConstantFP *CFP) 36 : Variable(Var), Expression(Expr), EntryKind(E_ConstantFP) { 37 Constant.CFP = CFP; 38 } 39 Value(const MDNode *Var, const MDNode *Expr, const ConstantInt *CIP) 40 : Variable(Var), Expression(Expr), EntryKind(E_ConstantInt) { 41 Constant.CIP = CIP; 42 } 43 Value(const MDNode *Var, const MDNode *Expr, MachineLocation Loc) 44 : Variable(Var), Expression(Expr), EntryKind(E_Location), Loc(Loc) { 45 assert(DIVariable(Var).Verify()); 46 assert(DIExpression(Expr).Verify()); 47 } 48 49 /// The variable to which this location entry corresponds. 50 const MDNode *Variable; 51 52 /// Any complex address location expression for this Value. 53 const MDNode *Expression; 54 55 /// Type of entry that this represents. 56 enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; 57 enum EntryType EntryKind; 58 59 /// Either a constant, 60 union { 61 int64_t Int; 62 const ConstantFP *CFP; 63 const ConstantInt *CIP; 64 } Constant; 65 66 // Or a location in the machine frame. 67 MachineLocation Loc; 68 69 bool isLocation() const { return EntryKind == E_Location; } 70 bool isInt() const { return EntryKind == E_Integer; } 71 bool isConstantFP() const { return EntryKind == E_ConstantFP; } 72 bool isConstantInt() const { return EntryKind == E_ConstantInt; } 73 int64_t getInt() const { return Constant.Int; } 74 const ConstantFP *getConstantFP() const { return Constant.CFP; } 75 const ConstantInt *getConstantInt() const { return Constant.CIP; } 76 MachineLocation getLoc() const { return Loc; } 77 const MDNode *getVariableNode() const { return Variable; } 78 DIVariable getVariable() const { return DIVariable(Variable); } 79 bool isBitPiece() const { return getExpression().isBitPiece(); } 80 DIExpression getExpression() const { return DIExpression(Expression); } 81 friend bool operator==(const Value &, const Value &); 82 friend bool operator<(const Value &, const Value &); 83 }; 84 85 private: 86 /// A nonempty list of locations/constants belonging to this entry, 87 /// sorted by offset. 88 SmallVector<Value, 1> Values; 89 SmallString<8> DWARFBytes; 90 SmallVector<std::string, 1> Comments; 91 92 public: 93 DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val) 94 : Begin(B), End(E) { 95 Values.push_back(std::move(Val)); 96 } 97 98 /// \brief If this and Next are describing different pieces of the same 99 /// variable, merge them by appending Next's values to the current 100 /// list of values. 101 /// Return true if the merge was successful. 102 bool MergeValues(const DebugLocEntry &Next) { 103 if (Begin == Next.Begin) { 104 DIExpression Expr(Values[0].Expression); 105 DIVariable Var(Values[0].Variable); 106 DIExpression NextExpr(Next.Values[0].Expression); 107 DIVariable NextVar(Next.Values[0].Variable); 108 if (Var == NextVar && Expr.isBitPiece() && 109 NextExpr.isBitPiece()) { 110 addValues(Next.Values); 111 End = Next.End; 112 return true; 113 } 114 } 115 return false; 116 } 117 118 /// \brief Attempt to merge this DebugLocEntry with Next and return 119 /// true if the merge was successful. Entries can be merged if they 120 /// share the same Loc/Constant and if Next immediately follows this 121 /// Entry. 122 bool MergeRanges(const DebugLocEntry &Next) { 123 // If this and Next are describing the same variable, merge them. 124 if ((End == Next.Begin && Values == Next.Values)) { 125 End = Next.End; 126 return true; 127 } 128 return false; 129 } 130 131 const MCSymbol *getBeginSym() const { return Begin; } 132 const MCSymbol *getEndSym() const { return End; } 133 ArrayRef<Value> getValues() const { return Values; } 134 void addValues(ArrayRef<DebugLocEntry::Value> Vals) { 135 Values.append(Vals.begin(), Vals.end()); 136 sortUniqueValues(); 137 assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){ 138 return V.isBitPiece(); 139 }) && "value must be a piece"); 140 } 141 142 // \brief Sort the pieces by offset. 143 // Remove any duplicate entries by dropping all but the first. 144 void sortUniqueValues() { 145 std::sort(Values.begin(), Values.end()); 146 Values.erase(std::unique(Values.begin(), Values.end(), 147 [](const Value &A, const Value &B) { 148 return A.getVariable() == B.getVariable() && 149 A.getExpression() == B.getExpression(); 150 }), 151 Values.end()); 152 } 153 154 /// \brief Lower this entry into a DWARF expression. 155 void finalize(const AsmPrinter &AP, 156 const DITypeIdentifierMap &TypeIdentifierMap); 157 158 /// \brief Return the lowered DWARF expression. 159 StringRef getDWARFBytes() const { return DWARFBytes; } 160 /// \brief Return the assembler comments for the lowered DWARF expression. 161 const SmallVectorImpl<std::string> &getComments() const { return Comments; } 162 }; 163 164 /// \brief Compare two Values for equality. 165 inline bool operator==(const DebugLocEntry::Value &A, 166 const DebugLocEntry::Value &B) { 167 if (A.EntryKind != B.EntryKind) 168 return false; 169 170 if (A.Expression != B.Expression) 171 return false; 172 173 if (A.Variable != B.Variable) 174 return false; 175 176 switch (A.EntryKind) { 177 case DebugLocEntry::Value::E_Location: 178 return A.Loc == B.Loc; 179 case DebugLocEntry::Value::E_Integer: 180 return A.Constant.Int == B.Constant.Int; 181 case DebugLocEntry::Value::E_ConstantFP: 182 return A.Constant.CFP == B.Constant.CFP; 183 case DebugLocEntry::Value::E_ConstantInt: 184 return A.Constant.CIP == B.Constant.CIP; 185 } 186 llvm_unreachable("unhandled EntryKind"); 187 } 188 189 /// \brief Compare two pieces based on their offset. 190 inline bool operator<(const DebugLocEntry::Value &A, 191 const DebugLocEntry::Value &B) { 192 return A.getExpression().getBitPieceOffset() < 193 B.getExpression().getBitPieceOffset(); 194 } 195 196 } 197 198 #endif 199