diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 263 |
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 |
