Skip to content

Commit d499df0

Browse files
authored
[RemoveDIs][DebugInfo] Add DPVAssign variant of DPValue (#77912)
This implements the DbgAssignIntrinsic class as a variant of DPValues - unfortunately this involves increasing the size of the `DebugValueUser` storage by 3x, but this is necessary to enable assigns to be represented, and can be offset in a future patch by splitting DPValue into subclasses such that each variant can store only the fields it needs. This patch does not actually create DPVAssigns in any case; future patches will handle this variant in all cases where generic DPValue handling does not. This patch also does not implement tracking support for DIAssignIDs, which is necessary to find DPVAssigns that reference a given DIAssignID; that is added in a subsequent patch.
1 parent c20811b commit d499df0

File tree

5 files changed

+266
-71
lines changed

5 files changed

+266
-71
lines changed

llvm/include/llvm/IR/DebugProgramInstruction.h

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class BasicBlock;
6161
class MDNode;
6262
class Module;
6363
class DbgVariableIntrinsic;
64+
class DIAssignID;
6465
class DPMarker;
6566
class DPValue;
6667
class raw_ostream;
@@ -83,6 +84,7 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
8384
DILocalVariable *Variable;
8485
DIExpression *Expression;
8586
DebugLoc DbgLoc;
87+
DIExpression *AddressExpression;
8688

8789
public:
8890
void deleteInstr();
@@ -102,6 +104,7 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
102104
enum class LocationType {
103105
Declare,
104106
Value,
107+
Assign,
105108

106109
End, ///< Marks the end of the concrete types.
107110
Any, ///< To indicate all LocationTypes in searches.
@@ -122,6 +125,21 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
122125
/// assigning \p Location to the DV / Expr / DI variable.
123126
DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr,
124127
const DILocation *DI, LocationType Type = LocationType::Value);
128+
DPValue(Metadata *Value, DILocalVariable *Variable, DIExpression *Expression,
129+
DIAssignID *AssignID, Metadata *Address,
130+
DIExpression *AddressExpression, const DILocation *DI);
131+
132+
static DPValue *createDPVAssign(Value *Val, DILocalVariable *Variable,
133+
DIExpression *Expression,
134+
DIAssignID *AssignID, Value *Address,
135+
DIExpression *AddressExpression,
136+
const DILocation *DI);
137+
static DPValue *createLinkedDPVAssign(Instruction *LinkedInstr, Value *Val,
138+
DILocalVariable *Variable,
139+
DIExpression *Expression,
140+
Value *Address,
141+
DIExpression *AddressExpression,
142+
const DILocation *DI);
125143

126144
static DPValue *createDPValue(Value *Location, DILocalVariable *DV,
127145
DIExpression *Expr, const DILocation *DI);
@@ -213,7 +231,7 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
213231

214232
/// Does this describe the address of a local variable. True for dbg.addr
215233
/// and dbg.declare, but not dbg.value, which describes its value.
216-
bool isAddressOfVariable() const { return Type != LocationType::Value; }
234+
bool isAddressOfVariable() const { return Type == LocationType::Declare; }
217235
LocationType getType() const { return Type; }
218236

219237
DebugLoc getDebugLoc() const { return DbgLoc; }
@@ -226,7 +244,11 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
226244

227245
DIExpression *getExpression() const { return Expression; }
228246

229-
Metadata *getRawLocation() const { return DebugValue; }
247+
/// Returns the metadata operand for the first location description. i.e.,
248+
/// dbg intrinsic dbg.value,declare operand and dbg.assign 1st location
249+
/// operand (the "value componenet"). Note the operand (singular) may be
250+
/// a DIArgList which is a list of values.
251+
Metadata *getRawLocation() const { return DebugValues[0]; }
230252

231253
Value *getValue(unsigned OpIdx = 0) const {
232254
return getVariableLocationOp(OpIdx);
@@ -240,36 +262,58 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
240262
(isa<ValueAsMetadata>(NewLocation) || isa<DIArgList>(NewLocation) ||
241263
isa<MDNode>(NewLocation)) &&
242264
"Location for a DPValue must be either ValueAsMetadata or DIArgList");
243-
resetDebugValue(NewLocation);
265+
resetDebugValue(0, NewLocation);
244266
}
245267

246268
/// Get the size (in bits) of the variable, or fragment of the variable that
247269
/// is described.
248270
std::optional<uint64_t> getFragmentSizeInBits() const;
249271

