[llvm] [DebugInfo] Fix issue with debug line table offsets for empty functions (PR #142253)
via llvm-commits
llvm-commits at lists.llvm.org
Sat May 31 07:41:51 PDT 2025
https://github.com/alx32 updated https://github.com/llvm/llvm-project/pull/142253
>From 72d37611264b2ee14079dbfa17bee477b8266d0c Mon Sep 17 00:00:00 2001
From: Alex B <alexborcan at meta.com>
Date: Fri, 30 May 2025 20:40:33 -0700
Subject: [PATCH 1/2] [MCDwarf] Fix issue with debug line offsets for empty
functions
---
llvm/lib/MC/MCDwarf.cpp | 31 +++++++++++-----
..._AT_LLVM_stmt_seq_sec_offset_empty_func.ll | 37 +++++++++++++++++++
2 files changed, 59 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/DebugInfo/X86/DW_AT_LLVM_stmt_seq_sec_offset_empty_func.ll
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index 2525ff02878e4..8f6f37e5b610a 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -144,19 +144,32 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
auto *Sec = &EndLabel->getSection();
// The line table may be empty, which we should skip adding an end entry.
- // There are two cases:
+ // There are three cases:
// (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
// place instead of adding a line entry if the target has
// usesDwarfFileAndLocDirectives.
// (2) MCObjectStreamer - if a function has incomplete debug info where
// instructions don't have DILocations, the line entries are missing.
+ // (3) It's also possible that there are no prior line entries if the section
+ // itself is empty before this end label.
auto I = MCLineDivisions.find(Sec);
- if (I != MCLineDivisions.end()) {
- auto &Entries = I->second;
- auto EndEntry = Entries.back();
- EndEntry.setEndLabel(EndLabel);
- Entries.push_back(EndEntry);
- }
+ if (I == MCLineDivisions.end()) // If section not found, do nothing.
+ return;
+
+ auto &Entries = I->second;
+ // If no entries in this section's list, nothing to base the end entry on.
+ if (Entries.empty())
+ return;
+
+ // Create the end entry based on the last existing entry.
+ MCDwarfLineEntry EndEntry = Entries.back();
+ EndEntry.setEndLabel(EndLabel);
+ // An end entry is just for marking the end of a sequence of code locations.
+ // It should not carry forward a LineStreamLabel from a previous special entry
+ // if Entries.back() happened to be such an entry. So here we clear
+ // LineStreamLabel.
+ EndEntry.LineStreamLabel = nullptr;
+ Entries.push_back(EndEntry);
}
//
@@ -1227,7 +1240,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
// a dwarf label.
//
void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
- SourceMgr &SrcMgr, SMLoc &Loc) {
+ SourceMgr &SrcMgr, SMLoc &Loc) {
// We won't create dwarf labels for temporary symbols.
if (Symbol->isTemporary())
return;
@@ -1295,7 +1308,7 @@ static unsigned getSizeForEncoding(MCStreamer &streamer,
}
static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
- unsigned symbolEncoding, bool isEH) {
+ unsigned symbolEncoding, bool isEH) {
MCContext &context = streamer.getContext();
const MCAsmInfo *asmInfo = context.getAsmInfo();
const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
diff --git a/llvm/test/DebugInfo/X86/DW_AT_LLVM_stmt_seq_sec_offset_empty_func.ll b/llvm/test/DebugInfo/X86/DW_AT_LLVM_stmt_seq_sec_offset_empty_func.ll
new file mode 100644
index 0000000000000..553a05f12082e
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/DW_AT_LLVM_stmt_seq_sec_offset_empty_func.ll
@@ -0,0 +1,37 @@
+; RUN: llc -filetype=obj -emit-func-debug-line-table-offsets < %s -o %t_yes_off.o
+; RUN: llc -filetype=obj < %s -o %t_no_off.o
+; RUN: llvm-dwarfdump -v -all %t_no_off.o | FileCheck --check-prefix=CHECK-NO-OFF %s
+; RUN: llvm-dwarfdump -v -all %t_yes_off.o | FileCheck --check-prefix=CHECK-YES-OFF %s
+
+; We don't need a line table for an empty function
+; CHECK-NO-OFF-NOT: DW_LNE_set_address
+
+; CHECK-YES-OFF: DW_AT_LLVM_stmt_sequence [DW_FORM_sec_offset] ({{.*}})
+; CHECK-YES-OFF: Address
+; CHECK-YES-OFF-NEXT: ------------------
+; CHECK-YES-OFF-NEXT: DW_LNE_set_address ({{.*}})
+; CHECK-YES-OFF-NEXT: DW_LNE_end_sequence
+; CHECK-YES-OFF-NEXT: 0x0000000000000000 {{.*}} is_stmt end_sequence
+
+; IR generated by llvm-reduce from LTO repro
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define ptr @_my_test_function() !dbg !4 {
+entry:
+ unreachable
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 21.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "repro_bug.cpp", directory: "/tmp/repro", checksumkind: CSK_MD5, checksum: "74e33e88b3108a4f94403da9fdb362f5")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "east", linkageName: "_my_test_function", scope: !6, file: !5, line: 114, type: !8, scopeLine: 114, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !9, retainedNodes: !2)
+!5 = !DIFile(filename: "repro_bug.cpp", directory: "/tmp/repro", checksumkind: CSK_MD5, checksum: "74e33e88b3108a4f94403da9fdb362f5")
+!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "rectangle", file: !5, line: 103, size: 256, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2, vtableHolder: !7)
+!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "shape", file: !5, line: 58, size: 128, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2, vtableHolder: !7, identifier: "_ZTS5shape")
+!8 = distinct !DISubroutineType(types: !2)
+!9 = !DISubprogram(name: "east", linkageName: "_my_test_function", scope: !6, file: !5, line: 114, type: !8, scopeLine: 114, containingType: !6, virtualIndex: 2, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagVirtual | DISPFlagOptimized)
>From 805bb644784f352a3e54aa9457f6307354f634a3 Mon Sep 17 00:00:00 2001
From: Alex B <alexborcan at meta.com>
Date: Sat, 31 May 2025 07:41:37 -0700
Subject: [PATCH 2/2] mend
---
llvm/include/llvm/MC/MCDwarf.h | 3 +++
llvm/lib/MC/MCDwarf.cpp | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h
index 2fa7d73e1fa25..b33c9f0c8e4d0 100644
--- a/llvm/include/llvm/MC/MCDwarf.h
+++ b/llvm/include/llvm/MC/MCDwarf.h
@@ -216,6 +216,9 @@ class MCDwarfLineEntry : public MCDwarfLoc {
// Override the label with the given EndLabel.
void setEndLabel(MCSymbol *EndLabel) {
+ // If we're setting this to be an end entry, make sure we don't have
+ // LineStreamLabel set.
+ assert(LineStreamLabel == nullptr);
Label = EndLabel;
IsEndEntry = true;
}
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index 8f6f37e5b610a..bb9bbd0a9e61b 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -163,12 +163,13 @@ void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
// Create the end entry based on the last existing entry.
MCDwarfLineEntry EndEntry = Entries.back();
- EndEntry.setEndLabel(EndLabel);
+
// An end entry is just for marking the end of a sequence of code locations.
// It should not carry forward a LineStreamLabel from a previous special entry
// if Entries.back() happened to be such an entry. So here we clear
// LineStreamLabel.
EndEntry.LineStreamLabel = nullptr;
+ EndEntry.setEndLabel(EndLabel);
Entries.push_back(EndEntry);
}
More information about the llvm-commits
mailing list