Skip to content

Commit 1143a04

Browse files
authored
[DebugInfo][DWARF] Emit DW_AT_abstract_origin for concrete/inlined DW_TAG_lexical_blocks (llvm#136205)
During the discussion under llvm#119001, it was noticed that concrete DW_TAG_lexical_blocks should refer to corresponding abstract DW_TAG_lexical_blocks by having DW_AT_abstract_origin, to avoid ambiguity. This behavior is implemented in GCC (https://godbolt.org/z/Khrzdq1Wx), but not in LLVM. Fixes llvm#49297.
1 parent 8832a59 commit 1143a04

File tree

7 files changed

+104
-8
lines changed

7 files changed

+104
-8
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,8 @@ DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
782782
assert(!LexicalBlockDIEs.count(DS) &&
783783
"Concrete out-of-line DIE for this scope exists!");
784784
LexicalBlockDIEs[DS] = ScopeDIE;
785+
} else {
786+
InlinedLocalScopeDIEs[DS].push_back(ScopeDIE);
785787
}
786788

787789
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
@@ -1491,6 +1493,19 @@ void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) {
14911493
getDwarfDebug().addAccelName(*this, CUNode->getNameTableKind(), Name, *Die);
14921494
}
14931495

1496+
void DwarfCompileUnit::attachLexicalScopesAbstractOrigins() {
1497+
auto AttachAO = [&](const DILocalScope *LS, DIE *ScopeDIE) {
1498+
if (auto *AbsLSDie = getAbstractScopeDIEs().lookup(LS))
1499+
addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *AbsLSDie);
1500+
};
1501+
1502+
for (auto [LScope, ScopeDIE] : LexicalBlockDIEs)
1503+
AttachAO(LScope, ScopeDIE);
1504+
for (auto &[LScope, ScopeDIEs] : InlinedLocalScopeDIEs)
1505+
for (auto *ScopeDIE : ScopeDIEs)
1506+
AttachAO(LScope, ScopeDIE);
1507+
}
1508+
14941509
DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) {
14951510
auto &AbstractEntities = getAbstractEntities();
14961511
auto I = AbstractEntities.find(Node);

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class DwarfCompileUnit final : public DwarfUnit {
8282
// List of abstract local scopes (either DISubprogram or DILexicalBlock).
8383
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
8484

85+
// List of inlined lexical block scopes that belong to subprograms within this
86+
// CU.
87+
DenseMap<const DILocalScope *, SmallVector<DIE *, 2>> InlinedLocalScopeDIEs;
88+
8589
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
8690

8791
/// DWO ID for correlating skeleton and split units.
@@ -299,6 +303,7 @@ class DwarfCompileUnit final : public DwarfUnit {
299303

300304
void finishSubprogramDefinition(const DISubprogram *SP);
301305
void finishEntityDefinition(const DbgEntity *Entity);
306+
void attachLexicalScopesAbstractOrigins();
302307

303308
/// Find abstract variable associated with Var.
304309
using InlinedEntity = DbgValueHistoryMap::InlinedEntity;

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,7 @@ void DwarfDebug::finalizeModuleInfo() {
12621262
auto &TheCU = *P.second;
12631263
if (TheCU.getCUNode()->isDebugDirectivesOnly())
12641264
continue;
1265+
TheCU.attachLexicalScopesAbstractOrigins();
12651266
// Emit DW_AT_containing_type attribute to connect types with their
12661267
// vtable holding type.
12671268
TheCU.constructContainingTypeDIEs();

llvm/test/DebugInfo/Generic/inline-scopes.ll

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,29 @@
2020
; }
2121

2222
; Ensure that lexical_blocks within inlined_subroutines are preserved/emitted.
23+
; CHECK: DW_TAG_subprogram
24+
; CHECK-NEXT: DW_AT_linkage_name ("_Z2f1v")
25+
; CHECK: [[ADDR1:0x[0-9a-f]+]]: DW_TAG_lexical_block
26+
; CHECK: DW_TAG_subprogram
27+
; CHECK-NEXT: DW_AT_linkage_name ("_Z2f2v")
28+
; CHECK: [[ADDR2:0x[0-9a-f]+]]: DW_TAG_lexical_block
2329
; CHECK: DW_TAG_inlined_subroutine
2430
; CHECK-NOT: DW_TAG
2531
; CHECK-NOT: NULL
26-
; CHECK: DW_TAG_lexical_block
32+
; CHECK: DW_TAG_lexical_block
33+
; CHECK-NOT: {{DW_TAG|NULL}}
34+
; CHECK: DW_AT_abstract_origin ([[ADDR1]]
2735
; CHECK-NOT: DW_TAG
2836
; CHECK-NOT: NULL
2937
; CHECK: DW_TAG_variable
3038
; Ensure that file changes don't interfere with creating inlined subroutines.
3139
; (see the line directive inside 'f2' in thesource)
3240
; CHECK: DW_TAG_inlined_subroutine
41+
; CHECK-NOT: {{DW_TAG|NULL}}
42+
; CHECK: DW_TAG_lexical_block
43+
; CHECK-NOT: {{DW_TAG|NULL}}
44+
; CHECK: DW_AT_abstract_origin ([[ADDR2]]
45+
; CHECK-NOT: {{DW_TAG|NULL}}
3346
; CHECK: DW_TAG_variable
3447
; CHECK-NOT: DW_TAG
3548
; CHECK: DW_AT_abstract_origin
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; RUN: %llc_dwarf -filetype=obj -O0 %s -o - | llvm-dwarfdump -debug-info - | FileCheck %s
2+
3+
; Check that DW_AT_abstract_origin is generated for concrete lexical block.
4+
5+
; Generated from:
6+
; inline __attribute__((always_inline)) int foo(int x) {
7+
; {
8+
; int y = x + 5;
9+
; return y - 10;
10+
; }
11+
; }
12+
;
13+
; int bar(int x) {
14+
; int y = foo(7);
15+
; return y + 8;
16+
; }
17+
18+
; CHECK: DW_TAG_subprogram
19+
; CHECK-NEXT: DW_AT_name ("foo")
20+
; CHECK-NOT: {{DW_TAG|NULL}}
21+
; CHECK: [[LB:.*]]: DW_TAG_lexical_block
22+
23+
; CHECK: DW_TAG_inlined_subroutine
24+
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} "foo"
25+
; CHECK-NOT: {{DW_TAG|NULL}}
26+
; CHECK: DW_TAG_lexical_block
27+
; CHECK-NOT: {{DW_TAG|NULL}}
28+
; CHECK: DW_AT_abstract_origin {{.*}}[[LB]]
29+
30+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
31+
target triple = "arm64-apple-macosx15.0.0"
32+
33+
define i32 @bar() !dbg !9 {
34+
entry:
35+
%y.i = alloca i32, align 4
36+
#dbg_declare(ptr %y.i, !22, !DIExpression(), !24)
37+
store i32 0, ptr %y.i, align 4, !dbg !24
38+
%1 = load i32, ptr %y.i, align 4
39+
ret i32 %1
40+
}
41+
42+
!llvm.dbg.cu = !{!0}
43+
!llvm.module.flags = !{!3}
44+
45+
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, emissionKind: FullDebug)
46+
!1 = !DIFile(filename: "test.c", directory: "")
47+
!3 = !{i32 2, !"Debug Info Version", i32 3}
48+
!9 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 8, type: !10, spFlags: DISPFlagDefinition, unit: !0)
49+
!10 = !DISubroutineType(types: !13)
50+
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
51+
!13 = !{}
52+
!19 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0)
53+
!21 = distinct !DILocation(line: 9, column: 11, scope: !9)
54+
!22 = !DILocalVariable(name: "y", scope: !23, file: !1, line: 3, type: !12)
55+
!23 = distinct !DILexicalBlock(scope: !19, file: !1, line: 2, column: 3)
56+
!24 = !DILocation(line: 3, column: 9, scope: !23, inlinedAt: !21)

llvm/test/DebugInfo/X86/lexical-block-file-inline.ll

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
; CHECK: DW_TAG_subprogram
2929
; CHECK-NOT: {{DW_TAG|NULL}}
3030
; CHECK: DW_AT_abstract_origin {{.*}} {[[Offset_bar:0x[0-9abcdef]+]]}
31-
; CHECK-NOT: {{DW_TAG|NULL}}
31+
; CHECK-NOT: {{DW_TAG|NULL}}
3232
; CHECK: DW_TAG_lexical_block
33-
; CHECK-NOT: {{DW_TAG|NULL}}
33+
; CHECK-NOT: {{DW_TAG|NULL}}
34+
; CHECK: DW_AT_abstract_origin {{.*}}[[Offset_lb:0x[0-9a-f]+]]
35+
; CHECK-NOT: {{DW_TAG|NULL}}
3436
; CHECK: DW_TAG_variable
3537

3638
;; Abstract "bar" function
@@ -40,7 +42,7 @@
4042
; CHECK-NOT: {{DW_TAG|NULL}}
4143
; CHECK: DW_AT_inline
4244
; CHECK-NOT: {{DW_TAG|NULL}}
43-
; CHECK: DW_TAG_lexical_block
45+
; CHECK: [[Offset_lb]]: DW_TAG_lexical_block
4446
; CHECK-NOT: {{DW_TAG|NULL}}
4547
; CHECK: DW_TAG_variable
4648
; CHECK-NOT: {{DW_TAG|NULL}}
@@ -56,8 +58,10 @@
5658
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[Offset_bar]]}
5759
; CHECK-NOT: {{DW_TAG|NULL}}
5860
; CHECK: DW_TAG_lexical_block
59-
; CHECK-NOT: {{DW_TAG|NULL}}
60-
; CHECK: DW_TAG_variable
61+
; CHECK-NOT: {{DW_TAG|NULL}}
62+
; CHECK: DW_AT_abstract_origin {{.*}}[[Offset_lb]]
63+
; CHECK-NOT: {{DW_TAG|NULL}}
64+
; CHECK: DW_TAG_variable
6165

