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(isa<MDLocalVariable>(Var)); 46 assert(cast<MDExpression>(Expr)->isValid()); 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 cast<MDLocalVariable>(Variable); } 79 bool isBitPiece() const { return getExpression().isBitPiece(); } 80 DIExpression getExpression() const { 81 return cast_or_null<MDExpression>(Expression); 82 } 83 friend bool operator==(const Value &, const Value &); 84 friend bool operator<(const Value &, const Value &); 85 }; 86 87 private: 88 /// A nonempty list of locations/constants belonging to this entry, 89 /// sorted by offset. 90 SmallVector<Value, 1> Values; 91 SmallString<8> DWARFBytes; 92 SmallVector<std::string, 1> Comments; 93 94 public: 95 DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val) 96 : Begin(B), End(E) { 97 Values.push_back(std::move(Val)); 98 } 99 100 /// \brief If this and Next are describing different pieces of the same 101 /// variable, merge them by appending Next's values to the current 102 /// list of values. 103 /// Return true if the merge was successful. 104 bool MergeValues(const DebugLocEntry &Next) { 105 if (Begin == Next.Begin) { 106 DIExpression Expr = cast_or_null<MDExpression>(Values[0].Expression); 107 DIVariable Var = cast_or_null<MDLocalVariable>(Values[0].Variable); 108 DIExpression NextExpr = 109 cast_or_null<MDExpression>(Next.Values[0].Expression); 110 DIVariable NextVar = cast_or_null<MDLocalVariable>(Next.Values[0].Variable); 111 if (Var == NextVar && Expr.isBitPiece() && 112 NextExpr.isBitPiece()) { 113 addValues(Next.Values); 114 End = Next.End; 115 return true; 116 } 117 } 118 return false; 119 } 120 121 /// \brief Attempt to merge this DebugLocEntry with Next and return 122 /// true if the merge was successful. Entries can be merged if they 123 /// share the same Loc/Constant and if Next immediately follows this 124 /// Entry. 125 bool MergeRanges(const DebugLocEntry &Next) { 126 // If this and Next are describing the same variable, merge them. 127 if ((End == Next.Begin && Values == Next.Values)) { 128 End = Next.End; 129 return true; 130 } 131 return false; 132 } 133 134 const MCSymbol *getBeginSym() const { return Begin; } 135 const MCSymbol *getEndSym() const { return End; } 136 ArrayRef<Value> getValues() const { return Values; } 137 void addValues(ArrayRef<DebugLocEntry::Value> Vals) { 138 Values.append(Vals.begin(), Vals.end()); 139 sortUniqueValues(); 140 assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){ 141 return V.isBitPiece(); 142 }) && "value must be a piece"); 143 } 144 145 // \brief Sort the pieces by offset. 146 // Remove any duplicate entries by dropping all but the first. 147 void sortUniqueValues() { 148 std::sort(Values.begin(), Values.end()); 149 Values.erase(std::unique(Values.begin(), Values.end(), 150 [](const Value &A, const Value &B) { 151 return A.getVariable() == B.getVariable() && 152 A.getExpression() == B.getExpression(); 153 }), 154 Values.end()); 155 } 156 157 /// \brief Lower this entry into a DWARF expression. 158 void finalize(const AsmPrinter &AP, 159 const DITypeIdentifierMap &TypeIdentifierMap); 160 161 /// \brief Return the lowered DWARF expression. 162 StringRef getDWARFBytes() const { return DWARFBytes; } 163 /// \brief Return the assembler comments for the lowered DWARF expression. 164 const SmallVectorImpl<std::string> &getComments() const { return Comments; } 165 }; 166 167 /// \brief Compare two Values for equality. 168 inline bool operator==(const DebugLocEntry::Value &A, 169 const DebugLocEntry::Value &B) { 170 if (A.EntryKind != B.EntryKind) 171 return false; 172 173 if (A.Expression != B.Expression) 174 return false; 175 176 if (A.Variable != B.Variable) 177 return false; 178 179 switch (A.EntryKind) { 180 case DebugLocEntry::Value::E_Location: 181 return A.Loc == B.Loc; 182 case DebugLocEntry::Value::E_Integer: 183 return A.Constant.Int == B.Constant.Int; 184 case DebugLocEntry::Value::E_ConstantFP: 185 return A.Constant.CFP == B.Constant.CFP; 186 case DebugLocEntry::Value::E_ConstantInt: 187 return A.Constant.CIP == B.Constant.CIP; 188 } 189 llvm_unreachable("unhandled EntryKind"); 190 } 191 192 /// \brief Compare two pieces based on their offset. 193 inline bool operator<(const DebugLocEntry::Value &A, 194 const DebugLocEntry::Value &B) { 195 return A.getExpression().getBitPieceOffset() < 196 B.getExpression().getBitPieceOffset(); 197 } 198 199 } 200 201 #endif 202