[llvm] 7a930ce - [DWARF] Emit a minimal line-table for totally empty functions (#107267)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 9 04:54:48 PDT 2024
Author: Jeremy Morse
Date: 2024-09-09T12:54:45+01:00
New Revision: 7a930ce327fdbc5c77b50ee6304645084100c037
URL: https://github.com/llvm/llvm-project/commit/7a930ce327fdbc5c77b50ee6304645084100c037
DIFF: https://github.com/llvm/llvm-project/commit/7a930ce327fdbc5c77b50ee6304645084100c037.diff
LOG: [DWARF] Emit a minimal line-table for totally empty functions (#107267)
In degenerate but legal inputs, we can have functions that have no source
locations at all -- all the DebugLocs attached to instructions are empty.
LLVM didn't produce any source location for the function; with this patch
it will at least emit the function-scope source location. Demonstrated by
empty-line-info.ll
The XCOFF test modified has similar symptoms -- with this patch, the size
of the ".dwline" section grows a bit, thus shifting some of the file
internal offsets, which I've updated.
Added:
llvm/test/DebugInfo/X86/empty-line-info.ll
Modified:
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll
llvm/test/CodeGen/X86/pseudo_cmov_lower2.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index ea3fed8817d893..148b620c2b62b7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -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
diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll
index bc6e9f35019828..9c5d560e27f91e 100644
--- a/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll
@@ -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]]
@@ -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]]
@@ -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)
@@ -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)
diff --git a/llvm/test/CodeGen/X86/pseudo_cmov_lower2.ll b/llvm/test/CodeGen/X86/pseudo_cmov_lower2.ll
index f2c1269143fbc5..19253d67c14945 100644
--- a/llvm/test/CodeGen/X86/pseudo_cmov_lower2.ll
+++ b/llvm/test/CodeGen/X86/pseudo_cmov_lower2.ll
@@ -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:
diff --git a/llvm/test/DebugInfo/X86/empty-line-info.ll b/llvm/test/DebugInfo/X86/empty-line-info.ll
new file mode 100644
index 00000000000000..e726e5c882460c
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/empty-line-info.ll
@@ -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)
+
More information about the llvm-commits
mailing list