DebugLocEntry.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 isIndirectLocation() const {
  68. return EntryKind == E_Location && Loc.isIndirect();
  69. }
  70. bool isTargetIndexLocation() const {
  71. return EntryKind == E_TargetIndexLocation;
  72. }
  73. bool isInt() const { return EntryKind == E_Integer; }
  74. bool isConstantFP() const { return EntryKind == E_ConstantFP; }
  75. bool isConstantInt() const { return EntryKind == E_ConstantInt; }
  76. int64_t getInt() const { return Constant.Int; }
  77. const ConstantFP *getConstantFP() const { return Constant.CFP; }
  78. const ConstantInt *getConstantInt() const { return Constant.CIP; }
  79. MachineLocation getLoc() const { return Loc; }
  80. TargetIndexLocation getTargetIndexLocation() const { return TIL; }
  81. friend bool operator==(const DbgValueLocEntry &, const DbgValueLocEntry &);
  82. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  83. LLVM_DUMP_METHOD void dump() const {
  84. if (isLocation()) {
  85. llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
  86. if (Loc.isIndirect())
  87. llvm::dbgs() << "+0";
  88. llvm::dbgs() << "} ";
  89. } else if (isConstantInt())
  90. Constant.CIP->dump();
  91. else if (isConstantFP())
  92. Constant.CFP->dump();
  93. }
  94. #endif
  95. };
  96. /// The location of a single variable, composed of an expression and 0 or more
  97. /// DbgValueLocEntries.
  98. class DbgValueLoc {
  99. /// Any complex address location expression for this DbgValueLoc.
  100. const DIExpression *Expression;
  101. SmallVector<DbgValueLocEntry, 2> ValueLocEntries;
  102. bool IsVariadic;
  103. public:
  104. DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs)
  105. : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
  106. IsVariadic(true) {}
  107. DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs,
  108. bool IsVariadic)
  109. : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
  110. IsVariadic(IsVariadic) {
  111. #ifndef NDEBUG
  112. assert(cast<DIExpression>(Expr)->isValid() ||
  113. !any_of(Locs, [](auto LE) { return LE.isLocation(); }));
  114. if (!IsVariadic) {
  115. assert(ValueLocEntries.size() == 1);
  116. }
  117. #endif
  118. }
  119. DbgValueLoc(const DIExpression *Expr, DbgValueLocEntry Loc)
  120. : Expression(Expr), ValueLocEntries(1, Loc), IsVariadic(false) {
  121. assert(((Expr && Expr->isValid()) || !Loc.isLocation()) &&
  122. "DBG_VALUE with a machine location must have a valid expression.");
  123. }
  124. bool isFragment() const { return getExpression()->isFragment(); }
  125. bool isEntryVal() const { return getExpression()->isEntryValue(); }
  126. bool isVariadic() const { return IsVariadic; }
  127. bool isEquivalent(const DbgValueLoc &Other) const {
  128. // Cannot be equivalent with different numbers of entries.
  129. if (ValueLocEntries.size() != Other.ValueLocEntries.size())
  130. return false;
  131. bool ThisIsIndirect =
  132. !IsVariadic && ValueLocEntries[0].isIndirectLocation();
  133. bool OtherIsIndirect =
  134. !Other.IsVariadic && Other.ValueLocEntries[0].isIndirectLocation();
  135. // Check equivalence of DIExpressions + Directness together.
  136. if (!DIExpression::isEqualExpression(Expression, ThisIsIndirect,
  137. Other.Expression, OtherIsIndirect))
  138. return false;
  139. // Indirectness should have been accounted for in the above check, so just
  140. // compare register values directly here.
  141. if (ThisIsIndirect || OtherIsIndirect) {
  142. DbgValueLocEntry ThisOp = ValueLocEntries[0];
  143. DbgValueLocEntry OtherOp = Other.ValueLocEntries[0];
  144. return ThisOp.isLocation() && OtherOp.isLocation() &&
  145. ThisOp.getLoc().getReg() == OtherOp.getLoc().getReg();
  146. }
  147. // If neither are indirect, then just compare the loc entries directly.
  148. return ValueLocEntries == Other.ValueLocEntries;
  149. }
  150. const DIExpression *getExpression() const { return Expression; }
  151. ArrayRef<DbgValueLocEntry> getLocEntries() const { return ValueLocEntries; }
  152. friend bool operator==(const DbgValueLoc &, const DbgValueLoc &);
  153. friend bool operator<(const DbgValueLoc &, const DbgValueLoc &);
  154. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  155. LLVM_DUMP_METHOD void dump() const {
  156. for (const DbgValueLocEntry &DV : ValueLocEntries)
  157. DV.dump();
  158. if (Expression)
  159. Expression->dump();
  160. }
  161. #endif
  162. };
  163. /// This struct describes location entries emitted in the .debug_loc
  164. /// section.
  165. class DebugLocEntry {
  166. /// Begin and end symbols for the address range that this location is valid.
  167. const MCSymbol *Begin;
  168. const MCSymbol *End;
  169. /// A nonempty list of locations/constants belonging to this entry,
  170. /// sorted by offset.
  171. SmallVector<DbgValueLoc, 1> Values;
  172. public:
  173. /// Create a location list entry for the range [\p Begin, \p End).
  174. ///
  175. /// \param Vals One or more values describing (parts of) the variable.
  176. DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End,
  177. ArrayRef<DbgValueLoc> Vals)
  178. : Begin(Begin), End(End) {
  179. addValues(Vals);
  180. }
  181. /// Attempt to merge this DebugLocEntry with Next and return
  182. /// true if the merge was successful. Entries can be merged if they
  183. /// share the same Loc/Constant and if Next immediately follows this
  184. /// Entry.
  185. bool MergeRanges(const DebugLocEntry &Next) {
  186. // If this and Next are describing the same variable, merge them.
  187. if (End != Next.Begin)
  188. return false;
  189. if (Values.size() != Next.Values.size())
  190. return false;
  191. for (unsigned EntryIdx = 0; EntryIdx < Values.size(); ++EntryIdx)
  192. if (!Values[EntryIdx].isEquivalent(Next.Values[EntryIdx]))
  193. return false;
  194. End = Next.End;
  195. return true;
  196. }
  197. const MCSymbol *getBeginSym() const { return Begin; }
  198. const MCSymbol *getEndSym() const { return End; }
  199. ArrayRef<DbgValueLoc> getValues() const { return Values; }
  200. void addValues(ArrayRef<DbgValueLoc> Vals) {
  201. Values.append(Vals.begin(), Vals.end());
  202. sortUniqueValues();
  203. assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {
  204. return V.isFragment();
  205. })) && "must either have a single value or multiple pieces");
  206. }
  207. // Sort the pieces by offset.
  208. // Remove any duplicate entries by dropping all but the first.
  209. void sortUniqueValues() {
  210. // Values is either 1 item that does not have a fragment, or many items
  211. // that all do. No need to sort if the former and also prevents operator<
  212. // being called on a non fragment item when _GLIBCXX_DEBUG is defined.
  213. if (Values.size() == 1)
  214. return;
  215. llvm::sort(Values);
  216. Values.erase(std::unique(Values.begin(), Values.end(),
  217. [](const DbgValueLoc &A, const DbgValueLoc &B) {
  218. return A.getExpression() == B.getExpression();
  219. }),
  220. Values.end());
  221. }
  222. /// Lower this entry into a DWARF expression.
  223. void finalize(const AsmPrinter &AP,
  224. DebugLocStream::ListBuilder &List,
  225. const DIBasicType *BT,
  226. DwarfCompileUnit &TheCU);
  227. };
  228. /// Compare two DbgValueLocEntries for equality.
  229. inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) {
  230. if (A.EntryKind != B.EntryKind)
  231. return false;
  232. switch (A.EntryKind) {
  233. case DbgValueLocEntry::E_Location:
  234. return A.Loc == B.Loc;
  235. case DbgValueLocEntry::E_TargetIndexLocation:
  236. return A.TIL == B.TIL;
  237. case DbgValueLocEntry::E_Integer:
  238. return A.Constant.Int == B.Constant.Int;
  239. case DbgValueLocEntry::E_ConstantFP:
  240. return A.Constant.CFP == B.Constant.CFP;
  241. case DbgValueLocEntry::E_ConstantInt:
  242. return A.Constant.CIP == B.Constant.CIP;
  243. }
  244. llvm_unreachable("unhandled EntryKind");
  245. }
  246. /// Compare two DbgValueLocs for equality.
  247. inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) {
  248. return A.ValueLocEntries == B.ValueLocEntries &&
  249. A.Expression == B.Expression && A.IsVariadic == B.IsVariadic;
  250. }
  251. /// Compare two fragments based on their offset.
  252. inline bool operator<(const DbgValueLoc &A,
  253. const DbgValueLoc &B) {
  254. return A.getExpression()->getFragmentInfo()->OffsetInBits <
  255. B.getExpression()->getFragmentInfo()->OffsetInBits;
  256. }
  257. }
  258. #endif