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
.begin(), Locs
.end()),
124 DbgValueLoc(const DIExpression
*Expr
, ArrayRef
<DbgValueLocEntry
> Locs
,
126 : Expression(Expr
), ValueLocEntries(Locs
.begin(), Locs
.end()),
127 IsVariadic(IsVariadic
) {
129 assert(Expr
->isValid() ||
130 !any_of(Locs
, [](auto LE
) { return LE
.isLocation(); }));
132 assert(ValueLocEntries
.size() == 1);
137 DbgValueLoc(const DIExpression
*Expr
, DbgValueLocEntry Loc
)
138 : Expression(Expr
), ValueLocEntries(1, Loc
), IsVariadic(false) {
139 assert(((Expr
&& Expr
->isValid()) || !Loc
.isLocation()) &&
140 "DBG_VALUE with a machine location must have a valid expression.");
143 bool isFragment() const { return getExpression()->isFragment(); }
144 bool isEntryVal() const { return getExpression()->isEntryValue(); }
145 bool isVariadic() const { return IsVariadic
; }
146 bool isEquivalent(const DbgValueLoc
&Other
) const {
147 // Cannot be equivalent with different numbers of entries.
148 if (ValueLocEntries
.size() != Other
.ValueLocEntries
.size())
150 bool ThisIsIndirect
=
151 !IsVariadic
&& ValueLocEntries
[0].isIndirectLocation();
152 bool OtherIsIndirect
=
153 !Other
.IsVariadic
&& Other
.ValueLocEntries
[0].isIndirectLocation();
154 // Check equivalence of DIExpressions + Directness together.
155 if (!DIExpression::isEqualExpression(Expression
, ThisIsIndirect
,
156 Other
.Expression
, OtherIsIndirect
))
158 // Indirectness should have been accounted for in the above check, so just
159 // compare register values directly here.
160 if (ThisIsIndirect
|| OtherIsIndirect
) {
161 DbgValueLocEntry ThisOp
= ValueLocEntries
[0];
162 DbgValueLocEntry OtherOp
= Other
.ValueLocEntries
[0];
163 return ThisOp
.isLocation() && OtherOp
.isLocation() &&
164 ThisOp
.getLoc().getReg() == OtherOp
.getLoc().getReg();
166 // If neither are indirect, then just compare the loc entries directly.
167 return ValueLocEntries
== Other
.ValueLocEntries
;
169 const DIExpression
*getExpression() const { return Expression
; }
170 ArrayRef
<DbgValueLocEntry
> getLocEntries() const { return ValueLocEntries
; }
171 friend bool operator==(const DbgValueLoc
&, const DbgValueLoc
&);
172 friend bool operator<(const DbgValueLoc
&, const DbgValueLoc
&);
173 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
174 LLVM_DUMP_METHOD
void dump() const {
175 for (const DbgValueLocEntry
&DV
: ValueLocEntries
)
183 /// This struct describes location entries emitted in the .debug_loc
185 class DebugLocEntry
{
186 /// Begin and end symbols for the address range that this location is valid.
187 const MCSymbol
*Begin
;
190 /// A nonempty list of locations/constants belonging to this entry,
191 /// sorted by offset.
192 SmallVector
<DbgValueLoc
, 1> Values
;
195 /// Create a location list entry for the range [\p Begin, \p End).
197 /// \param Vals One or more values describing (parts of) the variable.
198 DebugLocEntry(const MCSymbol
*Begin
, const MCSymbol
*End
,
199 ArrayRef
<DbgValueLoc
> Vals
)
200 : Begin(Begin
), End(End
) {
204 /// Attempt to merge this DebugLocEntry with Next and return
205 /// true if the merge was successful. Entries can be merged if they
206 /// share the same Loc/Constant and if Next immediately follows this
208 bool MergeRanges(const DebugLocEntry
&Next
) {
209 // If this and Next are describing the same variable, merge them.
210 if (End
!= Next
.Begin
)
212 if (Values
.size() != Next
.Values
.size())
214 for (unsigned EntryIdx
= 0; EntryIdx
< Values
.size(); ++EntryIdx
)
215 if (!Values
[EntryIdx
].isEquivalent(Next
.Values
[EntryIdx
]))
221 const MCSymbol
*getBeginSym() const { return Begin
; }
222 const MCSymbol
*getEndSym() const { return End
; }
223 ArrayRef
<DbgValueLoc
> getValues() const { return Values
; }
224 void addValues(ArrayRef
<DbgValueLoc
> Vals
) {
225 Values
.append(Vals
.begin(), Vals
.end());
227 assert((Values
.size() == 1 || all_of(Values
, [](DbgValueLoc V
) {
228 return V
.isFragment();
229 })) && "must either have a single value or multiple pieces");
232 // Sort the pieces by offset.
233 // Remove any duplicate entries by dropping all but the first.
234 void sortUniqueValues() {
235 // Values is either 1 item that does not have a fragment, or many items
236 // that all do. No need to sort if the former and also prevents operator<
237 // being called on a non fragment item when _GLIBCXX_DEBUG is defined.
238 if (Values
.size() == 1)
241 Values
.erase(std::unique(Values
.begin(), Values
.end(),
242 [](const DbgValueLoc
&A
, const DbgValueLoc
&B
) {
243 return A
.getExpression() == B
.getExpression();
248 /// Lower this entry into a DWARF expression.
249 void finalize(const AsmPrinter
&AP
,
250 DebugLocStream::ListBuilder
&List
,
251 const DIBasicType
*BT
,
252 DwarfCompileUnit
&TheCU
);
255 /// Compare two DbgValueLocEntries for equality.
256 inline bool operator==(const DbgValueLocEntry
&A
, const DbgValueLocEntry
&B
) {
257 if (A
.EntryKind
!= B
.EntryKind
)
260 switch (A
.EntryKind
) {
261 case DbgValueLocEntry::E_Location
:
262 return A
.Loc
== B
.Loc
;
263 case DbgValueLocEntry::E_TargetIndexLocation
:
264 return A
.TIL
== B
.TIL
;
265 case DbgValueLocEntry::E_Integer
:
266 return A
.Constant
.Int
== B
.Constant
.Int
;
267 case DbgValueLocEntry::E_ConstantFP
:
268 return A
.Constant
.CFP
== B
.Constant
.CFP
;
269 case DbgValueLocEntry::E_ConstantInt
:
270 return A
.Constant
.CIP
== B
.Constant
.CIP
;
272 llvm_unreachable("unhandled EntryKind");
275 /// Compare two DbgValueLocs for equality.
276 inline bool operator==(const DbgValueLoc
&A
, const DbgValueLoc
&B
) {
277 return A
.ValueLocEntries
== B
.ValueLocEntries
&&
278 A
.Expression
== B
.Expression
&& A
.IsVariadic
== B
.IsVariadic
;
281 /// Compare two fragments based on their offset.
282 inline bool operator<(const DbgValueLoc
&A
,
283 const DbgValueLoc
&B
) {
284 return A
.getExpression()->getFragmentInfo()->OffsetInBits
<
285 B
.getExpression()->getFragmentInfo()->OffsetInBits
;