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 /// This struct describes target specific location. 24 struct TargetIndexLocation { 25 int Index; 26 int Offset; 27 28 TargetIndexLocation() = default; TargetIndexLocationTargetIndexLocation29 TargetIndexLocation(unsigned Idx, int64_t Offset) 30 : Index(Idx), Offset(Offset) {} 31 32 bool operator==(const TargetIndexLocation &Other) const { 33 return Index == Other.Index && Offset == Other.Offset; 34 } 35 }; 36 37 /// A single location or constant. 38 class DbgValueLoc { 39 /// Any complex address location expression for this DbgValueLoc. 40 const DIExpression *Expression; 41 42 /// Type of entry that this represents. 43 enum EntryType { 44 E_Location, 45 E_Integer, 46 E_ConstantFP, 47 E_ConstantInt, 48 E_TargetIndexLocation 49 }; 50 enum EntryType EntryKind; 51 52 /// Either a constant, 53 union { 54 int64_t Int; 55 const ConstantFP *CFP; 56 const ConstantInt *CIP; 57 } Constant; 58 59 union { 60 /// Or a location in the machine frame. 61 MachineLocation Loc; 62 /// Or a location from target specific location. 63 TargetIndexLocation TIL; 64 }; 65 66 public: DbgValueLoc(const DIExpression * Expr,int64_t i)67 DbgValueLoc(const DIExpression *Expr, int64_t i) 68 : Expression(Expr), EntryKind(E_Integer) { 69 Constant.Int = i; 70 } DbgValueLoc(const DIExpression * Expr,const ConstantFP * CFP)71 DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP) 72 : Expression(Expr), EntryKind(E_ConstantFP) { 73 Constant.CFP = CFP; 74 } DbgValueLoc(const DIExpression * Expr,const ConstantInt * CIP)75 DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP) 76 : Expression(Expr), EntryKind(E_ConstantInt) { 77 Constant.CIP = CIP; 78 } DbgValueLoc(const DIExpression * Expr,MachineLocation Loc)79 DbgValueLoc(const DIExpression *Expr, MachineLocation Loc) 80 : Expression(Expr), EntryKind(E_Location), Loc(Loc) { 81 assert(cast<DIExpression>(Expr)->isValid()); 82 } DbgValueLoc(const DIExpression * Expr,TargetIndexLocation Loc)83 DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc) 84 : Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {} 85 isLocation()86 bool isLocation() const { return EntryKind == E_Location; } isTargetIndexLocation()87 bool isTargetIndexLocation() const { 88 return EntryKind == E_TargetIndexLocation; 89 } isInt()90 bool isInt() const { return EntryKind == E_Integer; } isConstantFP()91 bool isConstantFP() const { return EntryKind == E_ConstantFP; } isConstantInt()92 bool isConstantInt() const { return EntryKind == E_ConstantInt; } getInt()93 int64_t getInt() const { return Constant.Int; } getConstantFP()94 const ConstantFP *getConstantFP() const { return Constant.CFP; } getConstantInt()95 const ConstantInt *getConstantInt() const { return Constant.CIP; } getLoc()96 MachineLocation getLoc() const { return Loc; } getTargetIndexLocation()97 TargetIndexLocation getTargetIndexLocation() const { return TIL; } isFragment()98 bool isFragment() const { return getExpression()->isFragment(); } isEntryVal()99 bool isEntryVal() const { return getExpression()->isEntryValue(); } getExpression()100 const DIExpression *getExpression() const { return Expression; } 101 friend bool operator==(const DbgValueLoc &, const DbgValueLoc &); 102 friend bool operator<(const DbgValueLoc &, const DbgValueLoc &); 103 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()104 LLVM_DUMP_METHOD void dump() const { 105 if (isLocation()) { 106 llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " "; 107 if (Loc.isIndirect()) 108 llvm::dbgs() << "+0"; 109 llvm::dbgs() << "} "; 110 } else if (isConstantInt()) 111 Constant.CIP->dump(); 112 else if (isConstantFP()) 113 Constant.CFP->dump(); 114 if (Expression) 115 Expression->dump(); 116 } 117 #endif 118 }; 119 120 /// This struct describes location entries emitted in the .debug_loc 121 /// section. 122 class DebugLocEntry { 123 /// Begin and end symbols for the address range that this location is valid. 124 const MCSymbol *Begin; 125 const MCSymbol *End; 126 127 /// A nonempty list of locations/constants belonging to this entry, 128 /// sorted by offset. 129 SmallVector<DbgValueLoc, 1> Values; 130 131 public: 132 /// Create a location list entry for the range [\p Begin, \p End). 133 /// 134 /// \param Vals One or more values describing (parts of) the variable. DebugLocEntry(const MCSymbol * Begin,const MCSymbol * End,ArrayRef<DbgValueLoc> Vals)135 DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End, 136 ArrayRef<DbgValueLoc> Vals) 137 : Begin(Begin), End(End) { 138 addValues(Vals); 139 } 140 141 /// Attempt to merge this DebugLocEntry with Next and return 142 /// true if the merge was successful. Entries can be merged if they 143 /// share the same Loc/Constant and if Next immediately follows this 144 /// Entry. MergeRanges(const DebugLocEntry & Next)145 bool MergeRanges(const DebugLocEntry &Next) { 146 // If this and Next are describing the same variable, merge them. 147 if ((End == Next.Begin && Values == Next.Values)) { 148 End = Next.End; 149 return true; 150 } 151 return false; 152 } 153 getBeginSym()154 const MCSymbol *getBeginSym() const { return Begin; } getEndSym()155 const MCSymbol *getEndSym() const { return End; } getValues()156 ArrayRef<DbgValueLoc> getValues() const { return Values; } addValues(ArrayRef<DbgValueLoc> Vals)157 void addValues(ArrayRef<DbgValueLoc> Vals) { 158 Values.append(Vals.begin(), Vals.end()); 159 sortUniqueValues(); 160 assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) { 161 return V.isFragment(); 162 })) && "must either have a single value or multiple pieces"); 163 } 164 165 // Sort the pieces by offset. 166 // Remove any duplicate entries by dropping all but the first. sortUniqueValues()167 void sortUniqueValues() { 168 llvm::sort(Values); 169 Values.erase(std::unique(Values.begin(), Values.end(), 170 [](const DbgValueLoc &A, const DbgValueLoc &B) { 171 return A.getExpression() == B.getExpression(); 172 }), 173 Values.end()); 174 } 175 176 /// Lower this entry into a DWARF expression. 177 void finalize(const AsmPrinter &AP, 178 DebugLocStream::ListBuilder &List, 179 const DIBasicType *BT, 180 DwarfCompileUnit &TheCU); 181 }; 182 183 /// Compare two DbgValueLocs for equality. 184 inline bool operator==(const DbgValueLoc &A, 185 const DbgValueLoc &B) { 186 if (A.EntryKind != B.EntryKind) 187 return false; 188 189 if (A.Expression != B.Expression) 190 return false; 191 192 switch (A.EntryKind) { 193 case DbgValueLoc::E_Location: 194 return A.Loc == B.Loc; 195 case DbgValueLoc::E_TargetIndexLocation: 196 return A.TIL == B.TIL; 197 case DbgValueLoc::E_Integer: 198 return A.Constant.Int == B.Constant.Int; 199 case DbgValueLoc::E_ConstantFP: 200 return A.Constant.CFP == B.Constant.CFP; 201 case DbgValueLoc::E_ConstantInt: 202 return A.Constant.CIP == B.Constant.CIP; 203 } 204 llvm_unreachable("unhandled EntryKind"); 205 } 206 207 /// Compare two fragments based on their offset. 208 inline bool operator<(const DbgValueLoc &A, 209 const DbgValueLoc &B) { 210 return A.getExpression()->getFragmentInfo()->OffsetInBits < 211 B.getExpression()->getFragmentInfo()->OffsetInBits; 212 } 213 214 } 215 216 #endif 217