Skip to content

Commit e69b7eb

Browse files
committed
[DWARF] Don't leak line numbers onto frame-setup instructions
Fixes issue #157887
1 parent c20ef94 commit e69b7eb

File tree

2 files changed

+167
-18
lines changed

2 files changed

+167
-18
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,11 +2053,36 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20532053
if (NoDebug)
20542054
return;
20552055

2056+
auto RecordLineZero = [&]() {
2057+
// Preserve the file and column numbers, if we can, to save space in
2058+
// the encoded line table.
2059+
// Do not update PrevInstLoc, it remembers the last non-0 line.
2060+
const MDNode *Scope = nullptr;
2061+
unsigned Column = 0;
2062+
if (PrevInstLoc) {
2063+
Scope = PrevInstLoc.getScope();
2064+
Column = PrevInstLoc.getCol();
2065+
}
2066+
recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0);
2067+
};
2068+
2069+
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
2070+
// the last line number actually emitted, to see if it was line 0.
2071+
unsigned LastAsmLine =
2072+
Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
2073+
20562074
// Check if source location changes, but ignore DBG_VALUE and CFI locations.
20572075
// If the instruction is part of the function frame setup code, do not emit
20582076
// any line record, as there is no correspondence with any user code.
2059-
if (MI->isMetaInstruction() || MI->getFlag(MachineInstr::FrameSetup))
2077+
if (MI->isMetaInstruction())
2078+
return;
2079+
if (MI->getFlag(MachineInstr::FrameSetup)) {
2080+
// Prevent a loc from the previous block leaking into frame setup instrs.
2081+
if (LastAsmLine && PrevInstBB && PrevInstBB != MI->getParent())
2082+
RecordLineZero();
20602083
return;
2084+
}
2085+
20612086
const DebugLoc &DL = MI->getDebugLoc();
20622087
unsigned Flags = 0;
20632088

@@ -2080,11 +2105,6 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20802105
LocationString);
20812106
};
20822107

