Skip to content

Commit 26d9cb1

Browse files
authored
[MC][DebugInfo] Emit linetable entries with known offsets immediately (#134677)
DWARF linetable entries are usually emitted as a sequence of MCDwarfLineAddrFragment fragments containing the line-number difference and an MCExpr describing the instruction-range the linetable entry covers. These then get relaxed during assembly emission. However, a large number of these instruction-range expressions are ranges within a fixed MCDataFragment, i.e. a range over fixed-size instructions that are not subject to relaxation at a later stage. Thus, we can compute the address-delta immediately, and not spend time and memory describing that computation so it can be deferred.
1 parent 705e27c commit 26d9cb1

File tree

3 files changed

+112
-6
lines changed

3 files changed

+112
-6
lines changed

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,18 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
464464
Label, PointerSize);
465465
return;
466466
}
467+
468+
// If the two labels are within the same fragment, then the address-offset is
469+
// already a fixed constant and is not relaxable. Emit the advance-line-addr
470+
// data immediately to save time and memory.
471+
if (auto OptAddrDelta = absoluteSymbolDiff(Label, LastLabel)) {
472+
SmallString<16> Tmp;
473+
MCDwarfLineAddr::encode(getContext(), Assembler->getDWARFLinetableParams(),
474+
LineDelta, *OptAddrDelta, Tmp);
475+
emitBytes(Tmp);
476+
return;
477+
}
478+
467479
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc());
468480
insert(getContext().allocFragment<MCDwarfLineAddrFragment>(LineDelta,
469481
*AddrDelta));

llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
; LINE-DUMP: .debug_line contents:
3939
; LINE-DUMP-NEXT: debug_line[0x00000000]
4040
; LINE-DUMP-NEXT: Line table prologue:
41-
; LINE-DUMP-NEXT: total_length: 0x00000067
41+
; LINE-DUMP-NEXT: total_length: 0x00000061
4242
; LINE-DUMP-NEXT: format: DWARF32
4343
; LINE-DUMP-NEXT: version: 5
4444
; LINE-DUMP-NEXT: address_size: 4
@@ -83,12 +83,10 @@
8383
; LINE-DUMP-NEXT: 0x000000000000001c 3 5 0 0 0 0 is_stmt prologue_end
8484
; LINE-DUMP-NEXT:0x0000005d: 06 DW_LNS_negate_stmt
8585
; LINE-DUMP-NEXT:0x0000005e: 0b DW_LNS_set_epilogue_begin
86-
; LINE-DUMP-NEXT:0x0000005f: 03 DW_LNS_advance_line (3)
87-
; LINE-DUMP-NEXT:0x00000061: 09 DW_LNS_fixed_advance_pc (addr += 0x0004, op-index = 0)
88-
; LINE-DUMP-NEXT:0x00000064: 01 DW_LNS_copy
86+
; LINE-DUMP-NEXT:0x0000005f: 4a address += 4, line += 0, op-index += 0
8987
; LINE-DUMP-NEXT: 0x0000000000000020 3 5 0 0 0 0 epilogue_begin
90-
; LINE-DUMP-NEXT:0x00000065: 09 DW_LNS_fixed_advance_pc (addr += 0x0010, op-index = 0)
91-
; LINE-DUMP-NEXT:0x00000068: 00 DW_LNE_end_sequence
88+
; LINE-DUMP-NEXT:0x00000060: 02 DW_LNS_advance_pc (addr += 16, op-index += 0)
89+
; LINE-DUMP-NEXT:0x00000062: 00 DW_LNE_end_sequence
9290
; LINE-DUMP-NEXT: 0x0000000000000030 3 5 0 0 0 0 end_sequence
9391

