Skip to content

[DWARF] Emit a minimal line-table for totally empty functions #107267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 9, 2024
Merged
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
30 changes: 15 additions & 15 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2191,23 +2191,23 @@ DwarfDebug::emitInitialLocDirective(const MachineFunction &MF, unsigned CUID) {
const MachineInstr *PrologEndLoc = PrologEnd.first;
bool IsEmptyPrologue = PrologEnd.second;

// Get beginning of function.
if (PrologEndLoc) {
// If the prolog is empty, no need to generate scope line for the proc.
if (IsEmptyPrologue)
// If the prolog is empty, no need to generate scope line for the proc.
if (IsEmptyPrologue)
// In degenerate cases, we can have functions with no source locations
// at all. These want a scope line, to avoid a totally empty function.
// Thus, only skip scope line if there's location to place prologue_end.
if (PrologEndLoc)
return PrologEndLoc;

// Ensure the compile unit is created if the function is called before
// beginFunction().
DISubprogram *SP = MF.getFunction().getSubprogram();
(void)getOrCreateDwarfCompileUnit(SP->getUnit());
// We'd like to list the prologue as "not statements" but GDB behaves
// poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
::recordSourceLine(*Asm, SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT,
CUID, getDwarfVersion(), getUnits());
return PrologEndLoc;
}
return nullptr;
// Ensure the compile unit is created if the function is called before
// beginFunction().
DISubprogram *SP = MF.getFunction().getSubprogram();
(void)getOrCreateDwarfCompileUnit(SP->getUnit());
// We'd like to list the prologue as "not statements" but GDB behaves
// poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
::recordSourceLine(*Asm, SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT,
CUID, getDwarfVersion(), getUnits());
return PrologEndLoc;
}

