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 const DIExpression *getExpression() const { return Expression; } 70 friend bool operator==(const DbgValueLoc &, const DbgValueLoc &); 71 friend bool operator<(const DbgValueLoc &, const DbgValueLoc &); 72 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 73 LLVM_DUMP_METHOD void dump() const { 74 if (isLocation()) { 75 llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " "; 76 if (Loc.isIndirect()) 77 llvm::dbgs() << "+0"; 78 llvm::dbgs() << "} "; 79 } else if (isConstantInt()) 80 Constant.CIP->dump(); 81 else if (isConstantFP()) 82 Constant.CFP->dump(); 83 if (Expression) 84 Expression->dump(); 85 } 86 #endif 87 }; 88 89 /// This struct describes location entries emitted in the .debug_loc 90 /// section. 91 class DebugLocEntry { 92 /// Begin and end symbols for the address range that this location is valid. 93 const MCSymbol *Begin; 94 const MCSymbol *End; 95 96 /// A nonempty list of locations/constants belonging to this entry, 97 /// sorted by offset. 98 SmallVector<DbgValueLoc, 1> Values; 99 100 public: 101 /// Create a location list entry for the range [\p Begin, \p End). 102 /// 103 /// \param Vals One or more values describing (parts of) the variable. 104 DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End, 105 ArrayRef<DbgValueLoc> Vals) 106 : Begin(Begin), End(End) { 107 addValues(Vals); 108 } 109 110 /// Attempt to merge this DebugLocEntry with Next and return 111 /// true if the merge was successful. Entries can be merged if they 112 /// share the same Loc/Constant and if Next immediately follows this 113 /// Entry. 114 bool MergeRanges(const DebugLocEntry &Next) { 115 // If this and Next are describing the same variable, merge them. 116 if ((End == Next.Begin && Values == Next.Values)) { 117 End = Next.End; 118 return true; 119 } 120 return false; 121 } 122 123 const MCSymbol *getBeginSym() const { return Begin; } 124 const MCSymbol *getEndSym() const { return End; } 125 ArrayRef<DbgValueLoc> getValues() const { return Values; } 126 void addValues(ArrayRef<DbgValueLoc> Vals) { 127 Values.append(Vals.begin(), Vals.end()); 128 sortUniqueValues(); 129 assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) { 130 return V.isFragment(); 131 })) && "must either have a single value or multiple pieces"); 132 } 133 134 // Sort the pieces by offset. 135 // Remove any duplicate entries by dropping all but the first. 136 void sortUniqueValues() { 137 llvm::sort(Values); 138 Values.erase(std::unique(Values.begin(), Values.end(), 139 [](const DbgValueLoc &A, const DbgValueLoc &B) { 140 return A.getExpression() == B.getExpression(); 141 }), 142 Values.end()); 143 } 144 145 /// Lower this entry into a DWARF expression. 146 void finalize(const AsmPrinter &AP, 147 DebugLocStream::ListBuilder &List, 148 const DIBasicType *BT, 149 DwarfCompileUnit &TheCU); 150 }; 151 152 /// Compare two DbgValueLocs for equality. 153 inline bool operator==(const DbgValueLoc &A, 154 const DbgValueLoc &B) { 155 if (A.EntryKind != B.EntryKind) 156 return false; 157 158 if (A.Expression != B.Expression) 159 return false; 160 161 switch (A.EntryKind) { 162 case DbgValueLoc::E_Location: 163 return A.Loc == B.Loc; 164 case DbgValueLoc::E_Integer: 165 return A.Constant.Int == B.Constant.Int; 166 case DbgValueLoc::E_ConstantFP: 167 return A.Constant.CFP == B.Constant.CFP; 168 case DbgValueLoc::E_ConstantInt: 169 return A.Constant.CIP == B.Constant.CIP; 170 } 171 llvm_unreachable("unhandled EntryKind"); 172 } 173 174 /// Compare two fragments based on their offset. 175 inline bool operator<(const DbgValueLoc &A, 176 const DbgValueLoc &B) { 177 return A.getExpression()->getFragmentInfo()->OffsetInBits < 178 B.getExpression()->getFragmentInfo()->OffsetInBits; 179 } 180 181 } 182 183 #endif 184