From 2b08de43506350ec4bd083e320a1913efe76684a Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 16 Jan 2024 09:27:02 +0000 Subject: [PATCH] [RemoveDIs][DebugInfo][NFC] Add Instruction and convenience functions to DPValue (#77896) This patch adds a set of functions to the DPValue class that conveniently perform some common operations, and some that replicate existing functions on `DbgVariableIntrinsic` and its subclasses. --- .../include/llvm/IR/DebugProgramInstruction.h | 51 ++++++++++++- llvm/lib/IR/DebugProgramInstruction.cpp | 74 +++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index 8230070343e0c1..e089475cb0e7f3 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -47,10 +47,12 @@ #ifndef LLVM_IR_DEBUGPROGRAMINSTRUCTION_H #define LLVM_IR_DEBUGPROGRAMINSTRUCTION_H -#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/SymbolTableListTraits.h" namespace llvm { @@ -91,6 +93,9 @@ class DPValue : public ilist_node, private DebugValueUser { void removeFromParent(); void eraseFromParent(); + DPValue *getNextNode() { return &*std::next(getIterator()); } + DPValue *getPrevNode() { return &*std::prev(getIterator()); } + using self_iterator = simple_ilist::iterator; using const_self_iterator = simple_ilist::const_iterator; @@ -118,6 +123,17 @@ class DPValue : public ilist_node, private DebugValueUser { DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI, LocationType Type = LocationType::Value); + static DPValue *createDPValue(Value *Location, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI); + static DPValue *createDPValue(Value *Location, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + DPValue &InsertBefore); + static DPValue *createDPVDeclare(Value *Address, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI); + static DPValue *createDPVDeclare(Value *Address, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + DPValue &InsertBefore); + /// Iterator for ValueAsMetadata that internally uses direct pointer iteration /// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the /// ValueAsMetadata . @@ -166,6 +182,9 @@ class DPValue : public ilist_node, private DebugValueUser { } }; + bool isDbgDeclare() { return Type == LocationType::Declare; } + bool isDbgValue() { return Type == LocationType::Value; } + /// Get the locations corresponding to the variable referenced by the debug /// info intrinsic. Depending on the intrinsic, this could be the /// variable's value or its address. @@ -209,6 +228,10 @@ class DPValue : public ilist_node, private DebugValueUser { Metadata *getRawLocation() const { return DebugValue; } + Value *getValue(unsigned OpIdx = 0) const { + return getVariableLocationOp(OpIdx); + } + /// Use of this should generally be avoided; instead, /// replaceVariableLocationOp and addVariableLocationOps should be used where /// possible to avoid creating invalid state. @@ -224,6 +247,19 @@ class DPValue : public ilist_node, private DebugValueUser { /// is described. std::optional getFragmentSizeInBits() const; + bool isEquivalentTo(const DPValue &Other) { + return std::tie(Type, DebugValue, Variable, Expression, DbgLoc) == + std::tie(Other.Type, Other.DebugValue, 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, + Other.Expression); + } + DPValue *clone() const; /// Convert this DPValue back into a dbg.value intrinsic. /// \p InsertBefore Optional position to insert this intrinsic. @@ -251,6 +287,13 @@ class DPValue : public ilist_node, private DebugValueUser { LLVMContext &getContext(); const LLVMContext &getContext() const; + /// Insert this DPValue prior to \p InsertBefore. Must not be called if this + /// is already contained in a DPMarker. + void insertBefore(DPValue *InsertBefore); + void insertAfter(DPValue *InsertAfter); + void moveBefore(DPValue *MoveBefore); + void moveAfter(DPValue *MoveAfter); + void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; }; @@ -309,6 +352,8 @@ class DPMarker { /// Produce a range over all the DPValues in this Marker. iterator_range::iterator> getDbgValueRange(); + iterator_range::const_iterator> + getDbgValueRange() const; /// Transfer any DPValues from \p Src into this DPMarker. If \p InsertAtHead /// is true, place them before existing DPValues, otherwise afterwards. void absorbDebugValues(DPMarker &Src, bool InsertAtHead); @@ -320,6 +365,10 @@ class DPMarker { /// Insert a DPValue into this DPMarker, at the end of the list. If /// \p InsertAtHead is true, at the start. void insertDPValue(DPValue *New, bool InsertAtHead); + /// Insert a DPValue prior to a DPValue contained within this marker. + void insertDPValue(DPValue *New, DPValue *InsertBefore); + /// Insert a DPValue after a DPValue contained within this marker. + void insertDPValueAfter(DPValue *New, DPValue *InsertAfter); /// Clone all DPMarkers from \p From into this marker. There are numerous /// options to customise the source/destination, due to gnarliness, see class /// comment. diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 7b709a2de0335f..11ac118de389de 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -41,6 +41,34 @@ DPValue::DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, void DPValue::deleteInstr() { delete this; } +DPValue *DPValue::createDPValue(Value *Location, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI) { + return new DPValue(ValueAsMetadata::get(Location), DV, Expr, DI, + LocationType::Value); +} + +DPValue *DPValue::createDPValue(Value *Location, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + DPValue &InsertBefore) { + auto *NewDPValue = createDPValue(Location, DV, Expr, DI); + NewDPValue->insertBefore(&InsertBefore); + return NewDPValue; +} + +DPValue *DPValue::createDPVDeclare(Value *Address, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI) { + return new DPValue(ValueAsMetadata::get(Address), DV, Expr, DI, + LocationType::Declare); +} + +DPValue *DPValue::createDPVDeclare(Value *Address, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + DPValue &InsertBefore) { + auto *NewDPVDeclare = createDPVDeclare(Address, DV, Expr, DI); + NewDPVDeclare->insertBefore(&InsertBefore); + return NewDPVDeclare; +} + iterator_range DPValue::location_ops() const { auto *MD = getRawLocation(); // If a Value has been deleted, the "location" for this DPValue will be @@ -249,6 +277,35 @@ const LLVMContext &DPValue::getContext() const { return getBlock()->getContext(); } +void DPValue::insertBefore(DPValue *InsertBefore) { + assert(!getMarker() && + "Cannot insert a DPValue that is already has a DPMarker!"); + assert(InsertBefore->getMarker() && + "Cannot insert a DPValue before a DPValue that does not have a " + "DPMarker!"); + InsertBefore->getMarker()->insertDPValue(this, InsertBefore); +} +void DPValue::insertAfter(DPValue *InsertAfter) { + assert(!getMarker() && + "Cannot insert a DPValue that is already has a DPMarker!"); + assert(InsertAfter->getMarker() && + "Cannot insert a DPValue after a DPValue that does not have a " + "DPMarker!"); + InsertAfter->getMarker()->insertDPValueAfter(this, InsertAfter); +} +void DPValue::moveBefore(DPValue *MoveBefore) { + assert(getMarker() && + "Canot move a DPValue that does not currently have a DPMarker!"); + removeFromParent(); + insertBefore(MoveBefore); +} +void DPValue::moveAfter(DPValue *MoveAfter) { + assert(getMarker() && + "Canot move a DPValue that does not currently have a DPMarker!"); + removeFromParent(); + insertAfter(MoveAfter); +} + /////////////////////////////////////////////////////////////////////////////// // An empty, global, DPMarker for the purpose of describing empty ranges of @@ -313,9 +370,14 @@ void DPMarker::eraseFromParent() { iterator_range DPMarker::getDbgValueRange() { return make_range(StoredDPValues.begin(), StoredDPValues.end()); } +iterator_range +DPMarker::getDbgValueRange() const { + return make_range(StoredDPValues.begin(), StoredDPValues.end()); +} void DPValue::removeFromParent() { getMarker()->StoredDPValues.erase(getIterator()); + Marker = nullptr; } void DPValue::eraseFromParent() { @@ -328,6 +390,18 @@ void DPMarker::insertDPValue(DPValue *New, bool InsertAtHead) { StoredDPValues.insert(It, *New); New->setMarker(this); } +void DPMarker::insertDPValue(DPValue *New, DPValue *InsertBefore) { + assert(InsertBefore->getMarker() == this && + "DPValue 'InsertBefore' must be contained in this DPMarker!"); + StoredDPValues.insert(InsertBefore->getIterator(), *New); + New->setMarker(this); +} +void DPMarker::insertDPValueAfter(DPValue *New, DPValue *InsertAfter) { + assert(InsertAfter->getMarker() == this && + "DPValue 'InsertAfter' must be contained in this DPMarker!"); + StoredDPValues.insert(++(InsertAfter->getIterator()), *New); + New->setMarker(this); +} void DPMarker::absorbDebugValues(DPMarker &Src, bool InsertAtHead) { auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end();