Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2053,11 +2053,36 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
if (NoDebug)
return;

auto RecordLineZero = [&]() {
// Preserve the file and column numbers, if we can, to save space in
// the encoded line table.
// Do not update PrevInstLoc, it remembers the last non-0 line.
const MDNode *Scope = nullptr;
unsigned Column = 0;
if (PrevInstLoc) {
Scope = PrevInstLoc.getScope();
Column = PrevInstLoc.getCol();
}
recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0);
};

// When we emit a line-0 record, we don't update PrevInstLoc; so look at
// the last line number actually emitted, to see if it was line 0.
unsigned LastAsmLine =
Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();

// Check if source location changes, but ignore DBG_VALUE and CFI locations.
// If the instruction is part of the function frame setup code, do not emit
// any line record, as there is no correspondence with any user code.
if (MI->isMetaInstruction() || MI->getFlag(MachineInstr::FrameSetup))
if (MI->isMetaInstruction())
return;
if (MI->getFlag(MachineInstr::FrameSetup)) {
// Prevent a loc from the previous block leaking into frame setup instrs.
if (LastAsmLine && PrevInstBB && PrevInstBB != MI->getParent())
RecordLineZero();
return;
}

const DebugLoc &DL = MI->getDebugLoc();
unsigned Flags = 0;

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

// When we emit a line-0 record, we don't update PrevInstLoc; so look at
// the last line number actually emitted, to see if it was line 0.
unsigned LastAsmLine =
Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();

// There may be a mixture of scopes using and not using Key Instructions.
// Not-Key-Instructions functions inlined into Key Instructions functions
// should use not-key is_stmt handling. Key Instructions functions inlined
Expand Down Expand Up @@ -2150,18 +2170,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
// - Instruction is at the top of a block; we don't want to inherit the
// location from the physically previous (maybe unrelated) block.
if (UnknownLocations == Enable || PrevLabel ||
(PrevInstBB && PrevInstBB != MI->getParent())) {
// Preserve the file and column numbers, if we can, to save space in
// the encoded line table.
// Do not update PrevInstLoc, it remembers the last non-0 line.
const MDNode *Scope = nullptr;
unsigned Column = 0;
if (PrevInstLoc) {
Scope = PrevInstLoc.getScope();
Column = PrevInstLoc.getCol();
}
recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0);
}
(PrevInstBB && PrevInstBB != MI->getParent()))
RecordLineZero();
return;
}

Expand Down
139 changes: 139 additions & 0 deletions llvm/test/DebugInfo/X86/shrink-wrap-frame-setup-no-loc.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# RUN: %llc_dwarf %s -o - -mtriple=x86_64-unknown-unknown | FileCheck %s

## Check the line number from the ret above `.LBB0_1` doesn't leak onto the
## frame setup instructions in the `.LBB0_1` block; `pushq %rax` should
## explicitly get set to line zero.

# CHECK: loop:
# CHECK-NEXT: .Lfunc_begin0:
# CHECK-NEXT: .cfi_startproc
# CHECK-NEXT: # %bb.0:
# CHECK-NEXT: .file 1 "/" "test.c"
# CHECK-NEXT: .loc 1 5 16 prologue_end # test.c:5:16
# CHECK-NEXT: testq %rax, %rax
# CHECK-NEXT: je .LBB0_1
# CHECK-NEXT: # %bb.2:
# CHECK-NEXT: .loc 1 5 16 # test.c:5:16
# CHECK-NEXT: retq
# CHECK-NEXT: .LBB0_1:
# -- Check the .loc below sets the current location to line 0.
# CHECK-NEXT: .loc 1 0 16 is_stmt 0 # test.c:0:16
# CHECK-NEXT: pushq %rax
# CHECK-NEXT: .cfi_def_cfa_offset 16
# CHECK-NEXT: addq $8, %rsp
# CHECK-NEXT: .cfi_def_cfa_offset 8
# CHECK-NEXT: .loc 1 5 16 is_stmt 1 # test.c:5:16
# CHECK-NEXT: retq

--- |
source_filename = "reduced.ll"
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-unknown"

define void @loop(i64 %i) !dbg !4 {
entry:
%cmp.not = icmp eq i64 %i, 0, !dbg !7
br i1 %cmp.not, label %for.body, label %for.end

for.body: ; preds = %entry
%puts10 = tail call i32 null(ptr null)
%inc = add i64 0, 0
br label %for.end

for.end: ; preds = %for.body, %entry
ret void
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3}

!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)
!1 = !DIFile(filename: "test.c", directory: "/")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!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)
!5 = !DISubroutineType(types: !6)
!6 = !{null}
!7 = !DILocation(line: 5, column: 16, scope: !8, atomGroup: 720, atomRank: 2)
!8 = distinct !DILexicalBlock(scope: !4, file: !1, line: 5, column: 9)
...
---
name: loop
alignment: 16
exposesReturnsTwice: false
legalized: false
regBankSelected: false
selected: false
failedISel: false
tracksRegLiveness: true
hasWinCFI: false
noPhis: false
isSSA: true
noVRegs: false
hasFakeUses: false
callsEHReturn: false
callsUnwindInit: false
hasEHContTarget: false
hasEHScopes: false
hasEHFunclets: false
isOutlined: false
debugInstrRef: false
failsVerification: false
tracksDebugUserValues: false
registers:
- { id: 0, class: gr64, preferred-register: '', flags: [ ] }
- { id: 1, class: gr32, preferred-register: '', flags: [ ] }
- { id: 2, class: gr64, preferred-register: '', flags: [ ] }
- { id: 3, class: gr32, preferred-register: '', flags: [ ] }
- { id: 4, class: gr64, preferred-register: '', flags: [ ] }
- { id: 5, class: gr32, preferred-register: '', flags: [ ] }
- { id: 6, class: gr32, preferred-register: '', flags: [ ] }
- { id: 7, class: gr64, preferred-register: '', flags: [ ] }
liveins: []
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 1
adjustsStack: false
hasCalls: true
stackProtector: ''
functionContext: ''
maxCallFrameSize: 4294967295
cvBytesOfCalleeSavedRegisters: 0
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
hasTailCall: false
isCalleeSavedInfoValid: false
localFrameSize: 0
fixedStack: []
stack: []
entry_values: []
callSites: []
debugValueSubstitutions: []
constants: []
machineFunctionInfo:
amxProgModel: None
body: |
bb.0:
successors: %bb.1(0x30000000), %bb.2(0x50000000)
liveins: $rdi

%7:gr64 = IMPLICIT_DEF
TEST64rr undef %7, undef %7, implicit-def $eflags, debug-location !7
JCC_1 %bb.2, 5, implicit $eflags
JMP_1 %bb.1

bb.1:
successors: %bb.2(0x80000000)

ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

bb.2:
RET 0, debug-location !7
...
Loading