Skip to content

[RemoveDIs][DebugInfo] Add DPVAssign variant of DPValue #77912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 55 additions & 11 deletions llvm/include/llvm/IR/DebugProgramInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class BasicBlock;
class MDNode;
class Module;
class DbgVariableIntrinsic;
class DIAssignID;
class DPMarker;
class DPValue;
class raw_ostream;
Expand All @@ -83,6 +84,7 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
DILocalVariable *Variable;
DIExpression *Expression;
DebugLoc DbgLoc;
DIExpression *AddressExpression;

public:
void deleteInstr();
Expand All @@ -102,6 +104,7 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
enum class LocationType {
Declare,
Value,
Assign,

End, ///< Marks the end of the concrete types.
Any, ///< To indicate all LocationTypes in searches.
Expand All @@ -122,6 +125,21 @@ class DPValue : public ilist_node<DPValue>, private DebugValueUser {
/// assigning \p Location to the DV / Expr / DI variable.
DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr,
const DILocation *DI, LocationType Type = LocationType::Value);
DPValue(Metadata *Value, DILocalVariable *Variable, DIExpression *Expression,
DIAssignID *AssignID, Metadata *Address,
DIExpression *AddressExpression, const DILocation *DI);

static DPValue *createDPVAssign(Value *Val, DILocalVariable *Variable,
DIExpression *Expression,
DIAssignID *AssignID, Value *Address,
DIExpression *AddressExpression,
const DILocation *DI);
static DPValue *createLinkedDPVAssign(Instruction *LinkedInstr, Value *Val,
DILocalVariable *Variable,
DIExpression *Expression,
Value *Address,
DIExpression *AddressExpression,
const DILocation *DI);

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

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

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

DIExpression *getExpression() const { return Expression; }

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

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

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

bool isEquivalentTo(const DPValue &Other) {
return std::tie(Type, DebugValue, Variable, Expression, DbgLoc) ==
std::tie(Other.Type, Other.DebugValue, Other.Variable,
return std::tie(Type, DebugValues, Variable, Expression, DbgLoc) ==
std::tie(Other.Type, Other.DebugValues, Other.Variable,
Other.Expression, Other.DbgLoc);
}
// Matches the definition of the Instruction version, equivalent to above but
// without checking DbgLoc.
bool isIdenticalToWhenDefined(const DPValue &Other) {
return std::tie(Type, DebugValue, Variable, Expression) ==
std::tie(Other.Type, Other.DebugValue, Other.Variable,
return std::tie(Type, DebugValues, Variable, Expression) ==
std::tie(Other.Type, Other.DebugValues, Other.Variable,
Other.Expression);
}

/// @name DbgAssign Methods
/// @{
bool isDbgAssign() const { return getType() == LocationType::Assign; }

Value *getAddress() const;
Metadata *getRawAddress() const {
return isDbgAssign() ? DebugValues[1] : DebugValues[0];
}
Metadata *getRawAssignID() const { return DebugValues[2]; }
DIAssignID *getAssignID() const;
DIExpression *getAddressExpression() const { return AddressExpression; }
void setAddressExpression(DIExpression *NewExpr) {
AddressExpression = NewExpr;
}
void setAssignId(DIAssignID *New);
void setAddress(Value *V) { resetDebugValue(1, ValueAsMetadata::get(V)); }
/// Kill the address component.
void setKillAddress();
/// Check whether this kills the address component. This doesn't take into
/// account the position of the intrinsic, therefore a returned value of false
/// does not guarentee the address is a valid location for the variable at the
/// intrinsic's position in IR.
bool isKillAddress() const;

/// @}

DPValue *clone() const;
/// Convert this DPValue back into a dbg.value intrinsic.
/// \p InsertBefore Optional position to insert this intrinsic.
/// \returns A new dbg.value intrinsic representiung this DPValue.
DbgVariableIntrinsic *createDebugIntrinsic(Module *M,
Instruction *InsertBefore) const;
/// Handle changes to the location of the Value(s) that we refer to happening
/// "under our feet".
void handleChangedLocation(Metadata *NewLocation);

void setMarker(DPMarker *M) { Marker = M; }

DPMarker *getMarker() { return Marker; }
Expand Down
76 changes: 48 additions & 28 deletions llvm/include/llvm/IR/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,67 +211,87 @@ class MetadataAsValue : public Value {
/// lookup and callback handling.
class DebugValueUser {
protected:
Metadata *DebugValue;
// Capacity to store 3 debug values.
// TODO: Not all DebugValueUser instances need all 3 elements, if we
// restructure the DPValue class then we can template parameterize this array
// size.
std::array<Metadata *, 3> DebugValues;

ArrayRef<Metadata *> getDebugValues() const { return DebugValues; }

public:
DPValue *getUser();
const DPValue *getUser() const;
void handleChangedValue(Metadata *NewDebugValue);
/// To be called by ReplaceableMetadataImpl::replaceAllUsesWith, where `Old`
/// is a pointer to one of the pointers in `DebugValues` (so should be type
/// Metadata**), and `NewDebugValue` is the new Metadata* that is replacing
/// *Old.
/// For manually replacing elements of DebugValues,
/// `resetDebugValue(Idx, NewDebugValue)` should be used instead.
void handleChangedValue(void *Old, Metadata *NewDebugValue);
DebugValueUser() = default;
explicit DebugValueUser(Metadata *DebugValue) : DebugValue(DebugValue) {
trackDebugValue();
explicit DebugValueUser(std::array<Metadata *, 3> DebugValues)
: DebugValues(DebugValues) {
trackDebugValues();
}

DebugValueUser(DebugValueUser &&X) : DebugValue(X.DebugValue) {
retrackDebugValue(X);
DebugValueUser(DebugValueUser &&X) {
DebugValues = X.DebugValues;
retrackDebugValues(X);
}
DebugValueUser(const DebugValueUser &X) : DebugValue(X.DebugValue) {
trackDebugValue();
DebugValueUser(const DebugValueUser &X) {
DebugValues = X.DebugValues;
trackDebugValues();
}

DebugValueUser &operator=(DebugValueUser &&X) {
if (&X == this)
return *this;

untrackDebugValue();
DebugValue = X.DebugValue;
retrackDebugValue(X);
untrackDebugValues();
DebugValues = X.DebugValues;
retrackDebugValues(X);
return *this;
}

DebugValueUser &operator=(const DebugValueUser &X) {
if (&X == this)
return *this;

untrackDebugValue();
DebugValue = X.DebugValue;
trackDebugValue();
untrackDebugValues();
DebugValues = X.DebugValues;
trackDebugValues();
return *this;
}

~DebugValueUser() { untrackDebugValue(); }
~DebugValueUser() { untrackDebugValues(); }

void resetDebugValue() {
untrackDebugValue();
DebugValue = nullptr;
void resetDebugValues() {
untrackDebugValues();
DebugValues.fill(nullptr);
}
void resetDebugValue(Metadata *DebugValue) {
untrackDebugValue();
this->DebugValue = DebugValue;
trackDebugValue();

void resetDebugValue(size_t Idx, Metadata *DebugValue) {
assert(Idx < 3 && "Invalid debug value index.");
untrackDebugValue(Idx);
DebugValues[Idx] = DebugValue;
trackDebugValue(Idx);
}

bool operator==(const DebugValueUser &X) const {
return DebugValue == X.DebugValue;
return DebugValues == X.DebugValues;
}
bool operator!=(const DebugValueUser &X) const {
return DebugValue != X.DebugValue;
return DebugValues != X.DebugValues;
}

private:
void trackDebugValue();
void untrackDebugValue();
void retrackDebugValue(DebugValueUser &X);
void trackDebugValue(size_t Idx);
void trackDebugValues();

void untrackDebugValue(size_t Idx);
void untrackDebugValues();

void retrackDebugValues(DebugValueUser &X);
};

/// API for tracking metadata references through RAUW and deletion.
Expand Down
28 changes: 27 additions & 1 deletion llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,9 @@ void SlotTracker::processFunctionMetadata(const Function &F) {
void SlotTracker::processDPValueMetadata(const DPValue &DPV) {
CreateMetadataSlot(DPV.getVariable());
CreateMetadataSlot(DPV.getDebugLoc());
if (DPV.isDbgAssign()) {
CreateMetadataSlot(DPV.getAssignID());
}
}

void SlotTracker::processInstructionMetadata(const Instruction &I) {
Expand Down Expand Up @@ -4571,14 +4574,37 @@ void AssemblyWriter::printDPMarker(const DPMarker &Marker) {
void AssemblyWriter::printDPValue(const DPValue &Value) {
// There's no formal representation of a DPValue -- print purely as a
// debugging aid.
Out << " DPValue { ";
Out << " DPValue ";

switch (Value.getType()) {
case DPValue::LocationType::Value:
Out << "value";
break;
case DPValue::LocationType::Declare:
Out << "declare";
break;
case DPValue::LocationType::Assign:
Out << "assign";
break;
default:
llvm_unreachable("Tried to print a DPValue with an invalid LocationType!");
}
Out << " { ";
auto WriterCtx = getContext();
WriteAsOperandInternal(Out, Value.getRawLocation(), WriterCtx, true);
Out << ", ";
WriteAsOperandInternal(Out, Value.getVariable(), WriterCtx, true);
Out << ", ";
WriteAsOperandInternal(Out, Value.getExpression(), WriterCtx, true);
Out << ", ";
if (Value.isDbgAssign()) {
WriteAsOperandInternal(Out, Value.getAssignID(), WriterCtx, true);
Out << ", ";
WriteAsOperandInternal(Out, Value.getRawAddress(), WriterCtx, true);
Out << ", ";
WriteAsOperandInternal(Out, Value.getAddressExpression(), WriterCtx, true);
Out << ", ";
}
WriteAsOperandInternal(Out, Value.getDebugLoc().get(), WriterCtx, true);
Out << " marker @" << Value.getMarker();
Out << " }";
Expand Down
Loading