aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h263
1 files changed, 178 insertions, 85 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 1af4b643eb17..452485b632c4 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -17,7 +17,6 @@
#include "DebugLocEntry.h"
#include "DebugLocStream.h"
#include "DwarfFile.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
@@ -41,6 +40,7 @@
#include <limits>
#include <memory>
#include <utility>
+#include <variant>
#include <vector>
namespace llvm {
@@ -100,90 +100,154 @@ public:
}
};
-//===----------------------------------------------------------------------===//
-/// This class is used to track local variable information.
-///
-/// Variables can be created from allocas, in which case they're generated from
-/// the MMI table. Such variables can have multiple expressions and frame
-/// indices.
-///
-/// Variables can be created from \c DBG_VALUE instructions. Those whose
-/// location changes over time use \a DebugLocListIndex, while those with a
-/// single location use \a ValueLoc and (optionally) a single entry of \a Expr.
-///
-/// Variables that have been optimized out use none of these fields.
-class DbgVariable : public DbgEntity {
- /// Index of the entry list in DebugLocs.
- unsigned DebugLocListIndex = ~0u;
- /// DW_OP_LLVM_tag_offset value from DebugLocs.
- std::optional<uint8_t> DebugLocListTagOffset;
+class DbgVariable;
- /// Single value location description.
- std::unique_ptr<DbgValueLoc> ValueLoc = nullptr;
+bool operator<(const struct FrameIndexExpr &LHS,
+ const struct FrameIndexExpr &RHS);
+bool operator<(const struct EntryValueInfo &LHS,
+ const struct EntryValueInfo &RHS);
- struct FrameIndexExpr {
- int FI;
- const DIExpression *Expr;
- };
- mutable SmallVector<FrameIndexExpr, 1>
- FrameIndexExprs; /// Frame index + expression.
+/// Proxy for one MMI entry.
+struct FrameIndexExpr {
+ int FI;
+ const DIExpression *Expr;
+
+ /// Operator enabling sorting based on fragment offset.
+ friend bool operator<(const FrameIndexExpr &LHS, const FrameIndexExpr &RHS);
+};
+
+/// Represents an entry-value location, or a fragment of one.
+struct EntryValueInfo {
+ MCRegister Reg;
+ const DIExpression &Expr;
+
+ /// Operator enabling sorting based on fragment offset.
+ friend bool operator<(const EntryValueInfo &LHS, const EntryValueInfo &RHS);
+};
+
+// Namespace for alternatives of a DbgVariable.
+namespace Loc {
+/// Single value location description.
+class Single {
+ std::unique_ptr<DbgValueLoc> ValueLoc;
+ const DIExpression *Expr;
public:
- /// Construct a DbgVariable.
- ///
- /// Creates a variable without any DW_AT_location. Call \a initializeMMI()
- /// for MMI entries, or \a initializeDbgValue() for DBG_VALUE instructions.
- DbgVariable(const DILocalVariable *V, const DILocation *IA)
- : DbgEntity(V, IA, DbgVariableKind) {}
+ explicit Single(DbgValueLoc ValueLoc);
+ explicit Single(const MachineInstr *DbgValue);
+ const DbgValueLoc &getValueLoc() const { return *ValueLoc; }
+ const DIExpression *getExpr() const { return Expr; }
+};
+/// Multi-value location description.
+class Multi {
+ /// Index of the entry list in DebugLocs.
+ unsigned DebugLocListIndex;
+ /// DW_OP_LLVM_tag_offset value from DebugLocs.
+ std::optional<uint8_t> DebugLocListTagOffset;
- /// Initialize from the MMI table.
- void initializeMMI(const DIExpression *E, int FI) {
- assert(FrameIndexExprs.empty() && "Already initialized?");
- assert(!ValueLoc.get() && "Already initialized?");
+public:
+ explicit Multi(unsigned DebugLocListIndex,
+ std::optional<uint8_t> DebugLocListTagOffset)
+ : DebugLocListIndex(DebugLocListIndex),
+ DebugLocListTagOffset(DebugLocListTagOffset) {}
+ unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
+ std::optional<uint8_t> getDebugLocListTagOffset() const {
+ return DebugLocListTagOffset;
+ }
+};
+/// Single location defined by (potentially multiple) MMI entries.
+struct MMI {
+ std::set<FrameIndexExpr> FrameIndexExprs;
+public:
+ explicit MMI(const DIExpression *E, int FI) : FrameIndexExprs({{FI, E}}) {
assert((!E || E->isValid()) && "Expected valid expression");
assert(FI != std::numeric_limits<int>::max() && "Expected valid index");
-
- FrameIndexExprs.push_back({FI, E});
}
+ void addFrameIndexExpr(const DIExpression *Expr, int FI);
+ /// Get the FI entries, sorted by fragment offset.
+ const std::set<FrameIndexExpr> &getFrameIndexExprs() const;
+};
+/// Single location defined by (potentially multiple) EntryValueInfo.
+struct EntryValue {
+ std::set<EntryValueInfo> EntryValues;
+ explicit EntryValue(MCRegister Reg, const DIExpression &Expr) {
+ addExpr(Reg, Expr);
+ };
+ // Add the pair Reg, Expr to the list of entry values describing the variable.
+ // If multiple expressions are added, it is the callers responsibility to
+ // ensure they are all non-overlapping fragments.
+ void addExpr(MCRegister Reg, const DIExpression &Expr) {
+ std::optional<const DIExpression *> NonVariadicExpr =
+ DIExpression::convertToNonVariadicExpression(&Expr);
+ assert(NonVariadicExpr && *NonVariadicExpr);
+
+ EntryValues.insert({Reg, **NonVariadicExpr});
+ }
+};
+/// Alias for the std::variant specialization base class of DbgVariable.
+using Variant = std::variant<std::monostate, Loc::Single, Loc::Multi, Loc::MMI,
+ Loc::EntryValue>;
+} // namespace Loc
- // Initialize variable's location.
- void initializeDbgValue(DbgValueLoc Value) {
- assert(FrameIndexExprs.empty() && "Already initialized?");
- assert(!ValueLoc && "Already initialized?");
- assert(!Value.getExpression()->isFragment() && "Fragments not supported.");
+//===----------------------------------------------------------------------===//
+/// This class is used to track local variable information.
+///
+/// Variables that have been optimized out hold the \c monostate alternative.
+/// This is not distinguished from the case of a constructed \c DbgVariable
+/// which has not be initialized yet.
+///
+/// Variables can be created from allocas, in which case they're generated from
+/// the MMI table. Such variables hold the \c Loc::MMI alternative which can
+/// have multiple expressions and frame indices.
+///
+/// Variables can be created from the entry value of registers, in which case
+/// they're generated from the MMI table. Such variables hold the \c
+/// EntryValueLoc alternative which can either have a single expression or
+/// multiple *fragment* expressions.
+///
+/// Variables can be created from \c DBG_VALUE instructions. Those whose
+/// location changes over time hold a \c Loc::Multi alternative which uses \c
+/// DebugLocListIndex and (optionally) \c DebugLocListTagOffset, while those
+/// with a single location hold a \c Loc::Single alternative which use \c
+/// ValueLoc and (optionally) a single \c Expr.
+class DbgVariable : public DbgEntity, public Loc::Variant {
- ValueLoc = std::make_unique<DbgValueLoc>(Value);
- if (auto *E = ValueLoc->getExpression())
- if (E->getNumElements())
- FrameIndexExprs.push_back({0, E});
+public:
+ /// To workaround P2162R0 https://github.com/cplusplus/papers/issues/873 the
+ /// base class subobject needs to be passed directly to std::visit, so expose
+ /// it directly here.
+ Loc::Variant &asVariant() { return *static_cast<Loc::Variant *>(this); }
+ const Loc::Variant &asVariant() const {
+ return *static_cast<const Loc::Variant *>(this);
+ }
+ /// Member shorthand for std::holds_alternative
+ template <typename T> bool holds() const {
+ return std::holds_alternative<T>(*this);
+ }
+ /// Asserting, noexcept member alternative to std::get
+ template <typename T> auto &get() noexcept {
+ assert(holds<T>());
+ return *std::get_if<T>(this);
+ }
+ /// Asserting, noexcept member alternative to std::get
+ template <typename T> const auto &get() const noexcept {
+ assert(holds<T>());
+ return *std::get_if<T>(this);
}
- /// Initialize from a DBG_VALUE instruction.
- void initializeDbgValue(const MachineInstr *DbgValue);
+ /// Construct a DbgVariable.
+ ///
+ /// Creates a variable without any DW_AT_location.
+ DbgVariable(const DILocalVariable *V, const DILocation *IA)
+ : DbgEntity(V, IA, DbgVariableKind) {}
// Accessors.
const DILocalVariable *getVariable() const {
return cast<DILocalVariable>(getEntity());
}
- const DIExpression *getSingleExpression() const {
- assert(ValueLoc.get() && FrameIndexExprs.size() <= 1);
- return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr;
- }
-
- void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; }
- unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
- void setDebugLocListTagOffset(uint8_t O) { DebugLocListTagOffset = O; }
- std::optional<uint8_t> getDebugLocListTagOffset() const {
- return DebugLocListTagOffset;
- }
StringRef getName() const { return getVariable()->getName(); }
- const DbgValueLoc *getValueLoc() const { return ValueLoc.get(); }
- /// Get the FI entries, sorted by fragment offset.
- ArrayRef<FrameIndexExpr> getFrameIndexExprs() const;
- bool hasFrameIndexExprs() const { return !FrameIndexExprs.empty(); }
- void addMMIEntry(const DbgVariable &V);
// Translate tag to proper Dwarf tag.
dwarf::Tag getTag() const {
@@ -211,15 +275,6 @@ public:
return false;
}
- bool hasComplexAddress() const {
- assert(ValueLoc.get() && "Expected DBG_VALUE, not MMI variable");
- assert((FrameIndexExprs.empty() ||
- (FrameIndexExprs.size() == 1 &&
- FrameIndexExprs[0].Expr->getNumElements())) &&
- "Invalid Expr for DBG_VALUE");
- return !FrameIndexExprs.empty();
- }
-
const DIType *getType() const;
static bool classof(const DbgEntity *N) {
@@ -353,6 +408,11 @@ class DwarfDebug : public DebugHandlerBase {
std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
TypeUnitsUnderConstruction;
+ /// Used to set a uniqe ID for a Type Unit.
+ /// This counter represents number of DwarfTypeUnits created, not necessarily
+ /// number of type units that will be emitted.
+ unsigned NumTypeUnitsCreated = 0;
+
/// Whether to use the GNU TLS opcode (instead of the standard opcode).
bool UseGNUTLSOpcode;
@@ -393,6 +453,11 @@ public:
Form,
};
+ enum class DWARF5AccelTableKind {
+ CU = 0,
+ TU = 1,
+ };
+
private:
/// Force the use of DW_AT_ranges even for single-entry range lists.
MinimizeAddrInV5 MinimizeAddr = MinimizeAddrInV5::Disabled;
@@ -440,7 +505,10 @@ private:
AddressPool AddrPool;
/// Accelerator tables.
- AccelTable<DWARF5AccelTableData> AccelDebugNames;
+ DWARF5AccelTable AccelDebugNames;
+ DWARF5AccelTable AccelTypeUnitsDebugNames;
+ /// Used to hide which DWARF5AccelTable we are using now.
+ DWARF5AccelTable *CurrentDebugNames = &AccelDebugNames;
AccelTable<AppleAccelTableOffsetData> AccelNames;
AccelTable<AppleAccelTableOffsetData> AccelObjC;
AccelTable<AppleAccelTableOffsetData> AccelNamespace;
@@ -479,8 +547,10 @@ private:
DIE &ScopeDIE, const MachineFunction &MF);
template <typename DataT>
- void addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel,
- StringRef Name, const DIE &Die);
+ void addAccelNameImpl(const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ AccelTable<DataT> &AppleAccel, StringRef Name,
+ const DIE &Die);
void finishEntityDefinitions();
@@ -724,6 +794,9 @@ public:
/// Returns what kind (if any) of accelerator tables to emit.
AccelTableKind getAccelTableKind() const { return TheAccelTableKind; }
+ /// Seet TheAccelTableKind
+ void setTheAccelTableKind(AccelTableKind K) { TheAccelTableKind = K; };
+
bool useAppleExtensionAttributes() const {
return HasAppleExtensionAttributes;
}
@@ -781,20 +854,27 @@ public:
void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry,
const DwarfCompileUnit *CU);
- void addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP,
- DIE &Die);
+ void addSubprogramNames(const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ const DISubprogram *SP, DIE &Die);
AddressPool &getAddressPool() { return AddrPool; }
- void addAccelName(const DICompileUnit &CU, StringRef Name, const DIE &Die);
+ void addAccelName(const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ StringRef Name, const DIE &Die);
- void addAccelObjC(const DICompileUnit &CU, StringRef Name, const DIE &Die);
+ void addAccelObjC(const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ StringRef Name, const DIE &Die);
- void addAccelNamespace(const DICompileUnit &CU, StringRef Name,
- const DIE &Die);
+ void addAccelNamespace(const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ StringRef Name, const DIE &Die);
- void addAccelType(const DICompileUnit &CU, StringRef Name, const DIE &Die,
- char Flags);
+ void addAccelType(const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ StringRef Name, const DIE &Die, char Flags);
const MachineFunction *getCurrentFunction() const { return CurFn; }
@@ -842,6 +922,19 @@ public:
MDNodeSet &getLocalDeclsForScope(const DILocalScope *S) {
return LocalDeclsPerLS[S];
}
+
+ /// Sets the current DWARF5AccelTable to use.
+ void setCurrentDWARF5AccelTable(const DWARF5AccelTableKind Kind) {
+ switch (Kind) {
+ case DWARF5AccelTableKind::CU:
+ CurrentDebugNames = &AccelDebugNames;
+ break;
+ case DWARF5AccelTableKind::TU:
+ CurrentDebugNames = &AccelTypeUnitsDebugNames;
+ }
+ }
+ /// Returns either CU or TU DWARF5AccelTable.
+ DWARF5AccelTable &getCurrentDWARF5AccelTable() { return *CurrentDebugNames; }
};
} // end namespace llvm