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