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 isTargetIndexLocation() const {
80 return EntryKind
== E_TargetIndexLocation
;
82 bool isInt() const { return EntryKind
== E_Integer
; }
83 bool isConstantFP() const { return EntryKind
== E_ConstantFP
; }
84 bool isConstantInt() const { return EntryKind
== E_ConstantInt
; }
85 int64_t getInt() const { return Constant
.Int
; }
86 const ConstantFP
*getConstantFP() const { return Constant
.CFP
; }
87 const ConstantInt
*getConstantInt() const { return Constant
.CIP
; }
88 MachineLocation
getLoc() const { return Loc
; }
89 TargetIndexLocation
getTargetIndexLocation() const { return TIL
; }
90 friend bool operator==(const DbgValueLocEntry
&, const DbgValueLocEntry
&);
91 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
92 LLVM_DUMP_METHOD
void dump() const {
94 llvm::dbgs() << "Loc = { reg=" << Loc
.getReg() << " ";
98 } else if (isConstantInt())
100 else if (isConstantFP())
101 Constant
.CFP
->dump();
106 /// The location of a single variable, composed of an expression and 0 or more
107 /// DbgValueLocEntries.
109 /// Any complex address location expression for this DbgValueLoc.
110 const DIExpression
*Expression
;
112 SmallVector
<DbgValueLocEntry
, 2> ValueLocEntries
;
117 DbgValueLoc(const DIExpression
*Expr
, ArrayRef
<DbgValueLocEntry
> Locs
)
118 : Expression(Expr
), ValueLocEntries(Locs
.begin(), Locs
.end()),
121 // Currently, DBG_VALUE_VAR expressions must use stack_value.
122 assert(Expr
&& Expr
->isValid() &&
123 is_contained(Locs
, dwarf::DW_OP_stack_value
));
127 DbgValueLoc(const DIExpression
*Expr
, ArrayRef
<DbgValueLocEntry
> Locs
,
129 : Expression(Expr
), ValueLocEntries(Locs
.begin(), Locs
.end()),
130 IsVariadic(IsVariadic
) {
132 assert(cast
<DIExpression
>(Expr
)->isValid() ||
133 !any_of(Locs
, [](auto LE
) { return LE
.isLocation(); }));
135 assert(ValueLocEntries
.size() == 1);
137 // Currently, DBG_VALUE_VAR expressions must use stack_value.
138 assert(Expr
&& Expr
->isValid() &&
139 is_contained(Expr
->getElements(), dwarf::DW_OP_stack_value
));
144 DbgValueLoc(const DIExpression
*Expr
, DbgValueLocEntry Loc
)
145 : Expression(Expr
), ValueLocEntries(1, Loc
), IsVariadic(false) {
146 assert(((Expr
&& Expr
->isValid()) || !Loc
.isLocation()) &&
147 "DBG_VALUE with a machine location must have a valid expression.");
150 bool isFragment() const { return getExpression()->isFragment(); }
151 bool isEntryVal() const { return getExpression()->isEntryValue(); }
152 bool isVariadic() const { return IsVariadic
; }
153 const DIExpression
*getExpression() const { return Expression
; }
154 const ArrayRef
<DbgValueLocEntry
> getLocEntries() const {
155 return ValueLocEntries
;
157 friend bool operator==(const DbgValueLoc
&, const DbgValueLoc
&);
158 friend bool operator<(const DbgValueLoc
&, const DbgValueLoc
&);
159 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
160 LLVM_DUMP_METHOD
void dump() const {
161 for (const DbgValueLocEntry
&DV
: ValueLocEntries
)
169 /// This struct describes location entries emitted in the .debug_loc
171 class DebugLocEntry
{
172 /// Begin and end symbols for the address range that this location is valid.
173 const MCSymbol
*Begin
;
176 /// A nonempty list of locations/constants belonging to this entry,
177 /// sorted by offset.
178 SmallVector
<DbgValueLoc
, 1> Values
;
181 /// Create a location list entry for the range [\p Begin, \p End).
183 /// \param Vals One or more values describing (parts of) the variable.
184 DebugLocEntry(const MCSymbol
*Begin
, const MCSymbol
*End
,
185 ArrayRef
<DbgValueLoc
> Vals
)
186 : Begin(Begin
), End(End
) {
190 /// Attempt to merge this DebugLocEntry with Next and return
191 /// true if the merge was successful. Entries can be merged if they
192 /// share the same Loc/Constant and if Next immediately follows this
194 bool MergeRanges(const DebugLocEntry
&Next
) {
195 // If this and Next are describing the same variable, merge them.
196 if ((End
== Next
.Begin
&& Values
== Next
.Values
)) {
203 const MCSymbol
*getBeginSym() const { return Begin
; }
204 const MCSymbol
*getEndSym() const { return End
; }
205 ArrayRef
<DbgValueLoc
> getValues() const { return Values
; }
206 void addValues(ArrayRef
<DbgValueLoc
> Vals
) {
207 Values
.append(Vals
.begin(), Vals
.end());
209 assert((Values
.size() == 1 || all_of(Values
, [](DbgValueLoc V
) {
210 return V
.isFragment();
211 })) && "must either have a single value or multiple pieces");
214 // Sort the pieces by offset.
215 // Remove any duplicate entries by dropping all but the first.
216 void sortUniqueValues() {
218 Values
.erase(std::unique(Values
.begin(), Values
.end(),
219 [](const DbgValueLoc
&A
, const DbgValueLoc
&B
) {
220 return A
.getExpression() == B
.getExpression();
225 /// Lower this entry into a DWARF expression.
226 void finalize(const AsmPrinter
&AP
,
227 DebugLocStream::ListBuilder
&List
,
228 const DIBasicType
*BT
,
229 DwarfCompileUnit
&TheCU
);
232 /// Compare two DbgValueLocEntries for equality.
233 inline bool operator==(const DbgValueLocEntry
&A
, const DbgValueLocEntry
&B
) {
234 if (A
.EntryKind
!= B
.EntryKind
)
237 switch (A
.EntryKind
) {
238 case DbgValueLocEntry::E_Location
:
239 return A
.Loc
== B
.Loc
;
240 case DbgValueLocEntry::E_TargetIndexLocation
:
241 return A
.TIL
== B
.TIL
;
242 case DbgValueLocEntry::E_Integer
:
243 return A
.Constant
.Int
== B
.Constant
.Int
;
244 case DbgValueLocEntry::E_ConstantFP
:
245 return A
.Constant
.CFP
== B
.Constant
.CFP
;
246 case DbgValueLocEntry::E_ConstantInt
:
247 return A
.Constant
.CIP
== B
.Constant
.CIP
;
249 llvm_unreachable("unhandled EntryKind");
252 /// Compare two DbgValueLocs for equality.
253 inline bool operator==(const DbgValueLoc
&A
, const DbgValueLoc
&B
) {
254 return A
.ValueLocEntries
== B
.ValueLocEntries
&&
255 A
.Expression
== B
.Expression
&& A
.IsVariadic
== B
.IsVariadic
;
258 /// Compare two fragments based on their offset.
259 inline bool operator<(const DbgValueLoc
&A
,
260 const DbgValueLoc
&B
) {
261 return A
.getExpression()->getFragmentInfo()->OffsetInBits
<
262 B
.getExpression()->getFragmentInfo()->OffsetInBits
;