6266
; Function Attrs: alwaysinline nounwind
6367
define i32 @_Z3barv() #0 !dbg !4 {

llvm/test/DebugInfo/X86/missing-abstract-variable.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
; CHECK-NOT: DW_TAG
3838
; CHECK: DW_AT_name ("b")
3939
; CHECK-NOT: {{DW_TAG|NULL}}
40-
; CHECK: DW_TAG_lexical_block
40+
; CHECK: [[LB_DECL:.*]]: DW_TAG_lexical_block
4141
; CHECK-NOT: {{DW_TAG|NULL}}
4242
; CHECK: DW_TAG_variable
4343
; CHECK-NOT: DW_TAG
@@ -82,7 +82,9 @@
8282

8383
; CHECK-NOT: {{DW_TAG|NULL}}
8484
; CHECK: DW_TAG_lexical_block
85-
; CHECK-NOT: {{DW_TAG|NULL}}
85+
; CHECK-NOT: {{DW_TAG|NULL}}
86+
; CHECK: DW_AT_abstract_origin {{.*}}[[LB_DECL]]
87+
; CHECK-NOT: {{DW_TAG|NULL}}
8688
; CHECK: DW_TAG_variable
8789
; CHECK-NOT: DW_TAG
8890
; CHECK: DW_AT_abstract_origin {{.*}} "s"

0 commit comments

Comments
 (0)