// Gather pre-function debug information. Assumes being called immediately
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ define dso_local void @test__trap_annotation_debug(i32 %a) !dbg !4 {
; SYMS32-NEXT: NumberOfAuxEntries: 2
; SYMS32-NEXT: Function Auxiliary Entry {
; SYMS32-NEXT: Index: [[#IND+1]]
; SYMS32-NEXT: OffsetToExceptionTable: 0x2A8
; SYMS32-NEXT: OffsetToExceptionTable: 0x2B8
; SYMS32-NEXT: SizeOfFunction: 0xC
; SYMS32-NEXT: PointerToLineNum: 0x0
; SYMS32-NEXT: SymbolIndexOfNextBeyond: [[#IND+3]]
Expand All @@ -67,7 +67,7 @@ define dso_local void @test__trap_annotation_debug(i32 %a) !dbg !4 {
; SYMS32-NEXT: NumberOfAuxEntries: 2
; SYMS32-NEXT: Function Auxiliary Entry {
; SYMS32-NEXT: Index: [[#IND+4]]
; SYMS32-NEXT: OffsetToExceptionTable: 0x2B4
; SYMS32-NEXT: OffsetToExceptionTable: 0x2C4
; SYMS32-NEXT: SizeOfFunction: 0x34
; SYMS32-NEXT: PointerToLineNum: 0x0
; SYMS32-NEXT: SymbolIndexOfNextBeyond: [[#IND+6]]
Expand All @@ -93,7 +93,7 @@ define dso_local void @test__trap_annotation_debug(i32 %a) !dbg !4 {
; SYMS64-NEXT: NumberOfAuxEntries: 3
; SYMS64-NEXT: Exception Auxiliary Entry {
; SYMS64-NEXT: Index: [[#IND+1]]
; SYMS64-NEXT: OffsetToExceptionTable: 0x398
; SYMS64-NEXT: OffsetToExceptionTable: 0x3AC
; SYMS64-NEXT: SizeOfFunction: 0x18
; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+4]]
; SYMS64-NEXT: Auxiliary Type: AUX_EXCEPT (0xFF)
Expand Down Expand Up @@ -126,7 +126,7 @@ define dso_local void @test__trap_annotation_debug(i32 %a) !dbg !4 {
; SYMS64-NEXT: NumberOfAuxEntries: 3
; SYMS64-NEXT: Exception Auxiliary Entry {
; SYMS64-NEXT: Index: [[#IND+5]]
; SYMS64-NEXT: OffsetToExceptionTable: 0x3AC
; SYMS64-NEXT: OffsetToExceptionTable: 0x3C0
; SYMS64-NEXT: SizeOfFunction: 0x68
; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+8]]
; SYMS64-NEXT: Auxiliary Type: AUX_EXCEPT (0xFF)
Expand Down
6 changes: 6 additions & 0 deletions llvm/test/CodeGen/X86/pseudo_cmov_lower2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,20 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
; Like the test for @foo1, but check that the inserted dbg.value does not
; affect codegen. The CHECK items below should always be identical to @foo1,
; minus the DEBUG_VALUE line and changes in labels..
; We produce a scope-line source location for the entry block, and then
; explicitly terminate it in the second block, as there are no other source
; locations in the function.
define double @foo1_g(float %p1, double %p2, double %p3) nounwind !dbg !4 {
; CHECK-LABEL: foo1_g:
; CHECK: .file 1 "." "test.c"
; CHECK-NEXT: .loc 1 3 0
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: xorps %xmm3, %xmm3
; CHECK-NEXT: ucomiss %xmm3, %xmm0
; CHECK-NEXT: movsd {{.*#+}} xmm0 = [1.25E+0,0.0E+0]
; CHECK-NEXT: jae .LBB6_1
; CHECK-NEXT: # %bb.2: # %entry
; CHECK-NEXT: .loc 1 0 0 is_stmt 0
; CHECK-NEXT: addsd %xmm2, %xmm0
; CHECK-NEXT: jmp .LBB6_3
; CHECK-NEXT: .LBB6_1:
Expand Down
67 changes: 67 additions & 0 deletions llvm/test/DebugInfo/X86/empty-line-info.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
; RUN: llc -O2 %s -o - -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=OPTS
; RUN: llc -O0 %s -o - -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=UNOPT

;; Test that, even though there are no source locations attached to the foo
;; function, we still give it the start-of-function source location of the
;; definition line. Otherwise, this function would have no entry in the
;; line table at all.

; OPTS-LABEL: foo:
; OPTS-NEXT: .Lfunc_begin0:
; OPTS-NEXT: .file 0 "." "foobar.c"
; OPTS-NEXT: .loc 0 1 0
; OPTS-LABEL: bar:

define dso_local noundef i32 @foo(ptr nocapture noundef writeonly %bar) local_unnamed_addr !dbg !10 {
entry:
store i32 0, ptr %bar, align 4
ret i32 0
}

;; In a function with no source location, but multiple blocks, there will be
;; an opening scope-line, but it'll be automagically terminated when we switch
;; to a new block. Test for this behaviour, and preserve the unconditional
;; branch by compiling -O0.

; UNOPT-LABEL: bar:
; UNOPT-NEXT: .Lfunc_begin1:
; UNOPT-NEXT: .loc 0 11 0
; UNOPT-LABEL: %bb.0:
; UNOPT-NEXT: movq %rdi, -8(%rsp)
; UNOPT-NEXT: jmp .LBB1_1
; UNOPT-LABEL: .LBB1_1:
; UNOPT-NEXT: .loc 1 0 0 is_stmt 0
; UNOPT-NEXT: movq -8(%rsp), %rax

define dso_local noundef i32 @bar(ptr nocapture noundef writeonly %baz) local_unnamed_addr !dbg !20 {
entry:
br label %bb1
bb1:
store i32 0, ptr %baz, align 4
ret i32 0
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3}
!llvm.ident = !{!9}

!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "foobar.c", directory: ".")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{!"clang"}
!10 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !15)
!11 = !DISubroutineType(types: !12)
!12 = !{!13, !14}
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
!15 = !{!16}
!16 = !DILocalVariable(name: "bar", arg: 1, scope: !10, file: !1, line: 1, type: !14)
!17 = !DILocation(line: 0, scope: !10)
!18 = !DILocation(line: 2, column: 8, scope: !10)
!20 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 11, type: !11, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !25)
!25 = !{!26}
!26 = !DILocalVariable(name: "bar", arg: 1, scope: !20, file: !1, line: 11, type: !14)
!27 = !DILocation(line: 0, scope: !20)
!28 = !DILocation(line: 12, column: 8, scope: !20)

Loading