1 //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
10 #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
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"
23 /// This struct describes target specific location.
24 struct TargetIndexLocation
{
28 TargetIndexLocation() = default;
29 TargetIndexLocation(unsigned Idx
, int64_t Offset
)
30 : Index(Idx
), Offset(Offset
) {}
32 bool operator==(const TargetIndexLocation
&Other
) const {
33 return Index
== Other
.Index
&& Offset
== Other
.Offset
;
37 /// A single location or constant within a variable location description, with
38 /// either a single entry (with an optional DIExpression) used for a DBG_VALUE,
39 /// or a list of entries used for a DBG_VALUE_LIST.
40 class DbgValueLocEntry
{
42 /// Type of entry that this represents.
50 enum EntryType EntryKind
;
52 /// Either a constant,
55 const ConstantFP
*CFP
;
56 const ConstantInt
*CIP
;
60 /// Or a location in the machine frame.
62 /// Or a location from target specific location.
63 TargetIndexLocation TIL
;
67 DbgValueLocEntry(int64_t i
) : EntryKind(E_Integer
) { Constant
.Int
= i
; }
68 DbgValueLocEntry(const ConstantFP
*CFP
) : EntryKind(E_ConstantFP
) {
71 DbgValueLocEntry(const ConstantInt
*CIP
) : EntryKind(E_ConstantInt
) {
74 DbgValueLocEntry(MachineLocation Loc
) : EntryKind(E_Location
), Loc(Loc
) {}
75 DbgValueLocEntry(TargetIndexLocation Loc
)
76 : EntryKind(E_TargetIndexLocation
), TIL(Loc
) {}
78 bool isLocation() const { return EntryKind
== E_Location
; }
79 bool isIndirectLocation() const {
80 return EntryKind
== E_Location
&& Loc
.isIndirect();
82 bool isTargetIndexLocation() const {
83 return EntryKind
== E_TargetIndexLocation
;
85 bool isInt() const { return EntryKind
== E_Integer
; }
86 bool isConstantFP() const { return EntryKind
== E_ConstantFP
; }
87 bool isConstantInt() const { return EntryKind
== E_ConstantInt
; }
88 int64_t getInt() const { return Constant
.Int
; }
89 const ConstantFP
*getConstantFP() const { return Constant
.CFP
; }
90 const ConstantInt
*getConstantInt() const { return Constant
.CIP
; }
91 MachineLocation
getLoc() const { return Loc
; }
92 TargetIndexLocation
getTargetIndexLocation() const { return TIL
; }
93 friend bool operator==(const DbgValueLocEntry
&, const DbgValueLocEntry
&);
94 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
95 LLVM_DUMP_METHOD
void dump() const {
97 llvm::dbgs() << "Loc = { reg=" << Loc
.getReg() << " ";
100 llvm::dbgs() << "} ";
101 } else if (isConstantInt())
102 Constant
.CIP
->dump();
103 else if (isConstantFP())
104 Constant
.CFP
->dump();
109 /// The location of a single variable, composed of an expression and 0 or more
110 /// DbgValueLocEntries.
112 /// Any complex address location expression for this DbgValueLoc.
113 const DIExpression
*Expression
;
115 SmallVector
<DbgValueLocEntry
, 2> ValueLocEntries
;
120 DbgValueLoc(const DIExpression
*Expr
, ArrayRef
<DbgValueLocEntry
> Locs
)
121 : Expression(Expr
), ValueLocEntries(Locs
), IsVariadic(true) {}
123 DbgValueLoc(const DIExpression
*Expr
, ArrayRef
<DbgValueLocEntry
> Locs
,
125 : Expression(Expr
), ValueLocEntries(Locs
), IsVariadic(IsVariadic
) {
127 assert(Expr
->isValid() ||
128 !any_of(Locs
, [](auto LE
) { return LE
.isLocation(); }));
130 assert(ValueLocEntries
.size() == 1);
135 DbgValueLoc(const DIExpression
*Expr
, DbgValueLocEntry Loc
)
136 : Expression(Expr
), ValueLocEntries(1, Loc
), IsVariadic(false) {
137 assert(((Expr
&& Expr
->isValid()) || !Loc
.isLocation()) &&
138 "DBG_VALUE with a machine location must have a valid expression.");
141 bool isFragment() const { return getExpression()->isFragment(); }
142 bool isEntryVal() const { return getExpression()->isEntryValue(); }
143 bool isVariadic() const { return IsVariadic
; }
144 bool isEquivalent(const DbgValueLoc
&Other
) const {
145 // Cannot be equivalent with different numbers of entries.
146 if (ValueLocEntries
.size() != Other
.ValueLocEntries
.size())
148 bool ThisIsIndirect
=
149 !IsVariadic
&& ValueLocEntries
[0].isIndirectLocation();
150 bool OtherIsIndirect
=
151 !Other
.IsVariadic
&& Other
.ValueLocEntries
[0].isIndirectLocation();
152 // Check equivalence of DIExpressions + Directness together.
153 if (!DIExpression::isEqualExpression(Expression
, ThisIsIndirect
,
154 Other
.Expression
, OtherIsIndirect
))
156 // Indirectness should have been accounted for in the above check, so just
157 // compare register values directly here.
158 if (ThisIsIndirect
|| OtherIsIndirect
) {
159 DbgValueLocEntry ThisOp
= ValueLocEntries
[0];
160 DbgValueLocEntry OtherOp
= Other
.ValueLocEntries
[0];
161 return ThisOp
.isLocation() && OtherOp
.isLocation() &&
162 ThisOp
.getLoc().getReg() == OtherOp
.getLoc().getReg();
164 // If neither are indirect, then just compare the loc entries directly.
165 return ValueLocEntries
== Other
.ValueLocEntries
;
167 const DIExpression
*getExpression() const { return Expression
; }
168 ArrayRef
<DbgValueLocEntry
> getLocEntries() const { return ValueLocEntries
; }
169 friend bool operator==(const DbgValueLoc
&, const DbgValueLoc
&);
170 friend bool operator<(const DbgValueLoc
&, const DbgValueLoc
&);
171 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
172 LLVM_DUMP_METHOD
void dump() const {
173 for (const DbgValueLocEntry
&DV
: ValueLocEntries
)
181 /// This struct describes location entries emitted in the .debug_loc
183 class DebugLocEntry
{
184 /// Begin and end symbols for the address range that this location is valid.
185 const MCSymbol
*Begin
;
188 /// A nonempty list of locations/constants belonging to this entry,
189 /// sorted by offset.
190 SmallVector
<DbgValueLoc
, 1> Values
;
193 /// Create a location list entry for the range [\p Begin, \p End).
195 /// \param Vals One or more values describing (parts of) the variable.
196 DebugLocEntry(const MCSymbol
*Begin
, const MCSymbol
*End
,
197 ArrayRef
<DbgValueLoc
> Vals
)
198 : Begin(Begin
), End(End
) {
202 /// Attempt to merge this DebugLocEntry with Next and return
203 /// true if the merge was successful. Entries can be merged if they
204 /// share the same Loc/Constant and if Next immediately follows this
206 bool MergeRanges(const DebugLocEntry
&Next
) {
207 // If this and Next are describing the same variable, merge them.
208 if (End
!= Next
.Begin
)
210 if (Values
.size() != Next
.Values
.size())
212 for (unsigned EntryIdx
= 0; EntryIdx
< Values
.size(); ++EntryIdx
)
213 if (!Values
[EntryIdx
].isEquivalent(Next
.Values
[EntryIdx
]))
219 const MCSymbol
*getBeginSym() const { return Begin
; }
220 const MCSymbol
*getEndSym() const { return End
; }
221 ArrayRef
<DbgValueLoc
> getValues() const { return Values
; }
222 void addValues(ArrayRef
<DbgValueLoc
> Vals
) {
223 Values
.append(Vals
.begin(), Vals
.end());
225 assert((Values
.size() == 1 || all_of(Values
, [](DbgValueLoc V
) {
226 return V
.isFragment();
227 })) && "must either have a single value or multiple pieces");
230 // Sort the pieces by offset.
231 // Remove any duplicate entries by dropping all but the first.
232 void sortUniqueValues() {
233 // Values is either 1 item that does not have a fragment, or many items
234 // that all do. No need to sort if the former and also prevents operator<
235 // being called on a non fragment item when _GLIBCXX_DEBUG is defined.
236 if (Values
.size() == 1)
239 Values
.erase(llvm::unique(Values
,
240 [](const DbgValueLoc
&A
, const DbgValueLoc
&B
) {
241 return A
.getExpression() == B
.getExpression();
246 /// Lower this entry into a DWARF expression.
247 void finalize(const AsmPrinter
&AP
,
248 DebugLocStream::ListBuilder
&List
,
249 const DIBasicType
*BT
,
250 DwarfCompileUnit
&TheCU
);
253 /// Compare two DbgValueLocEntries for equality.
254 inline bool operator==(const DbgValueLocEntry
&A
, const DbgValueLocEntry
&B
) {
255 if (A
.EntryKind
!= B
.EntryKind
)
258 switch (A
.EntryKind
) {
259 case DbgValueLocEntry::E_Location
:
260 return A
.Loc
== B
.Loc
;
261 case DbgValueLocEntry::E_TargetIndexLocation
:
262 return A
.TIL
== B
.TIL
;
263 case DbgValueLocEntry::E_Integer
:
264 return A
.Constant
.Int
== B
.Constant
.Int
;
265 case DbgValueLocEntry::E_ConstantFP
:
266 return A
.Constant
.CFP
== B
.Constant
.CFP
;
267 case DbgValueLocEntry::E_ConstantInt
:
268 return A
.Constant
.CIP
== B
.Constant
.CIP
;
270 llvm_unreachable("unhandled EntryKind");
273 /// Compare two DbgValueLocs for equality.
274 inline bool operator==(const DbgValueLoc
&A
, const DbgValueLoc
&B
) {
275 return A
.ValueLocEntries
== B
.ValueLocEntries
&&
276 A
.Expression
== B
.Expression
&& A
.IsVariadic
== B
.IsVariadic
;
279 /// Compare two fragments based on their offset.
280 inline bool operator<(const DbgValueLoc
&A
,
281 const DbgValueLoc
&B
) {
282 return A
.getExpression()->getFragmentInfo()->OffsetInBits
<
283 B
.getExpression()->getFragmentInfo()->OffsetInBits
;