Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1313,6 +1313,20 @@ } } +static const DebugLoc & +findNextDebugLoc(MachineBasicBlock::const_iterator MBBI, + MachineBasicBlock::const_iterator MBBE) { + static DebugLoc NoLocation; + for ( ; MBBI != MBBE; ++MBBI) { + if (MBBI->isDebugInstr()) + continue; + const DebugLoc &DL = MBBI->getDebugLoc(); + if (DL) + return DL; + } + return NoLocation; +} + // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { DebugHandlerBase::beginInstruction(MI); @@ -1327,43 +1341,48 @@ // any line record, as there is no correspondence with any user code. if (MI->isMetaInstruction() || MI->getFlag(MachineInstr::FrameSetup)) return; - const DebugLoc &DL = MI->getDebugLoc(); + const DebugLoc *DL = &MI->getDebugLoc(); // 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(); - if (DL == PrevInstLoc) { + if (*DL == PrevInstLoc) { // If we have an ongoing unspecified location, nothing to do here. - if (!DL) + if (!*DL) return; // We have an explicit location, same as the previous location. // But we might be coming back to it after a line 0 record. - if (LastAsmLine == 0 && DL.getLine() != 0) { + if (LastAsmLine == 0 && DL->getLine() != 0) { // Reinstate the source location but not marked as a statement. - const MDNode *Scope = DL.getScope(); - recordSourceLine(DL.getLine(), DL.getCol(), Scope, /*Flags=*/0); + const MDNode *Scope = DL->getScope(); + recordSourceLine(DL->getLine(), DL->getCol(), Scope, /*Flags=*/0); } return; } - if (!DL) { + if (!*DL) { // We have an unspecified location, which might want to be line 0. // If we have already emitted a line-0 record, don't repeat it. if (LastAsmLine == 0) return; - // If user said Don't Do That, don't do that. - if (UnknownLocations == Disable) - return; - // See if we have a reason to emit a line-0 record now. - // Reasons to emit a line-0 record include: - // - User asked for it (UnknownLocations). - // - Instruction has a label, so it's referenced from somewhere else, - // possibly debug information; we want it to have a source location. - // - 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())) { + // By default we emit nothing to avoid line table bloat. However at the + // beginning of a basic block or after a label it is undesirable to let + // the previous location unchanged. In these cases do a forward search for + // the next valid debug location. + if (UnknownLocations == Default) { + const MachineBasicBlock &MBB = *MI->getParent(); + if (PrevLabel || PrevInstBB != &MBB) { + DL = &findNextDebugLoc(MI->getIterator(), MBB.end()); + } else { + return; + } + } + if (!*DL) { + // If user said Don't Do That, don't do that. + if (UnknownLocations == Disable) + return; + // Emit a line-0 record now. // 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. @@ -1374,32 +1393,33 @@ Column = PrevInstLoc.getCol(); } recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0); + return; } - return; } // We have an explicit location, different from the previous location. // Don't repeat a line-0 record, but otherwise emit the new location. // (The new location might be an explicit line 0, which we do emit.) - if (PrevInstLoc && DL.getLine() == 0 && LastAsmLine == 0) + unsigned Line = DL->getLine(); + if (PrevInstLoc && Line == 0 && LastAsmLine == 0) return; unsigned Flags = 0; - if (DL == PrologEndLoc) { + if (*DL == PrologEndLoc) { Flags |= DWARF2_FLAG_PROLOGUE_END | DWARF2_FLAG_IS_STMT; PrologEndLoc = DebugLoc(); } // If the line changed, we call that a new statement; unless we went to // line 0 and came back, in which case it is not a new statement. unsigned OldLine = PrevInstLoc ? PrevInstLoc.getLine() : LastAsmLine; - if (DL.getLine() && DL.getLine() != OldLine) + if (Line && Line != OldLine) Flags |= DWARF2_FLAG_IS_STMT; - const MDNode *Scope = DL.getScope(); - recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags); + const MDNode *Scope = DL->getScope(); + recordSourceLine(Line, DL->getCol(), Scope, Flags); // If we're not at line 0, remember this location. - if (DL.getLine()) - PrevInstLoc = DL; + if (Line) + PrevInstLoc = *DL; } static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { Index: test/DebugInfo/AArch64/line-header.ll =================================================================== --- test/DebugInfo/AArch64/line-header.ll +++ test/DebugInfo/AArch64/line-header.ll @@ -3,4 +3,4 @@ ; check line table length is correctly calculated for both big and little endian CHECK-LABEL: .debug_line contents: -CHECK: total_length: 0x0000003f +CHECK: total_length: 0x0000003c Index: test/DebugInfo/ARM/single-constant-use-preserves-dbgloc.ll =================================================================== --- test/DebugInfo/ARM/single-constant-use-preserves-dbgloc.ll +++ test/DebugInfo/ARM/single-constant-use-preserves-dbgloc.ll @@ -31,11 +31,10 @@ if.end: ; preds = %entry ; Materialize the constant. -; CHECK: .loc 1 0 +; CHECK: .loc 1 7 5 ; CHECK-NEXT: mvn r0, #0 ; The backend performs the store to %retval first, for some reason. -; CHECK-NEXT: .loc 1 7 5 ; CHECK-NEXT: str r0, [sp, #4] store i32 -1, i32* %x, align 4, !dbg !19 Index: test/DebugInfo/Mips/delay-slot.ll =================================================================== --- test/DebugInfo/Mips/delay-slot.ll +++ test/DebugInfo/Mips/delay-slot.ll @@ -16,7 +16,7 @@ ; CHECK: 0x0000000000000004 2 0 1 0 0 is_stmt prologue_end ; CHECK: 0x0000000000000024 3 0 1 0 0 is_stmt ; CHECK: 0x0000000000000034 4 0 1 0 0 is_stmt -; CHECK: 0x0000000000000048 5 0 1 0 0 is_stmt +; CHECK: 0x0000000000000044 5 0 1 0 0 is_stmt ; CHECK: 0x0000000000000058 5 0 1 0 0 is_stmt end_sequence Index: test/DebugInfo/NVPTX/debug-info.ll =================================================================== --- test/DebugInfo/NVPTX/debug-info.ll +++ test/DebugInfo/NVPTX/debug-info.ll @@ -36,6 +36,7 @@ ; CHECK: setp.ge.s32 %p{{.+}}, %r{{.+}}, %r{{.+}}; ; CHECK: .loc [[DEBUG_INFO_CU]] 7 7 ; CHECK: @%p{{.+}} bra [[BB:.+]]; +; CHECK: .loc [[DEBUG_INFO_CU]] 8 13 ; CHECK: ld.param.f32 %f{{.+}}, [{{.+}}]; ; CHECK: ld.param.u64 %rd{{.+}}, [{{.+}}]; ; CHECK: cvta.to.global.u64 %rd{{.+}}, %rd{{.+}}; @@ -43,7 +44,6 @@ ; CHECK: cvta.to.global.u64 %rd{{.+}}, %rd{{.+}}; ; CHECK: mul.wide.u32 %rd{{.+}}, %r{{.+}}, 4; ; CHECK: add.s64 %rd{{.+}}, %rd{{.+}}, %rd{{.+}}; -; CHECK: .loc [[DEBUG_INFO_CU]] 8 13 ; CHECK: ld.global.f32 %f{{.+}}, [%rd{{.+}}]; ; CHECK: add.s64 %rd{{.+}}, %rd{{.+}}, %rd{{.+}}; ; CHECK: .loc [[DEBUG_INFO_CU]] 8 19 Index: test/DebugInfo/X86/dwarf-no-source-loc.ll =================================================================== --- test/DebugInfo/X86/dwarf-no-source-loc.ll +++ test/DebugInfo/X86/dwarf-no-source-loc.ll @@ -40,15 +40,14 @@ ret void, !dbg !14 } -; CHECK: .loc 1 7 7 +; CHECK: .loc 1 7 7 prologue_end ; CHECK-NOT: .loc -; CHECK: .loc 1 0 7 is_stmt 0 +; CHECK: # %bb.1 +; CHECK-NEXT: .file 2 "/tests/include.h" +; CHECK-NEXT: .loc 2 20 5 ; CHECK-NOT: .loc -; CHECK: .loc 2 20 5 is_stmt 1 ; CHECK: .LBB0_2: -; CHECK-NEXT: .loc 2 0 5 is_stmt 0 -; CHECK-NOT: .loc -; CHECK: .loc 1 10 3 is_stmt 1 +; CHECK: .loc 1 10 3 ; ; DISABLE-NOT: .loc 1 0 Index: test/DebugInfo/X86/dwarf-no-source-loc.mir =================================================================== --- /dev/null +++ test/DebugInfo/X86/dwarf-no-source-loc.mir @@ -0,0 +1,74 @@ +# RUN: llc -o - %s -start-before=patchable-function -use-unknown-locations=Default | FileCheck %s --check-prefixes=CHECK,DEFAULT +# RUN: llc -o - %s -start-before=patchable-function -use-unknown-locations=Enable | FileCheck %s --check-prefixes=CHECK,ENABLE +# RUN: llc -o - %s -start-before=patchable-function -use-unknown-locations=Disable | FileCheck %s --check-prefixes=CHECK,DISABLE +--- | + target triple = "x86_64--" + + !0 = !DIFile(filename: "dwarf-no-source-loc.mir", directory: "/") + !1 = distinct !DICompileUnit(file: !0, language: DW_LANG_C, emissionKind: LineTablesOnly) + !2 = distinct !DISubprogram(name: "func", unit: !1) + !3 = !DILocation(line: 17, scope: !2) + !4 = !DILocation(line: 42, scope: !2) + + !llvm.dbg.cu = !{!1} + !llvm.module.flags = !{!10, !11} + !10 = !{i32 2, !"Dwarf Version", i32 4} + !11 = !{i32 2, !"Debug Info Version", i32 3} + + define void @func() !dbg !2 { + unreachable + } +... +--- +name: func +body: | + bb.0: + NOOP + NOOP + $eax = MOV32ri 1, debug-location !3 + ; CHECK-LABEL: bb.0 + ; CHECK: nop + ; CHECK: nop + ; CHECK: .loc 1 17 0 prologue_end + ; CHECK: movl $1, %eax + + bb.1: + NOOP + $ebx = MOV32ri 2, debug-location !4 + ; CHECK-LABEL: bb.1 + ; DEFAULT: .loc 1 42 0 + ; ENABLE: .loc 1 0 + ; DISABLE-NOT: .loc 1 0 + ; CHECK: nop + ; ENABLE: .loc 1 42 0 + ; CHECK: movl $2, %ebx + + bb.2: + NOOP + ; CHECK-LABEL: bb.2 + ; DEFAULT: .loc 1 0 0 is_stmt 0 + ; ENABLE: .loc 1 0 0 is_stmt 0 + ; DISABLE-NOT: .loc 1 0 + ; CHECK: nop + + bb.3: + NOOP + $ecx = MOV32ri 3, debug-location !3 + ; CHECK-LABEL: bb.3 + ; CHECK: nop + ; DEFAULT: .loc 1 17 0 is_stmt 1 + ; ENABLE: .loc 1 17 0 is_stmt 1 + ; DISABLE-NOT: .loc 1 0 + ; CHECK: movl $3, %ecx + + bb.4: + NOOP + $edx = MOV32ri 4, debug-location !4 + ; CHECK: bb.4 + ; DEFAULT: .loc 1 42 0 + ; ENABLE: .loc 1 0 0 is_stmt 0 + ; DISABLE-NOT: .loc 1 0 + ; CHECK: nop + ; ENABLE: .loc 1 42 0 is_stmt 1 + ; CHECK: movl $4, %edx +...