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 18namespace llvm { 19class AsmPrinter; 20class MDNode; 21/// \brief This struct describes location entries emitted in the .debug_loc 22/// section. 23class DebugLocEntry { 24 /// Begin and end symbols for the address range that this location is valid. 25 const MCSymbol *Begin; 26 const MCSymbol *End; 27 28public: 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 DIVariable getVariable() const { return cast<MDLocalVariable>(Variable); } 78 bool isBitPiece() const { return getExpression()->isBitPiece(); } 79 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 86private: 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 93public: 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. 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. 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 132 const MCSymbol *getBeginSym() const { return Begin; } 133 const MCSymbol *getEndSym() const { return End; } 134 ArrayRef<Value> getValues() const { return Values; } 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. 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. 160 StringRef getDWARFBytes() const { return DWARFBytes; } 161 /// \brief Return the assembler comments for the lowered DWARF expression. 162 const SmallVectorImpl<std::string> &getComments() const { return Comments; } 163}; 164 165/// \brief Compare two Values for equality. 166inline 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. 191inline 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