[llvm] [DebugInfo][DWARF] Emit DW_AT_abstract_origin for concrete/inlined DW_TAG_lexical_blocks (PR #136205)
Vladislav Dzhidzhoev via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 17 15:24:35 PDT 2025
https://github.com/dzhidzhoev updated https://github.com/llvm/llvm-project/pull/136205
>From 34da121b861fe1859e95215493abf4f30d698017 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Mon, 14 Apr 2025 17:12:13 +0200
Subject: [PATCH] [DebugInfo][DWARF] Emit DW_AT_abstract_origin for
concrete/inlined DW_TAG_lexical_blocks
During the discussion under
https://github.com/llvm/llvm-project/pull/119001, it was noticed, that
concrete DW_TAG_lexical_blocks should refer to corresponding abstract
DW_TAG_lexical_blocks to avoid ambiguity. This behavior is implemented
in GCC (https://godbolt.org/z/Khrzdq1Wx), but not in LLVM so far.
Fixes https://github.com/llvm/llvm-project/issues/49297.
---
.../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 15 +++++
.../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 5 ++
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1 +
llvm/test/DebugInfo/Generic/inline-scopes.ll | 15 ++++-
.../Generic/lexical-block-abstract-origin.ll | 56 +++++++++++++++++++
.../X86/lexical-block-file-inline.ll | 14 +++--
.../X86/missing-abstract-variable.ll | 6 +-
7 files changed, 104 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/DebugInfo/Generic/lexical-block-abstract-origin.ll
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 3939dae81841f..a20c374e08935 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -782,6 +782,8 @@ DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
assert(!LexicalBlockDIEs.count(DS) &&
"Concrete out-of-line DIE for this scope exists!");
LexicalBlockDIEs[DS] = ScopeDIE;
+ } else {
+ InlinedLocalScopeDIEs[DS].push_back(ScopeDIE);
}
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
@@ -1491,6 +1493,19 @@ void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) {
getDwarfDebug().addAccelName(*this, CUNode->getNameTableKind(), Name, *Die);
}
+void DwarfCompileUnit::attachLexicalScopesAbstractOrigins() {
+ auto AttachAO = [&](const DILocalScope *LS, DIE *ScopeDIE) {
+ if (auto *AbsLSDie = getAbstractScopeDIEs().lookup(LS))
+ addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *AbsLSDie);
+ };
+
+ for (auto [LScope, ScopeDIE] : LexicalBlockDIEs)
+ AttachAO(LScope, ScopeDIE);
+ for (auto &[LScope, ScopeDIEs] : InlinedLocalScopeDIEs)
+ for (auto *ScopeDIE : ScopeDIEs)
+ AttachAO(LScope, ScopeDIE);
+}
+
DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) {
auto &AbstractEntities = getAbstractEntities();
auto I = AbstractEntities.find(Node);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 104039db03c7c..09be22ce35e36 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -82,6 +82,10 @@ class DwarfCompileUnit final : public DwarfUnit {
// List of abstract local scopes (either DISubprogram or DILexicalBlock).
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
+ // List of inlined lexical block scopes that belong to subprograms within this
+ // CU.
+ DenseMap<const DILocalScope *, SmallVector<DIE *, 2>> InlinedLocalScopeDIEs;
+
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
/// DWO ID for correlating skeleton and split units.
@@ -299,6 +303,7 @@ class DwarfCompileUnit final : public DwarfUnit {
void finishSubprogramDefinition(const DISubprogram *SP);
void finishEntityDefinition(const DbgEntity *Entity);
+ void attachLexicalScopesAbstractOrigins();
/// Find abstract variable associated with Var.
using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 39f1299a24e81..6c932651750ee 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1262,6 +1262,7 @@ void DwarfDebug::finalizeModuleInfo() {
auto &TheCU = *P.second;
if (TheCU.getCUNode()->isDebugDirectivesOnly())
continue;
+ TheCU.attachLexicalScopesAbstractOrigins();
// Emit DW_AT_containing_type attribute to connect types with their
// vtable holding type.
TheCU.constructContainingTypeDIEs();
diff --git a/llvm/test/DebugInfo/Generic/inline-scopes.ll b/llvm/test/DebugInfo/Generic/inline-scopes.ll
index 8e7543eb16e69..45ecdd0594f64 100644
--- a/llvm/test/DebugInfo/Generic/inline-scopes.ll
+++ b/llvm/test/DebugInfo/Generic/inline-scopes.ll
@@ -20,16 +20,29 @@
; }
; Ensure that lexical_blocks within inlined_subroutines are preserved/emitted.
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT_linkage_name ("_Z2f1v")
+; CHECK: [[ADDR1:0x[0-9a-f]+]]: DW_TAG_lexical_block
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT_linkage_name ("_Z2f2v")
+; CHECK: [[ADDR2:0x[0-9a-f]+]]: DW_TAG_lexical_block
; CHECK: DW_TAG_inlined_subroutine
; CHECK-NOT: DW_TAG
; CHECK-NOT: NULL
-; CHECK: DW_TAG_lexical_block
+; CHECK: DW_TAG_lexical_block
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_AT_abstract_origin ([[ADDR1]]
; CHECK-NOT: DW_TAG
; CHECK-NOT: NULL
; CHECK: DW_TAG_variable
; Ensure that file changes don't interfere with creating inlined subroutines.
; (see the line directive inside 'f2' in thesource)
; CHECK: DW_TAG_inlined_subroutine
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_TAG_lexical_block
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_AT_abstract_origin ([[ADDR2]]
+; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_abstract_origin
diff --git a/llvm/test/DebugInfo/Generic/lexical-block-abstract-origin.ll b/llvm/test/DebugInfo/Generic/lexical-block-abstract-origin.ll
new file mode 100644
index 0000000000000..cbe2b818fba38
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/lexical-block-abstract-origin.ll
@@ -0,0 +1,56 @@
+; RUN: %llc_dwarf -filetype=obj -O0 %s -o - | llvm-dwarfdump -debug-info - | FileCheck %s
+
+; Check that DW_AT_abstract_origin is generated for concrete lexical block.
+
+; Generated from:
+; inline __attribute__((always_inline)) int foo(int x) {
+; {
+; int y = x + 5;
+; return y - 10;
+; }
+; }
+;
+; int bar(int x) {
+; int y = foo(7);
+; return y + 8;
+; }
+
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT_name ("foo")
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: [[LB:.*]]: DW_TAG_lexical_block
+
+; CHECK: DW_TAG_inlined_subroutine
+; CHECK-NEXT: DW_AT_abstract_origin {{.*}} "foo"
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_TAG_lexical_block
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_AT_abstract_origin {{.*}}[[LB]]
+
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
+target triple = "arm64-apple-macosx15.0.0"
+
+define i32 @bar() !dbg !9 {
+entry:
+ %y.i = alloca i32, align 4
+ #dbg_declare(ptr %y.i, !22, !DIExpression(), !24)
+ store i32 0, ptr %y.i, align 4, !dbg !24
+ %1 = load i32, ptr %y.i, align 4
+ ret i32 %1
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.c", directory: "")
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 8, type: !10, spFlags: DISPFlagDefinition, unit: !0)
+!10 = !DISubroutineType(types: !13)
+!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!13 = !{}
+!19 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0)
+!21 = distinct !DILocation(line: 9, column: 11, scope: !9)
+!22 = !DILocalVariable(name: "y", scope: !23, file: !1, line: 3, type: !12)
+!23 = distinct !DILexicalBlock(scope: !19, file: !1, line: 2, column: 3)
+!24 = !DILocation(line: 3, column: 9, scope: !23, inlinedAt: !21)
diff --git a/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll b/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll
index 15d0785bde93d..e8136f8eea965 100644
--- a/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll
+++ b/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll
@@ -28,9 +28,11 @@
; CHECK: DW_TAG_subprogram
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_abstract_origin {{.*}} {[[Offset_bar:0x[0-9abcdef]+]]}
-; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
-; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_AT_abstract_origin {{.*}}[[Offset_lb:0x[0-9a-f]+]]
+; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
;; Abstract "bar" function
@@ -40,7 +42,7 @@
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_inline
; CHECK-NOT: {{DW_TAG|NULL}}
-; CHECK: DW_TAG_lexical_block
+; CHECK: [[Offset_lb]]: DW_TAG_lexical_block
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
@@ -56,8 +58,10 @@
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[Offset_bar]]}
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
-; CHECK-NOT: {{DW_TAG|NULL}}
-; CHECK: DW_TAG_variable
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_AT_abstract_origin {{.*}}[[Offset_lb]]
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_TAG_variable
; Function Attrs: alwaysinline nounwind
define i32 @_Z3barv() #0 !dbg !4 {
diff --git a/llvm/test/DebugInfo/X86/missing-abstract-variable.ll b/llvm/test/DebugInfo/X86/missing-abstract-variable.ll
index 572dca2c2cb6c..21363805aff2f 100644
--- a/llvm/test/DebugInfo/X86/missing-abstract-variable.ll
+++ b/llvm/test/DebugInfo/X86/missing-abstract-variable.ll
@@ -37,7 +37,7 @@
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name ("b")
; CHECK-NOT: {{DW_TAG|NULL}}
-; CHECK: DW_TAG_lexical_block
+; CHECK: [[LB_DECL:.*]]: DW_TAG_lexical_block
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: DW_TAG
@@ -82,7 +82,9 @@
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
-; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_AT_abstract_origin {{.*}}[[LB_DECL]]
+; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_abstract_origin {{.*}} "s"
More information about the llvm-commits
mailing list