Skip to content

Commit af9e522

Browse files
committed
[DebugInfo][NFC] Add RawLocationWrapper to wrap location operand metadata [1/x]
RawLocationWrapper wraps the location operand of a debug intrinsic which may be either (wrapped in MetadataAsValue) a DIArgList, ValueAsMetadata, or an empty MDTuple. This class lets us avoid duplicating location handling code in a later patch in this stack. Reviewed By: StephenTozer Differential Revision: https://reviews.llvm.org/D145909
1 parent d4320cb commit af9e522

File tree

2 files changed

+124
-60
lines changed

2 files changed

+124
-60
lines changed

llvm/include/llvm/IR/IntrinsicInst.h

Lines changed: 112 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -176,57 +176,114 @@ class DbgInfoIntrinsic : public IntrinsicInst {
176176
/// @}
177177
};
178178

179-
/// This is the common base class for debug info intrinsics for variables.
180-
class DbgVariableIntrinsic : public DbgInfoIntrinsic {
179+
// Iterator for ValueAsMetadata that internally uses direct pointer iteration
180+
// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the
181+
// ValueAsMetadata .
182+
class location_op_iterator
183+
: public iterator_facade_base<location_op_iterator,
184+
std::bidirectional_iterator_tag, Value *> {
185+
PointerUnion<ValueAsMetadata *, ValueAsMetadata **> I;
186+
181187
public:
182-
// Iterator for ValueAsMetadata that internally uses direct pointer iteration
183-
// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the
184-
// ValueAsMetadata .
185-
class location_op_iterator
186-
: public iterator_facade_base<location_op_iterator,
187-
std::bidirectional_iterator_tag, Value *> {
188-
PointerUnion<ValueAsMetadata *, ValueAsMetadata **> I;
189-
190-
public:
191-
location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {}
192-
location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {}
193-
194-
location_op_iterator(const location_op_iterator &R) : I(R.I) {}
195-
location_op_iterator &operator=(const location_op_iterator &R) {
196-
I = R.I;
197-
return *this;
198-
}
199-
bool operator==(const location_op_iterator &RHS) const {
200-
return I == RHS.I;
201-
}
202-
const Value *operator*() const {
203-
ValueAsMetadata *VAM = I.is<ValueAsMetadata *>()
204-
? I.get<ValueAsMetadata *>()
205-
: *I.get<ValueAsMetadata **>();
206-
return VAM->getValue();
207-
};
208-
Value *operator*() {
209-
ValueAsMetadata *VAM = I.is<ValueAsMetadata *>()
210-
? I.get<ValueAsMetadata *>()
211-
: *I.get<ValueAsMetadata **>();
212-
return VAM->getValue();
213-
}
214-
location_op_iterator &operator++() {
215-
if (I.is<ValueAsMetadata *>())
216-
I = I.get<ValueAsMetadata *>() + 1;
217-
else
218-
I = I.get<ValueAsMetadata **>() + 1;
219-
return *this;
220-
}
221-
location_op_iterator &operator--() {
222-
if (I.is<ValueAsMetadata *>())
223-
I = I.get<ValueAsMetadata *>() - 1;
224-
else
225-
I = I.get<ValueAsMetadata **>() - 1;
226-
return *this;
227-
}
188+
location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {}
189+
location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {}
190+
191+
location_op_iterator(const location_op_iterator &R) : I(R.I) {}
192+
location_op_iterator &operator=(const location_op_iterator &R) {
193+
I = R.I;
194+
return *this;
195+
}
196+
bool operator==(const location_op_iterator &RHS) const { return I == RHS.I; }
197+
const Value *operator*() const {
198+
ValueAsMetadata *VAM = I.is<ValueAsMetadata *>()
199+
? I.get<ValueAsMetadata *>()
200+
: *I.get<ValueAsMetadata **>();
201+
return VAM->getValue();
228202
};
203+
Value *operator*() {
204+
ValueAsMetadata *VAM = I.is<ValueAsMetadata *>()
205+
? I.get<ValueAsMetadata *>()
206+
: *I.get<ValueAsMetadata **>();
207+
return VAM->getValue();
208+
}
209+
location_op_iterator &operator++() {
210+
if (I.is<ValueAsMetadata *>())
211+
I = I.get<ValueAsMetadata *>() + 1;
212+
else
213+
I = I.get<ValueAsMetadata **>() + 1;
214+
return *this;
215+
}
216+
location_op_iterator &operator--() {
217+
if (I.is<ValueAsMetadata *>())
218+
I = I.get<ValueAsMetadata *>() - 1;
219+
else
220+
I = I.get<ValueAsMetadata **>() - 1;
221+
return *this;
222+
}
223+
};
224+
225+
/// Lightweight class that wraps the location operand metadata of a debug
226+
/// intrinsic. The raw location may be a ValueAsMetadata, an empty MDTuple,
227+
/// or a DIArgList.
228+
class RawLocationWrapper {
229+
Metadata *RawLocation = nullptr;
230+
231+
public:
232+
RawLocationWrapper() = default;
233+
explicit RawLocationWrapper(Metadata *RawLocation)
234+
: RawLocation(RawLocation) {
235+
// Allow ValueAsMetadata, empty MDTuple, DIArgList.
236+
assert(RawLocation && "unexpected null RawLocation");
237+
assert(isa<ValueAsMetadata>(RawLocation) || isa<DIArgList>(RawLocation) ||
238+
(isa<MDNode>(RawLocation) &&
239+
!cast<MDNode>(RawLocation)->getNumOperands()));
240+
}
241+
Metadata *getRawLocation() const { return RawLocation; }
242+
/// Get the locations corresponding to the variable referenced by the debug
243+
/// info intrinsic. Depending on the intrinsic, this could be the
244+
/// variable's value or its address.
245+
iterator_range<location_op_iterator> location_ops() const;
246+
Value *getVariableLocationOp(unsigned OpIdx) const;
247+
unsigned getNumVariableLocationOps() const {
248+
if (hasArgList())
249+
return cast<DIArgList>(getRawLocation())->getArgs().size();
250+
return 1;
251+
}
252+
bool hasArgList() const { return isa<DIArgList>(getRawLocation()); }
253+
bool isKillLocation(const DIExpression *Expression) const {
254+
return (getNumVariableLocationOps() == 0 && !Expression->isComplex()) ||
255+
any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); });
256+
}
257+
258+
friend bool operator==(const RawLocationWrapper &A,
259+
const RawLocationWrapper &B) {
260+
return A.RawLocation == B.RawLocation;
261+
}
262+
friend bool operator!=(const RawLocationWrapper &A,
263+
const RawLocationWrapper &B) {
264+
return !(A == B);
265+
}
266+
friend bool operator>(const RawLocationWrapper &A,
267+
const RawLocationWrapper &B) {
268+
return A.RawLocation > B.RawLocation;
269+
}
270+
friend bool operator>=(const RawLocationWrapper &A,
271+
const RawLocationWrapper &B) {
272+
return A.RawLocation >= B.RawLocation;
273+
}
274+
friend bool operator<(const RawLocationWrapper &A,
275+
const RawLocationWrapper &B) {
276+
return A.RawLocation < B.RawLocation;
277+
}
278+
friend bool operator<=(const RawLocationWrapper &A,
279+
const RawLocationWrapper &B) {
280+
return A.RawLocation <= B.RawLocation;
281+
}
282+
};
229283

