From a2f6fc5d44b791a2c7842a570620fa429d52ce5e Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Tue, 7 Nov 2023 17:10:25 -0800 Subject: [PATCH] [DebugInfo] Implement TAG_label entries for debug_names The DWARF 5 specification says that: > The name index must contain an entry for each debugging information entry that > defines a named [...] label [...]. The verifier currently verifies this, but the AsmPrinter does not add entries for TAG_labels in debug_names. This patch addresses the issue by ensuring we add labels in the accelerator tables once we have a fully completed DIE for the TAG_label entry. We also respect the spec as follows: > DW_TAG_label debugging information entries without an address attribute > (DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, or DW_AT_entry_pc) are excluded. The effect of this on the size of accelerator tables is minimal, as TAG_labels are usually created by C/C++ labels (see example in test), which are typically paired with "goto" statements. --- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 15 ++++- .../test/DebugInfo/X86/debug-names-dwarf64.ll | 57 ++++++++++++++++++- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 42bf755737506..feb5ab665a17d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1422,9 +1422,18 @@ void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) { llvm_unreachable("DbgEntity must be DbgVariable or DbgLabel."); } - if (Label) - if (const auto *Sym = Label->getSymbol()) - addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym); + if (!Label) + return; + + const auto *Sym = Label->getSymbol(); + if (!Sym) + return; + + addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym); + + // A TAG_label with a name and an AT_low_pc must be placed in debug_names. + if (StringRef Name = Label->getName(); !Name.empty()) + getDwarfDebug().addAccelName(*CUNode, Name, *Die); } DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) { diff --git a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll index 8cd1f0c182920..e5fd6be033ca7 100644 --- a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll +++ b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll @@ -10,6 +10,10 @@ ; CHECK-NEXT: DW_AT_name ("foo") ; CHECK: [[TYPEDIE:.+]]: DW_TAG_base_type ; CHECK-NEXT: DW_AT_name ("int") +; CHECK: [[SPDIE:.+]]: DW_TAG_subprogram +; CHECK: DW_AT_name ("func") +; CHECK: [[LABELDIE:.+]]: DW_TAG_label +; CHECK-NEXT: DW_AT_name ("MyLabel") ; CHECK: .debug_names contents: ; CHECK-NEXT: Name Index @ 0x0 { @@ -19,8 +23,8 @@ ; CHECK-NEXT: CU count: 1 ; CHECK-NEXT: Local TU count: 0 ; CHECK-NEXT: Foreign TU count: 0 -; CHECK-NEXT: Bucket count: 2 -; CHECK-NEXT: Name count: 2 +; CHECK-NEXT: Bucket count: 4 +; CHECK-NEXT: Name count: 4 ; CHECK: } ; CHECK-NEXT: Compilation Unit offsets [ ; CHECK-NEXT: CU[0]: 0x00000000 @@ -30,6 +34,14 @@ ; CHECK-NEXT: Tag: DW_TAG_variable ; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 ; CHECK-NEXT: } +; CHECK-NEXT: Abbreviation [[ABBREV_SP:0x[0-9a-f]*]] { +; CHECK-NEXT: Tag: DW_TAG_subprogram +; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; CHECK-NEXT: } +; CHECK-NEXT: Abbreviation [[ABBREV_LABEL:0x[0-9a-f]*]] { +; CHECK-NEXT: Tag: DW_TAG_label +; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; CHECK-NEXT: } ; CHECK-NEXT: Abbreviation [[ABBREV:0x[0-9a-f]*]] { ; CHECK-NEXT: Tag: DW_TAG_base_type ; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 @@ -56,6 +68,29 @@ ; CHECK-NEXT: DW_IDX_die_offset: [[VARDIE]] ; CHECK-NEXT: } ; CHECK-NEXT: } +; CHECK-NEXT: Name 3 { +; CHECK-NEXT: Hash: 0x7C96FE71 +; CHECK-NEXT: String: {{.+}} "func" +; CHECK-NEXT: Entry @ {{.+}} { +; CHECK-NEXT: Abbrev: [[ABBREV_SP]] +; CHECK-NEXT: Tag: DW_TAG_subprogram +; CHECK-NEXT: DW_IDX_die_offset: [[SPDIE]] +; CHECK-NEXT: } +; CHECK-NEXT: } +; CHECK-NEXT: ] +; CHECK-NEXT: Bucket 2 [ +; CHECK-NEXT: EMPTY +; CHECK-NEXT: ] +; CHECK-NEXT: Bucket 3 [ +; CHECK-NEXT: Name 4 { +; CHECK-NEXT: Hash: 0xEC64E52B +; CHECK-NEXT: String: {{.+}} "MyLabel" +; CHECK-NEXT: Entry @ {{.+}} { +; CHECK-NEXT: Abbrev: [[ABBREV_LABEL]] +; CHECK-NEXT: Tag: DW_TAG_label +; CHECK-NEXT: DW_IDX_die_offset: [[LABELDIE]] +; CHECK-NEXT: } +; CHECK-NEXT: } ; CHECK-NEXT: ] ; CHECK-NEXT: } @@ -64,12 +99,25 @@ ; IR generated and reduced from: ; $ cat foo.c ; int foo; +; void func() { +; goto MyLabel; +; +; MyLabel: +; return 1; +; } ; $ clang -g -gpubnames -S -emit-llvm foo.c -o foo.ll target triple = "x86_64-unknown-linux-gnu" @foo = dso_local global i32 0, align 4, !dbg !0 +define void @func() !dbg !11 { + call void @llvm.dbg.label(metadata !15), !dbg !14 + ret void, !dbg !14 +} + +declare void @llvm.dbg.label(metadata) + !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!7, !8, !9} !llvm.ident = !{!10} @@ -85,3 +133,8 @@ target triple = "x86_64-unknown-linux-gnu" !8 = !{i32 2, !"Debug Info Version", i32 3} !9 = !{i32 1, !"wchar_size", i32 4} !10 = !{!"clang version 12.0.0"} +!11 = distinct !DISubprogram(name: "func", linkageName: "func", scope: !3, file: !3, line: 2, type: !12, unit: !2) +!12 = !DISubroutineType(types: !13) +!13 = !{null} +!14 = !DILocation(line: 2, column: 13, scope: !11) +!15 = !DILabel(scope: !11, name: "MyLabel", file: !3, line: 5)