Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
35271 views
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 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 {
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
DbgValueLocEntry(int64_t i) : EntryKind(E_Integer) { Constant.Int = i; }
68
DbgValueLocEntry(const ConstantFP *CFP) : EntryKind(E_ConstantFP) {
69
Constant.CFP = CFP;
70
}
71
DbgValueLocEntry(const ConstantInt *CIP) : EntryKind(E_ConstantInt) {
72
Constant.CIP = CIP;
73
}
74
DbgValueLocEntry(MachineLocation Loc) : EntryKind(E_Location), Loc(Loc) {}
75
DbgValueLocEntry(TargetIndexLocation Loc)
76
: EntryKind(E_TargetIndexLocation), TIL(Loc) {}
77
78
bool isLocation() const { return EntryKind == E_Location; }
79
bool isIndirectLocation() const {
80
return EntryKind == E_Location && Loc.isIndirect();
81
}
82
bool isTargetIndexLocation() const {
83
return EntryKind == E_TargetIndexLocation;
84
}
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 {
96
if (isLocation()) {
97
llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
98
if (Loc.isIndirect())
99
llvm::dbgs() << "+0";
100
llvm::dbgs() << "} ";
101
} else if (isConstantInt())
102
Constant.CIP->dump();
103
else if (isConstantFP())
104
Constant.CFP->dump();
105
}
106
#endif
107
};
108
109
/// The location of a single variable, composed of an expression and 0 or more
110
/// DbgValueLocEntries.
111
class DbgValueLoc {
112
/// Any complex address location expression for this DbgValueLoc.
113
const DIExpression *Expression;
114
115
SmallVector<DbgValueLocEntry, 2> ValueLocEntries;
116
117
bool IsVariadic;
118
119
public:
120
DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs)
121
: Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
122
IsVariadic(true) {}
123
124
DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs,
125
bool IsVariadic)
126
: Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
127
IsVariadic(IsVariadic) {
128
#ifndef NDEBUG
129
assert(Expr->isValid() ||
130
!any_of(Locs, [](auto LE) { return LE.isLocation(); }));
131
if (!IsVariadic) {
132
assert(ValueLocEntries.size() == 1);
133
}
134
#endif
135
}
136
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.");
141
}
142
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())
149
return false;
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))
157
return false;
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();
165
}
166
// If neither are indirect, then just compare the loc entries directly.
167
return ValueLocEntries == Other.ValueLocEntries;
168
}
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)
176
DV.dump();
177
if (Expression)
178
Expression->dump();
179
}
180
#endif
181
};
182
183
/// This struct describes location entries emitted in the .debug_loc
184
/// section.
185
class DebugLocEntry {
186
/// Begin and end symbols for the address range that this location is valid.
187
const MCSymbol *Begin;
188
const MCSymbol *End;
189
190
/// A nonempty list of locations/constants belonging to this entry,
191
/// sorted by offset.
192
SmallVector<DbgValueLoc, 1> Values;
193
194
public:
195
/// Create a location list entry for the range [\p Begin, \p End).
196
///
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) {
201
addValues(Vals);
202
}
203
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
207
/// Entry.
208
bool MergeRanges(const DebugLocEntry &Next) {
209
// If this and Next are describing the same variable, merge them.
210
if (End != Next.Begin)
211
return false;
212
if (Values.size() != Next.Values.size())
213
return false;
214
for (unsigned EntryIdx = 0; EntryIdx < Values.size(); ++EntryIdx)
215
if (!Values[EntryIdx].isEquivalent(Next.Values[EntryIdx]))
216
return false;
217
End = Next.End;
218
return true;
219
}
220
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());
226
sortUniqueValues();
227
assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {
228
return V.isFragment();
229
})) && "must either have a single value or multiple pieces");
230
}
231
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)
239
return;
240
llvm::sort(Values);
241
Values.erase(llvm::unique(Values,
242
[](const DbgValueLoc &A, const DbgValueLoc &B) {
243
return A.getExpression() == B.getExpression();
244
}),
245
Values.end());
246
}
247
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);
253
};
254
255
/// Compare two DbgValueLocEntries for equality.
256
inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) {
257
if (A.EntryKind != B.EntryKind)
258
return false;
259
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;
271
}
272
llvm_unreachable("unhandled EntryKind");
273
}
274
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;
279
}
280
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;
286
}
287
288
}
289
290
#endif
291
292