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