Skip to content

Commit 72d3761

Browse files
author
Alex B
committed
[MCDwarf] Fix issue with debug line offsets for empty functions
1 parent 45218e0 commit 72d3761

File tree

2 files changed

+59
-9
lines changed

2 files changed

+59
-9
lines changed

llvm/lib/MC/MCDwarf.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,32 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
144144
void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
145145
auto *Sec = &EndLabel->getSection();
146146
// The line table may be empty, which we should skip adding an end entry.
147-
// There are two cases:
147+
// There are three cases:
148148
// (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
149149
// place instead of adding a line entry if the target has
150150
// usesDwarfFileAndLocDirectives.
151151
// (2) MCObjectStreamer - if a function has incomplete debug info where
152152
// instructions don't have DILocations, the line entries are missing.
153+
// (3) It's also possible that there are no prior line entries if the section
154+
// itself is empty before this end label.
153155
auto I = MCLineDivisions.find(Sec);
154-
if (I != MCLineDivisions.end()) {
155-
auto &Entries = I->second;
156-
auto EndEntry = Entries.back();
157-
EndEntry.setEndLabel(EndLabel);
158-
Entries.push_back(EndEntry);
159-
}
156+
if (I == MCLineDivisions.end()) // If section not found, do nothing.
157+
return;
158+
159+
auto &Entries = I->second;
160+
// If no entries in this section's list, nothing to base the end entry on.
161+
if (Entries.empty())
162+
return;
163+
164+
// Create the end entry based on the last existing entry.
165+
MCDwarfLineEntry EndEntry = Entries.back();
166+
EndEntry.setEndLabel(EndLabel);
167+
// An end entry is just for marking the end of a sequence of code locations.
168+
// It should not carry forward a LineStreamLabel from a previous special entry
169+
// if Entries.back() happened to be such an entry. So here we clear
170+
// LineStreamLabel.
171+
EndEntry.LineStreamLabel = nullptr;
172+
Entries.push_back(EndEntry);
160173
}
161174

162175
//
@@ -1227,7 +1240,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
12271240
// a dwarf label.
12281241
//
12291242
void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
1230-
SourceMgr &SrcMgr, SMLoc &Loc) {
1243+
SourceMgr &SrcMgr, SMLoc &Loc) {
12311244
// We won't create dwarf labels for temporary symbols.
12321245
if (Symbol->isTemporary())
12331246
return;
@@ -1295,7 +1308,7 @@ static unsigned getSizeForEncoding(MCStreamer &streamer,
12951308
}
12961309

12971310
static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
1298-
unsigned symbolEncoding, bool isEH) {
1311+
unsigned symbolEncoding, bool isEH) {
12991312
MCContext &context = streamer.getContext();
13001313
const MCAsmInfo *asmInfo = context.getAsmInfo();
13011314
const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; RUN: llc -filetype=obj -emit-func-debug-line-table-offsets < %s -o %t_yes_off.o
2+
; RUN: llc -filetype=obj < %s -o %t_no_off.o
3+
; RUN: llvm-dwarfdump -v -all %t_no_off.o | FileCheck --check-prefix=CHECK-NO-OFF %s
4+
; RUN: llvm-dwarfdump -v -all %t_yes_off.o | FileCheck --check-prefix=CHECK-YES-OFF %s
5+
6+
; We don't need a line table for an empty function
7+
; CHECK-NO-OFF-NOT: DW_LNE_set_address
8+
9+
; CHECK-YES-OFF: DW_AT_LLVM_stmt_sequence [DW_FORM_sec_offset] ({{.*}})
10+
; CHECK-YES-OFF: Address
11+
; CHECK-YES-OFF-NEXT: ------------------
12+
; CHECK-YES-OFF-NEXT: DW_LNE_set_address ({{.*}})
13+
; CHECK-YES-OFF-NEXT: DW_LNE_end_sequence
14+
; CHECK-YES-OFF-NEXT: 0x0000000000000000 {{.*}} is_stmt end_sequence
15+
16+
; IR generated by llvm-reduce from LTO repro
17+
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"
18+
target triple = "x86_64-unknown-linux-gnu"
19+
20+
define ptr @_my_test_function() !dbg !4 {
21+
entry:
22+
unreachable
23+
}
24+
25+
!llvm.dbg.cu = !{!0}
26+
!llvm.module.flags = !{!3}
27+
28+
!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)
29+
!1 = !DIFile(filename: "repro_bug.cpp", directory: "/tmp/repro", checksumkind: CSK_MD5, checksum: "74e33e88b3108a4f94403da9fdb362f5")
30+
!2 = !{}
31+
!3 = !{i32 2, !"Debug Info Version", i32 3}
32+
!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)
33+
!5 = !DIFile(filename: "repro_bug.cpp", directory: "/tmp/repro", checksumkind: CSK_MD5, checksum: "74e33e88b3108a4f94403da9fdb362f5")
34+
!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "rectangle", file: !5, line: 103, size: 256, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2, vtableHolder: !7)
35+
!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")
36+
!8 = distinct !DISubroutineType(types: !2)
37+
!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)

0 commit comments

Comments
 (0)