250272
bool isEquivalentTo(const DPValue &Other) {
251-
return std::tie(Type, DebugValue, Variable, Expression, DbgLoc) ==
252-
std::tie(Other.Type, Other.DebugValue, Other.Variable,
273+
return std::tie(Type, DebugValues, Variable, Expression, DbgLoc) ==
274+
std::tie(Other.Type, Other.DebugValues, Other.Variable,
253275
Other.Expression, Other.DbgLoc);
254276
}
255277
// Matches the definition of the Instruction version, equivalent to above but
256278
// without checking DbgLoc.
257279
bool isIdenticalToWhenDefined(const DPValue &Other) {
258-
return std::tie(Type, DebugValue, Variable, Expression) ==
259-
std::tie(Other.Type, Other.DebugValue, Other.Variable,
280+
return std::tie(Type, DebugValues, Variable, Expression) ==
281+
std::tie(Other.Type, Other.DebugValues, Other.Variable,
260282
Other.Expression);
261283
}
262284

285+
/// @name DbgAssign Methods
286+
/// @{
287+
bool isDbgAssign() const { return getType() == LocationType::Assign; }
288+
289+
Value *getAddress() const;
290+
Metadata *getRawAddress() const {
291+
return isDbgAssign() ? DebugValues[1] : DebugValues[0];
292+
}
293+
Metadata *getRawAssignID() const { return DebugValues[2]; }
294+
DIAssignID *getAssignID() const;
295+
DIExpression *getAddressExpression() const { return AddressExpression; }
296+
void setAddressExpression(DIExpression *NewExpr) {
297+
AddressExpression = NewExpr;
298+
}
299+
void setAssignId(DIAssignID *New);
300+
void setAddress(Value *V) { resetDebugValue(1, ValueAsMetadata::get(V)); }
301+
/// Kill the address component.
302+
void setKillAddress();
303+
/// Check whether this kills the address component. This doesn't take into
304+
/// account the position of the intrinsic, therefore a returned value of false
305+
/// does not guarentee the address is a valid location for the variable at the
306+
/// intrinsic's position in IR.
307+
bool isKillAddress() const;
308+
309+
/// @}
310+
263311
DPValue *clone() const;
264312
/// Convert this DPValue back into a dbg.value intrinsic.
265313
/// \p InsertBefore Optional position to insert this intrinsic.
266314
/// \returns A new dbg.value intrinsic representiung this DPValue.
267315
DbgVariableIntrinsic *createDebugIntrinsic(Module *M,
268316
Instruction *InsertBefore) const;
269-
/// Handle changes to the location of the Value(s) that we refer to happening
270-
/// "under our feet".
271-
void handleChangedLocation(Metadata *NewLocation);
272-
273317
void setMarker(DPMarker *M) { Marker = M; }
274318

275319
DPMarker *getMarker() { return Marker; }

llvm/include/llvm/IR/Metadata.h

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -211,67 +211,87 @@ class MetadataAsValue : public Value {
211211
/// lookup and callback handling.
212212
class DebugValueUser {
213213
protected:
214-
Metadata *DebugValue;
214+
// Capacity to store 3 debug values.
215+
// TODO: Not all DebugValueUser instances need all 3 elements, if we
216+
// restructure the DPValue class then we can template parameterize this array
217+
// size.
218+
std::array<Metadata *, 3> DebugValues;
219+
220+
ArrayRef<Metadata *> getDebugValues() const { return DebugValues; }
215221

216222
public:
217223
DPValue *getUser();
218224
const DPValue *getUser() const;
219-
void handleChangedValue(Metadata *NewDebugValue);
225+
/// To be called by ReplaceableMetadataImpl::replaceAllUsesWith, where `Old`
226+
/// is a pointer to one of the pointers in `DebugValues` (so should be type
227+
/// Metadata**), and `NewDebugValue` is the new Metadata* that is replacing
228+
/// *Old.
229+
/// For manually replacing elements of DebugValues,
230+
/// `resetDebugValue(Idx, NewDebugValue)` should be used instead.
231+
void handleChangedValue(void *Old, Metadata *NewDebugValue);
220232
DebugValueUser() = default;
221-
explicit DebugValueUser(Metadata *DebugValue) : DebugValue(DebugValue) {
222-
trackDebugValue();
233+
explicit DebugValueUser(std::array<Metadata *, 3> DebugValues)
234+
: DebugValues(DebugValues) {
235+
trackDebugValues();
223236
}
224-
225-
DebugValueUser(DebugValueUser &&X) : DebugValue(X.DebugValue) {
226-
retrackDebugValue(X);
237+
DebugValueUser(DebugValueUser &&X) {
238+
DebugValues = X.DebugValues;
239+
retrackDebugValues(X);
227240
}
228-
DebugValueUser(const DebugValueUser &X) : DebugValue(X.DebugValue) {
229-
trackDebugValue();
241+
DebugValueUser(const DebugValueUser &X) {
242+
DebugValues = X.DebugValues;
243+
trackDebugValues();
230244
}
231245

232246
DebugValueUser &operator=(DebugValueUser &&X) {
233247
if (&X == this)
234248
return *this;
235249

236-
untrackDebugValue();
237-
DebugValue = X.DebugValue;
238-
retrackDebugValue(X);
250+
untrackDebugValues();
251+
DebugValues = X.DebugValues;
252+
retrackDebugValues(X);
239253
return *this;
240254
}
241255

242256
DebugValueUser &operator=(const DebugValueUser &X) {
243257
if (&X == this)
244258
return *this;
245259

246-
untrackDebugValue();
247-
DebugValue = X.DebugValue;
248-
trackDebugValue();
260+
untrackDebugValues();
261+
DebugValues = X.DebugValues;
262+
trackDebugValues();
249263
return *this;
250264
}
251265

252-
~DebugValueUser() { untrackDebugValue(); }
266+
~DebugValueUser() { untrackDebugValues(); }
253267

254-
void resetDebugValue() {
255-
untrackDebugValue();
256-
DebugValue = nullptr;
268+
void resetDebugValues() {
269+
untrackDebugValues();
270+
DebugValues.fill(nullptr);
257271
}
258-
void resetDebugValue(Metadata *DebugValue) {
259-
untrackDebugValue();
260-
this->DebugValue = DebugValue;
261-
trackDebugValue();
272+
273+
void resetDebugValue(size_t Idx, Metadata *DebugValue) {
274+
assert(Idx < 3 && "Invalid debug value index.");
275+
untrackDebugValue(Idx);
276+
DebugValues[Idx] = DebugValue;
277+
trackDebugValue(Idx);
262278
}
263279

264280
bool operator==(const DebugValueUser &X) const {
265-
return DebugValue == X.DebugValue;
281+
return DebugValues == X.DebugValues;
266282
}
267283
bool operator!=(const DebugValueUser &X) const {
268-
return DebugValue != X.DebugValue;
284+
return DebugValues != X.DebugValues;
269285
}
270286

271287
private:
272-
void trackDebugValue();
273-
void untrackDebugValue();
274-
void retrackDebugValue(DebugValueUser &X);
288+
void trackDebugValue(size_t Idx);
289+
void trackDebugValues();
290+
291+
void untrackDebugValue(size_t Idx);
292+
void untrackDebugValues();
293+
294+
void retrackDebugValues(DebugValueUser &X);
275295
};
276296

277297
/// API for tracking metadata references through RAUW and deletion.

llvm/lib/IR/AsmWriter.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,9 @@ void SlotTracker::processFunctionMetadata(const Function &F) {
11401140
void SlotTracker::processDPValueMetadata(const DPValue &DPV) {
11411141
CreateMetadataSlot(DPV.getVariable());
11421142
CreateMetadataSlot(DPV.getDebugLoc());
1143+
if (DPV.isDbgAssign()) {
1144+
CreateMetadataSlot(DPV.getAssignID());
1145+
}
11431146
}
11441147

11451148
void SlotTracker::processInstructionMetadata(const Instruction &I) {
@@ -4571,14 +4574,37 @@ void AssemblyWriter::printDPMarker(const DPMarker &Marker) {
45714574
void AssemblyWriter::printDPValue(const DPValue &Value) {
45724575
// There's no formal representation of a DPValue -- print purely as a
45734576
// debugging aid.
4574-
Out << " DPValue { ";
4577+
Out << " DPValue ";
4578+
4579+
switch (Value.getType()) {
4580+
case DPValue::LocationType::Value:
4581+
Out << "value";
4582+
break;
4583+
case DPValue::LocationType::Declare:
4584+
Out << "declare";
4585+
break;
4586+
case DPValue::LocationType::Assign:
4587+
Out << "assign";
4588+
break;
4589+
default:
4590+
llvm_unreachable("Tried to print a DPValue with an invalid LocationType!");
4591+
}
4592+
Out << " { ";
45754593
auto WriterCtx = getContext();
45764594
WriteAsOperandInternal(Out, Value.getRawLocation(), WriterCtx, true);
45774595
Out << ", ";
45784596
WriteAsOperandInternal(Out, Value.getVariable(), WriterCtx, true);
45794597
Out << ", ";
45804598
WriteAsOperandInternal(Out, Value.getExpression(), WriterCtx, true);
45814599
Out << ", ";
4600+
if (Value.isDbgAssign()) {
4601+
WriteAsOperandInternal(Out, Value.getAssignID(), WriterCtx, true);
4602+
Out << ", ";
4603+
WriteAsOperandInternal(Out, Value.getRawAddress(), WriterCtx, true);
4604+
Out << ", ";
4605+
WriteAsOperandInternal(Out, Value.getAddressExpression(), WriterCtx, true);
4606+
Out << ", ";
4607+
}
45824608
WriteAsOperandInternal(Out, Value.getDebugLoc().get(), WriterCtx, true);
45834609
Out << " marker @" << Value.getMarker();
45844610
Out << " }";

0 commit comments

Comments
 (0)