2083-
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
2084-
// the last line number actually emitted, to see if it was line 0.
2085-
unsigned LastAsmLine =
2086-
Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
2087-
20882108
// There may be a mixture of scopes using and not using Key Instructions.
20892109
// Not-Key-Instructions functions inlined into Key Instructions functions
20902110
// should use not-key is_stmt handling. Key Instructions functions inlined
@@ -2150,18 +2170,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
21502170
// - Instruction is at the top of a block; we don't want to inherit the
21512171
// location from the physically previous (maybe unrelated) block.
21522172
if (UnknownLocations == Enable || PrevLabel ||
2153-
(PrevInstBB && PrevInstBB != MI->getParent())) {
2154-
// Preserve the file and column numbers, if we can, to save space in
2155-
// the encoded line table.
2156-
// Do not update PrevInstLoc, it remembers the last non-0 line.
2157-
const MDNode *Scope = nullptr;
2158-
unsigned Column = 0;
2159-
if (PrevInstLoc) {
2160-
Scope = PrevInstLoc.getScope();
2161-
Column = PrevInstLoc.getCol();
2162-
}
2163-
recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0);
2164-
}
2173+
(PrevInstBB && PrevInstBB != MI->getParent()))
2174+
RecordLineZero();
21652175
return;
21662176
}
21672177

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# RUN: %llc_dwarf %s -o - -mtriple=x86_64-unknown-unknown | FileCheck %s
2+
3+
## Check the line number from the ret above `.LBB0_1` doesn't leak onto the
4+
## frame setup instructions in the `.LBB0_1` block; `pushq %rax` should
5+
## explicitly get set to line zero.
6+
7+
# CHECK: loop:
8+
# CHECK-NEXT: .Lfunc_begin0:
9+
# CHECK-NEXT: .cfi_startproc
10+
# CHECK-NEXT: # %bb.0:
11+
# CHECK-NEXT: .file 1 "/" "test.c"
12+
# CHECK-NEXT: .loc 1 5 16 prologue_end # test.c:5:16
13+
# CHECK-NEXT: testq %rax, %rax
14+
# CHECK-NEXT: je .LBB0_1
15+
# CHECK-NEXT: # %bb.2:
16+
# CHECK-NEXT: .loc 1 5 16 # test.c:5:16
17+
# CHECK-NEXT: retq
18+
# CHECK-NEXT: .LBB0_1:
19+
# -- Check the .loc below sets the current location to line 0.
20+
# CHECK-NEXT: .loc 1 0 16 is_stmt 0 # test.c:0:16
21+
# CHECK-NEXT: pushq %rax
22+
# CHECK-NEXT: .cfi_def_cfa_offset 16
23+
# CHECK-NEXT: addq $8, %rsp
24+
# CHECK-NEXT: .cfi_def_cfa_offset 8
25+
# CHECK-NEXT: .loc 1 5 16 is_stmt 1 # test.c:5:16
26+
# CHECK-NEXT: retq
27+
28+
--- |
29+
source_filename = "reduced.ll"
30+
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"
31+
target triple = "x86_64-unknown-unknown"
32+
33+
define void @loop(i64 %i) !dbg !4 {
34+
entry:
35+
%cmp.not = icmp eq i64 %i, 0, !dbg !7
36+
br i1 %cmp.not, label %for.body, label %for.end
37+
38+
for.body: ; preds = %entry
39+
%puts10 = tail call i32 null(ptr null)
40+
%inc = add i64 0, 0
41+
br label %for.end
42+
43+
for.end: ; preds = %for.body, %entry
44+
ret void
45+
}
46+
47+
!llvm.dbg.cu = !{!0}
48+
!llvm.module.flags = !{!3}
49+
50+
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 22.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None)
51+
!1 = !DIFile(filename: "test.c", directory: "/")
52+
!2 = !{}
53+
!3 = !{i32 2, !"Debug Info Version", i32 3}
54+
!4 = distinct !DISubprogram(name: "loop", scope: !1, file: !1, line: 4, type: !5, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2, keyInstructions: true)
55+
!5 = !DISubroutineType(types: !6)
56+
!6 = !{null}
57+
!7 = !DILocation(line: 5, column: 16, scope: !8, atomGroup: 720, atomRank: 2)
58+
!8 = distinct !DILexicalBlock(scope: !4, file: !1, line: 5, column: 9)
59+
...
60+
---
61+
name: loop
62+
alignment: 16
63+
exposesReturnsTwice: false
64+
legalized: false
65+
regBankSelected: false
66+
selected: false
67+
failedISel: false
68+
tracksRegLiveness: true
69+
hasWinCFI: false
70+
noPhis: false
71+
isSSA: true
72+
noVRegs: false
73+
hasFakeUses: false
74+
callsEHReturn: false
75+
callsUnwindInit: false
76+
hasEHContTarget: false
77+
hasEHScopes: false
78+
hasEHFunclets: false
79+
isOutlined: false
80+
debugInstrRef: false
81+
failsVerification: false
82+
tracksDebugUserValues: false
83+
registers:
84+
- { id: 0, class: gr64, preferred-register: '', flags: [ ] }
85+
- { id: 1, class: gr32, preferred-register: '', flags: [ ] }
86+
- { id: 2, class: gr64, preferred-register: '', flags: [ ] }
87+
- { id: 3, class: gr32, preferred-register: '', flags: [ ] }
88+
- { id: 4, class: gr64, preferred-register: '', flags: [ ] }
89+
- { id: 5, class: gr32, preferred-register: '', flags: [ ] }
90+
- { id: 6, class: gr32, preferred-register: '', flags: [ ] }
91+
- { id: 7, class: gr64, preferred-register: '', flags: [ ] }
92+
liveins: []
93+
frameInfo:
94+
isFrameAddressTaken: false
95+
isReturnAddressTaken: false
96+
hasStackMap: false
97+
hasPatchPoint: false
98+
stackSize: 0
99+
offsetAdjustment: 0
100+
maxAlignment: 1
101+
adjustsStack: false
102+
hasCalls: true
103+
stackProtector: ''
104+
functionContext: ''
105+
maxCallFrameSize: 4294967295
106+
cvBytesOfCalleeSavedRegisters: 0
107+
hasOpaqueSPAdjustment: false
108+
hasVAStart: false
109+
hasMustTailInVarArgFunc: false
110+
hasTailCall: false
111+
isCalleeSavedInfoValid: false
112+
localFrameSize: 0
113+
fixedStack: []
114+
stack: []
115+
entry_values: []
116+
callSites: []
117+
debugValueSubstitutions: []
118+
constants: []
119+
machineFunctionInfo:
120+
amxProgModel: None
121+
body: |
122+
bb.0:
123+
successors: %bb.1(0x30000000), %bb.2(0x50000000)
124+
liveins: $rdi
125+
126+
%7:gr64 = IMPLICIT_DEF
127+
TEST64rr undef %7, undef %7, implicit-def $eflags, debug-location !7
128+
JCC_1 %bb.2, 5, implicit $eflags
129+
JMP_1 %bb.1
130+
131+
bb.1:
132+
successors: %bb.2(0x80000000)
133+
134+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
135+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
136+
137+
bb.2:
138+
RET 0, debug-location !7
139+
...

0 commit comments

Comments
 (0)