xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
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;
29   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:
67   DbgValueLoc(const DIExpression *Expr, int64_t i)
68       : Expression(Expr), EntryKind(E_Integer) {
69     Constant.Int = i;
70   }
71   DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP)
72       : Expression(Expr), EntryKind(E_ConstantFP) {
73     Constant.CFP = CFP;
74   }
75   DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP)
76       : Expression(Expr), EntryKind(E_ConstantInt) {
77     Constant.CIP = CIP;
78   }
79   DbgValueLoc(const DIExpression *Expr, MachineLocation Loc)
80       : Expression(Expr), EntryKind(E_Location), Loc(Loc) {
81     assert(cast<DIExpression>(Expr)->isValid());
82   }
83   DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc)
84       : Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {}
85 
86   bool isLocation() const { return EntryKind == E_Location; }
87   bool isTargetIndexLocation() const {
88     return EntryKind == E_TargetIndexLocation;
89   }
90   bool isInt() const { return EntryKind == E_Integer; }
91   bool isConstantFP() const { return EntryKind == E_ConstantFP; }
92   bool isConstantInt() const { return EntryKind == E_ConstantInt; }
93   int64_t getInt() const { return Constant.Int; }
94   const ConstantFP *getConstantFP() const { return Constant.CFP; }
95   const ConstantInt *getConstantInt() const { return Constant.CIP; }
96   MachineLocation getLoc() const { return Loc; }
97   TargetIndexLocation getTargetIndexLocation() const { return TIL; }
98   bool isFragment() const { return getExpression()->isFragment(); }
99   bool isEntryVal() const { return getExpression()->isEntryValue(); }
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)
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.
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.
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 
154   const MCSymbol *getBeginSym() const { return Begin; }
155   const MCSymbol *getEndSym() const { return End; }
156   ArrayRef<DbgValueLoc> getValues() const { return Values; }
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.
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