284+
/// This is the common base class for debug info intrinsics for variables.
285+
class DbgVariableIntrinsic : public DbgInfoIntrinsic {
286+
public:
230287
/// Get the locations corresponding to the variable referenced by the debug
231288
/// info intrinsic. Depending on the intrinsic, this could be the
232289
/// variable's value or its address.
@@ -251,12 +308,10 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
251308
}
252309

253310
unsigned getNumVariableLocationOps() const {
254-
if (hasArgList())
255-
return cast<DIArgList>(getRawLocation())->getArgs().size();
256-
return 1;
311+
return getWrappedLocation().getNumVariableLocationOps();
257312
}
258313

259-
bool hasArgList() const { return isa<DIArgList>(getRawLocation()); }
314+
bool hasArgList() const { return getWrappedLocation().hasArgList(); }
260315

261316
/// Does this describe the address of a local variable. True for dbg.declare,
262317
/// but not dbg.value, which describes its value, or dbg.assign, which
@@ -278,9 +333,7 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
278333
}
279334

280335
bool isKillLocation() const {
281-
return (getNumVariableLocationOps() == 0 &&
282-
!getExpression()->isComplex()) ||
283-
any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); });
336+
return getWrappedLocation().isKillLocation(getExpression());
284337
}
285338

286339
DILocalVariable *getVariable() const {
@@ -295,6 +348,10 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
295348
return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();
296349
}
297350

351+
RawLocationWrapper getWrappedLocation() const {
352+
return RawLocationWrapper(getRawLocation());
353+
}
354+
298355
Metadata *getRawVariable() const {
299356
return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();
300357
}

llvm/lib/IR/IntrinsicInst.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,9 @@ bool IntrinsicInst::mayLowerToFunctionCall(Intrinsic::ID IID) {
7171
/// intrinsics for variables.
7272
///
7373

74-
iterator_range<DbgVariableIntrinsic::location_op_iterator>
75-
DbgVariableIntrinsic::location_ops() const {
76-
auto *MD = getRawLocation();
74+
iterator_range<location_op_iterator> RawLocationWrapper::location_ops() const {
75+
Metadata *MD = getRawLocation();
7776
assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
78-
7977
// If operand is ValueAsMetadata, return a range over just that operand.
8078
if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
8179
return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};
@@ -89,8 +87,17 @@ DbgVariableIntrinsic::location_ops() const {
8987
location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};
9088
}
9189

90+
iterator_range<location_op_iterator>
91+
DbgVariableIntrinsic::location_ops() const {
92+
return getWrappedLocation().location_ops();
93+
}
94+
9295
Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {
93-
auto *MD = getRawLocation();
96+
return getWrappedLocation().getVariableLocationOp(OpIdx);
97+
}
98+
99+
Value *RawLocationWrapper::getVariableLocationOp(unsigned OpIdx) const {
100+
Metadata *MD = getRawLocation();
94101
assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
95102
if (auto *AL = dyn_cast<DIArgList>(MD))
96103
return AL->getArgs()[OpIdx]->getValue();

0 commit comments

Comments
 (0)