diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index e94616fd5900..a81d56e9618b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -365,7 +365,7 @@ static void addLocIfNotPresent(SmallVectorImpl &Locs, void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL, const MachineFunction *MF) { // Skip this instruction if it has the same location as the previous one. - if (DL == CurFn->LastLoc) + if (!DL || DL == PrevInstLoc) return; const DIScope *Scope = DL.get()->getScope(); @@ -385,11 +385,11 @@ void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL, if (!CurFn->HaveLineInfo) CurFn->HaveLineInfo = true; unsigned FileId = 0; - if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile()) + if (PrevInstLoc.get() && PrevInstLoc->getFile() == DL->getFile()) FileId = CurFn->LastFileId; else FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile()); - CurFn->LastLoc = DL; + PrevInstLoc = DL; unsigned FuncId = CurFn->FuncId; if (const DILocation *SiteLoc = DL->getInlinedAt()) { @@ -2150,9 +2150,23 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) { if (!Asm || !CurFn || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup)) return; + + // If the first instruction of a new MBB has no location, find the first + // instruction with a location and use that. DebugLoc DL = MI->getDebugLoc(); - if (DL == PrevInstLoc || !DL) + if (!DL && MI->getParent() != PrevInstBB) { + for (const auto &NextMI : *MI->getParent()) { + DL = NextMI.getDebugLoc(); + if (DL) + break; + } + } + PrevInstBB = MI->getParent(); + + // If we still don't have a debug location, don't record a location. + if (!DL) return; + maybeRecordLocation(DL, Asm->MF); } diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 2cd495aec6dc..fd8f60425c24 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -118,7 +118,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { SmallVector Locals; - DebugLoc LastLoc; const MCSymbol *Begin = nullptr; const MCSymbol *End = nullptr; unsigned FuncId = 0; diff --git a/llvm/test/DebugInfo/COFF/lines-bb-start.ll b/llvm/test/DebugInfo/COFF/lines-bb-start.ll new file mode 100644 index 000000000000..249b38d34998 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/lines-bb-start.ll @@ -0,0 +1,97 @@ +; RUN: llc -O0 < %s | FileCheck %s + +source_filename = "t.c" +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc19.0.24215" + +@str_const = internal unnamed_addr constant [4 x i8] c"str\00", align 1 + +declare i32 @puts(i8*) + +; We had a line info quality issue where the LEA for the string constant had no +; location info, so the .cv_loc directive appeared after it. Now we have logic +; that tries to emit the first valid location to the top of each MBB. + +define void @lea_str_loc(i1 %cond) !dbg !8 { +entry: + br i1 %cond, label %if.then, label %if.end, !dbg !17 + +if.then: ; preds = %entry + br label %return, !dbg !18 + +if.end: ; preds = %entry + %call = call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @str_const, i32 0, i32 0)), !dbg !19 + br label %return, !dbg !20 + +return: ; preds = %if.end, %if.then + ret void, !dbg !20 +} + +; The t.c:5 line marker should appear immediately after the BB label. + +; CHECK-LABEL: _lea_str_loc: +; CHECK: .cv_loc {{.*}} # t.c:4:5 +; CHECK: jmp LBB{{.*}} +; CHECK: LBB0_{{.*}}: # %if.end +; CHECK-NEXT: .cv_loc {{.*}} # t.c:5:3 +; CHECK-NEXT: leal _str_const, %[[reg:[^ ]*]] +; CHECK-NEXT: movl %[[reg]], (%esp) +; CHECK-NEXT: calll _puts + +define void @instr_no_loc(i1 %cond) !dbg !21 { +entry: + br i1 %cond, label %if.then, label %if.end, !dbg !22 + +if.then: ; preds = %entry + br label %return, !dbg !23 + +if.end: ; preds = %entry + call void asm sideeffect "nop", ""() + %call = call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @str_const, i32 0, i32 0)), !dbg !24 + br label %return, !dbg !25 + +return: ; preds = %if.end, %if.then + ret void, !dbg !25 +} + +; CHECK-LABEL: _instr_no_loc: +; CHECK: .cv_loc {{.*}} # t.c:4:5 +; CHECK: jmp LBB{{.*}} +; CHECK: LBB1_{{.*}}: # %if.end +; CHECK-NEXT: .cv_loc {{.*}} # t.c:5:3 +; CHECK-NEXT: #APP +; CHECK-NEXT: nop +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: leal _str_const, %[[reg:[^ ]*]] +; CHECK-NEXT: movl %[[reg]], (%esp) +; CHECK-NEXT: calll _puts + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "b32df088e991f1996b4e4deb3855c14b") +!2 = !{} +!3 = !{i32 1, !"NumRegisterParameters", i32 0} +!4 = !{i32 2, !"CodeView", i32 1} +!5 = !{i32 2, !"Debug Info Version", i32 3} +!6 = !{i32 1, !"wchar_size", i32 2} +!7 = !{!"clang version 5.0.0 "} +!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{null, !11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DIExpression() +!14 = !DILocation(line: 2, column: 12, scope: !8) +!15 = !DILocation(line: 3, column: 7, scope: !16) +!16 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3, column: 7) +!17 = !DILocation(line: 3, column: 7, scope: !8) +!18 = !DILocation(line: 4, column: 5, scope: !16) +!19 = !DILocation(line: 5, column: 3, scope: !8) +!20 = !DILocation(line: 6, column: 1, scope: !8) +!21 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!22 = !DILocation(line: 3, column: 7, scope: !21) +!23 = !DILocation(line: 4, column: 5, scope: !21) +!24 = !DILocation(line: 5, column: 3, scope: !21) +!25 = !DILocation(line: 6, column: 1, scope: !21) diff --git a/llvm/test/DebugInfo/COFF/local-variables.ll b/llvm/test/DebugInfo/COFF/local-variables.ll index c0bac0d174a9..249b6e1103db 100644 --- a/llvm/test/DebugInfo/COFF/local-variables.ll +++ b/llvm/test/DebugInfo/COFF/local-variables.ll @@ -193,7 +193,7 @@ ; OBJ: ChangeLineOffset: 1 ; OBJ: ChangeCodeOffset: 0x35 ; OBJ: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xD, LineOffset: 1} -; OBJ: ChangeCodeLength: 0xF +; OBJ: ChangeCodeLength: 0xA ; OBJ: ] ; OBJ: } ; OBJ: Local {