9492
; ModuleID = 'dwarf-riscv-relocs.c'
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
; RUN: llc %s -o %t.o -filetype=obj
2+
; RUN: llvm-dwarfdump --debug-line %t.o | FileCheck %s --check-prefix=LINES
3+
; RUN: llc %s -o %t.o -filetype=obj -debug-only=mc-dump 2>&1 | FileCheck %s --check-prefix=FRAGMENTS
4+
;
5+
; REQUIRES: asserts
6+
7+
;; Test (using mc-dump debug output) that .debug_line can be arranged in memory
8+
;; using a single data fragment for a simple function, instead of using multiple
9+
;; MCDwarfFragment fragments in un-necessary cirucmstances. Some targets want
10+
;; multiple fragments so that they can linker-relax the linetable, but x86
11+
;; doesn't.
12+
;;
13+
;; First, sanity check that the linetable output is as expected,
14+
15+
; LINES: Address Line Column File ISA Discriminator OpIndex Flags
16+
; LINES-NEXT: ------------------ ------ ------ ------ --- ------------- ------- -------------
17+
; LINES-NEXT: 0x0000000000000000 3 5 0 0 0 0 is_stmt prologue_end
18+
; LINES-NEXT: 0x0000000000000003 4 12 0 0 0 0 is_stmt
19+
; LINES-NEXT: 0x0000000000000007 4 3 0 0 0 0
20+
; LINES-NEXT: 0x0000000000000008 4 3 0 0 0 0 end_sequence
21+
22+
;; Here's a typical example of .debug_line in a suboptimal arrangement: for each
23+
;; address-delta there's an MCDwarfFragment computing the delta during
24+
;; relaxation.
25+
;;
26+
;; <MCSection Name:.debug_line Fragments:[
27+
;; <MCDataFragment<MCFragment
28+
;; Contents:[...
29+
;; Fixups:[...
30+
;; <MCDwarfFragment<MCFragment 0x5624fe435a80 LayoutOrder:1 Offset:86 HasInstructions:0 BundlePadding:0>
31+
;; AddrDelta:- LineDelta:1>,
32+
;; <MCDataFragment<MCFragment 0x5624fe435b00 LayoutOrder:2 Offset:87 HasInstructions:0 BundlePadding:0>
33+
;; Contents:[05,03,06] (3 bytes)>,
34+
;; <MCDwarfFragment<MCFragment 0x5624fe435bd0 LayoutOrder:3 Offset:90 HasInstructions:0 BundlePadding:0>
35+
;; AddrDelta:- LineDelta:0>,
36+
;; <MCDwarfFragment<MCFragment 0x5624fe435c50 LayoutOrder:4 Offset:91 HasInstructions:0 BundlePadding:0>
37+
;; AddrDelta:- LineDelta:9223372036854775807>,
38+
;; <MCDataFragment<MCFragment 0x5624fe435cd0 LayoutOrder:5 Offset:96 HasInstructions:0 BundlePadding:0>
39+
;; Contents:[] (0 bytes)>]>,
40+
;;
41+
;; The function in question is made of a single data fragment where the address
42+
;; deltas are known at assembly time. We can (and should) emit .debug_line as a
43+
;; single data fragment. (Check that we see one data fragment, then no more
44+
;; fragments until the next section).
45+
;
46+
; FRAGMENTS: <MCSection Name:.debug_line Fragments:[
47+
; FRAGMENTS-NEXT: <MCDataFragment<MCFragment
48+
; FRAGMENTS-NEXT: Contents:[
49+
; FRAGMENTS-NEXT: Fixups:[
50+
;
51+
; FRAGMENTS-NOT: MCDataFragment
52+
; FRAGMENTS-NOT: MCFragment
53+
;
54+
; FRAGMENTS: <MCSection Name:.debug_line_str Fragments:[
55+
56+
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"
57+
target triple = "x86_64-unknown-linux-gnu"
58+
59+
define dso_local i32 @foo(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 !dbg !10 {
60+
entry:
61+
#dbg_value(i32 %a, !15, !DIExpression(), !17)
62+
#dbg_value(i32 %b, !16, !DIExpression(), !17)
63+
%add = add nsw i32 %a, 1, !dbg !18
64+
#dbg_value(i32 %add, !15, !DIExpression(), !17)
65+
%mul = mul nsw i32 %b, 5, !dbg !19
66+
#dbg_value(i32 %mul, !16, !DIExpression(), !17)
67+
%add1 = add nsw i32 %add, %mul, !dbg !20
68+
ret i32 %add1, !dbg !21
69+
}
70+
71+
!llvm.dbg.cu = !{!0}
72+
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
73+
!llvm.ident = !{!9}
74+
75+
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git (/fast/fs/llvm4 8bd196e0eaf4310ad2d9598512d13220b28b9aee)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
76+
!1 = !DIFile(filename: "text.c", directory: "/fast/fs/llvm-main", checksumkind: CSK_MD5, checksum: "e81ed96ea393640bf1b965103b190e09")
77+
!2 = !{i32 7, !"Dwarf Version", i32 5}
78+
!3 = !{i32 2, !"Debug Info Version", i32 3}
79+
!4 = !{i32 1, !"wchar_size", i32 4}
80+
!5 = !{i32 8, !"PIC Level", i32 2}
81+
!6 = !{i32 7, !"PIE Level", i32 2}
82+
!7 = !{i32 7, !"uwtable", i32 2}
83+
!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
84+
!9 = !{!"clang version 21.0.0git (/fast/fs/llvm4 8bd196e0eaf4310ad2d9598512d13220b28b9aee)"}
85+
!10 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
86+
!11 = !DISubroutineType(types: !12)
87+
!12 = !{!13, !13, !13}
88+
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
89+
!14 = !{!15, !16}
90+
!15 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 1, type: !13)
91+
!16 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !1, line: 1, type: !13)
92+
!17 = !DILocation(line: 0, scope: !10)
93+
!18 = !DILocation(line: 2, column: 5, scope: !10)
94+
!19 = !DILocation(line: 3, column: 5, scope: !10)
95+
!20 = !DILocation(line: 4, column: 12, scope: !10)
96+
!21 = !DILocation(line: 4, column: 3, scope: !10)

0 commit comments

Comments
 (0)