DebugLocEntry.h 8.9 KB

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