[llvm] [llvm][DebugInfo] Attach object-pointer to DISubprogram declarations (PR #122742)
Michael Buch via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 13 08:49:02 PST 2025
https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/122742
Currently Clang only attaches `DW_AT_object_pointer` to `DW_TAG_subprogram` definitions. LLDB constructs C++ method types from their `DW_TAG_subprogram` declaration, which is also the point at which it needs to determine whether a method is static or not. LLDB's heuristic for this could be very simple if we emitted `DW_AT_object_pointer` on declarations. But since we don't, LLDB has to guess whether an argument is an implicit object parameter based on the DW_AT_name and DW_AT_type.
To simplify LLDB's job (and to eventually support C++23's explicit object parameters), this patch adds the `DIFlagObjectPointer` to `DISubprogram` declarations.
For reference, GCC attaches the object-pointer DIE to both the definition and declaration: https://godbolt.org/z/3TWjTfWon
Fixes https://github.com/llvm/llvm-project/issues/120973
>From c1e4faf70993f59734882d9a98024d44eb50d82d Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 9 Jan 2025 14:37:41 +0000
Subject: [PATCH] [llvm][DebugInfo] Attach object-pointer to DISubprogram
declarations
Currently Clang only attaches `DW_AT_object_pointer` to
`DW_TAG_subprogram` definitions. LLDB constructs C++ method
types from their `DW_TAG_subprogram` declaration, which is also
the point at which it needs to determine whether a method is
static or not. LLDB's heuristic for this could be very simple if we
emitted `DW_AT_object_pointer` on declarations. But since we don't,
LLDB has to guess whether an argument is an implicit object parameter
based on the DW_AT_name and DW_AT_type.
To simplify LLDB's job (and to eventually support C++23's explicit
object parameters), this patch adds the `DIFlagObjectPointer` to
`DISubprogram` declarations.
For reference, GCC attaches the object-pointer DIE to both the
definition and declaration: https://godbolt.org/z/3TWjTfWon
Fixes https://github.com/llvm/llvm-project/issues/120973
---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 13 +++++++++++--
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 4 +++-
llvm/test/DebugInfo/X86/DW_AT_object_pointer.ll | 10 +++++++++-
llvm/test/DebugInfo/X86/dwarf-public-names.ll | 2 +-
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 0a8a1ad38c959f2..d3450b8b0556fde 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -849,7 +849,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
}
}
-void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) {
+DIE *DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) {
+ // Args[0] is the return type.
+ DIE *ObjectPointer = nullptr;
for (unsigned i = 1, N = Args.size(); i < N; ++i) {
const DIType *Ty = Args[i];
if (!Ty) {
@@ -860,8 +862,14 @@ void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) {
addType(Arg, Ty);
if (Ty->isArtificial())
addFlag(Arg, dwarf::DW_AT_artificial);
+ if (Ty->isObjectPointer()) {
+ assert(!ObjectPointer && "Can't have more than one object pointer");
+ ObjectPointer = &Arg;
+ }
}
}
+
+ return ObjectPointer;
}
void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) {
@@ -1358,7 +1366,8 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
// Add arguments. Do not add arguments for subprogram definition. They will
// be handled while processing variables.
- constructSubprogramArguments(SPDie, Args);
+ if (auto *ObjectPointer = constructSubprogramArguments(SPDie, Args))
+ addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
addThrownTypes(SPDie, SP->getThrownTypes());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 163205378fb4b66..7a5295d826a483b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -268,7 +268,9 @@ class DwarfUnit : public DIEUnit {
void constructContainingTypeDIEs();
/// Construct function argument DIEs.
- void constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args);
+ ///
+ /// \returns DIE of the object pointer if one exists. Nullptr otherwise.
+ DIE *constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args);
/// Create a DIE with the given Tag, add the DIE to its parent, and
/// call insertDIE if MD is not null.
diff --git a/llvm/test/DebugInfo/X86/DW_AT_object_pointer.ll b/llvm/test/DebugInfo/X86/DW_AT_object_pointer.ll
index d9988ac31451e2c..30d4203466766ef 100644
--- a/llvm/test/DebugInfo/X86/DW_AT_object_pointer.ll
+++ b/llvm/test/DebugInfo/X86/DW_AT_object_pointer.ll
@@ -5,7 +5,15 @@
; CHECK-NOT: ""
; CHECK: DW_TAG
; CHECK: DW_TAG_class_type
-; CHECK: DW_AT_object_pointer [DW_FORM_ref4] (cu + 0x{{[0-9a-f]*}} => {[[PARAM:0x[0-9a-f]*]]})
+; CHECK: [[DECL:0x[0-9a-f]+]]: DW_TAG_subprogram
+; CHECK: DW_AT_name {{.*}} "A"
+; CHECK: DW_AT_object_pointer [DW_FORM_ref4]
+; CHECK-SAME: (cu + 0x{{[0-9a-f]*}} => {[[DECL_PARAM:0x[0-9a-f]*]]})
+; CHECK: [[DECL_PARAM]]: DW_TAG_formal_parameter
+;
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_specification [DW_FORM_ref4] (cu + {{.*}} => {[[DECL]]}
+; CHECK: DW_AT_object_pointer [DW_FORM_ref4] (cu + 0x{{[0-9a-f]*}} => {[[PARAM:0x[0-9a-f]*]]})
; CHECK: [[PARAM]]: DW_TAG_formal_parameter
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]*}}] = "this")
diff --git a/llvm/test/DebugInfo/X86/dwarf-public-names.ll b/llvm/test/DebugInfo/X86/dwarf-public-names.ll
index c2274511d4191f4..a484c094892d0cf 100644
--- a/llvm/test/DebugInfo/X86/dwarf-public-names.ll
+++ b/llvm/test/DebugInfo/X86/dwarf-public-names.ll
@@ -61,7 +61,7 @@
; Skip the output to the header of the pubnames section.
; LINUX: debug_pubnames
-; LINUX-NEXT: unit_size = 0x00000128
+; LINUX-NEXT: unit_size =
; Check for each name in the output.
; LINUX-DAG: "ns"
More information about the llvm-commits
mailing list