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