diff --git a/llvm/lib/CodeGen/MachineDebugify.cpp b/llvm/lib/CodeGen/MachineDebugify.cpp --- a/llvm/lib/CodeGen/MachineDebugify.cpp +++ b/llvm/lib/CodeGen/MachineDebugify.cpp @@ -12,11 +12,17 @@ /// This isn't intended to have feature parity with Debugify. //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/InitializePasses.h" #include "llvm/Transforms/Utils/Debugify.h" @@ -28,13 +34,32 @@ bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI, DIBuilder &DIB, Function &F) { MachineFunction &MF = MMI.getOrCreateMachineFunction(F); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); DISubprogram *SP = F.getSubprogram(); assert(SP && "IR Debugify just created it?"); - LLVMContext &Ctx = F.getParent()->getContext(); + Module &M = *F.getParent(); + LLVMContext &Ctx = M.getContext(); unsigned NextLine = SP->getLine(); + // Find local variables defined by debugify. Later, we can insert DBG_VALUE + // insts that point to these local variables. + Function *DbgValF = M.getFunction("llvm.dbg.value"); + DenseMap Line2Var; + SmallVector DefinedValues; + DIExpression *Expr = nullptr; + if (DbgValF) { + for (const Use &U : DbgValF->uses()) { + if (auto *DbgValInst = dyn_cast(U.getUser())) { + Line2Var[DbgValInst->getDebugLoc().getLine()] = + DbgValInst->getVariable(); + if (!Expr) + Expr = DbgValInst->getExpression(); + } + } + } + for (MachineBasicBlock &MBB : MF) { for (MachineInstr &MI : MBB) { // This will likely emit line numbers beyond the end of the imagined @@ -42,9 +67,31 @@ // that as it doesn't really matter to the compiler where the line is in // the imaginary source code. MI.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); + + // Keep track of defined regs. This lets us insert DBG_VALUEs later. + for (MachineOperand &MO : MI.operands()) + if (MO.isReg() && MO.isDef() && MO.getReg()) + DefinedValues.push_back(&MO); } } + // Insert DBG_VALUEs for all defined regs. + // FIXME: This uses a matching-line heuristic to pair local variables with + // register definitions, which is pretty bogus. + const MCInstrDesc &DbgValDesc = TII.get(TargetOpcode::DBG_VALUE); + for (MachineOperand *MO : DefinedValues) { + MachineInstr &MI = *MO->getParent(); + // Just like at the IR level, it's not expected for there to be non-PHI + // instructions in between PHIs at the MIR level. + if (MI.isPHI()) + continue; + DILocalVariable *LocalVar = Line2Var[MI.getDebugLoc().getLine()]; + if (!LocalVar) + continue; + BuildMI(*MI.getParent(), std::next(MI.getIterator()), MI.getDebugLoc(), + DbgValDesc, /*IsIndirect=*/false, *MO, LocalVar, Expr); + } + return true; } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-phi-insertpt-decrement.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -O0 -mtriple=aarch64-unknown-unknown -verify-machineinstrs -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -debugify-and-strip-all-safe -O0 -mtriple=aarch64-unknown-unknown -verify-machineinstrs -run-pass=legalizer %s -o - | FileCheck %s --- | target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/CodeGen/Generic/MIRDebugify/locations.mir b/llvm/test/CodeGen/Generic/MIRDebugify/locations.mir --- a/llvm/test/CodeGen/Generic/MIRDebugify/locations.mir +++ b/llvm/test/CodeGen/Generic/MIRDebugify/locations.mir @@ -1,6 +1,6 @@ -# RUN: llc -run-pass=mir-debugify -o - %s | FileCheck --check-prefixes=ALL,VALUE %s +# RUN: llc -run-pass=mir-debugify -o - %s | FileCheck --check-prefixes=ALL,VALUE --implicit-check-not=DBG_VALUE %s # RUN: llc -run-pass=mir-debugify -debugify-level=locations -o - %s | FileCheck --check-prefixes=ALL --implicit-check-not=dbg.value %s -# RUN: llc -run-pass=mir-debugify,mir-strip-debug,mir-debugify -o - %s | FileCheck --check-prefixes=ALL,VALUE %s +# RUN: llc -run-pass=mir-debugify,mir-strip-debug,mir-debugify -o - %s | FileCheck --check-prefixes=ALL,VALUE --implicit-check-not=DBG_VALUE %s --- | ; ModuleID = 'loc-only.ll' source_filename = "loc-only.ll" @@ -17,11 +17,13 @@ ret i32 %sub } - ; CHECK: !llvm.dbg.cu = !{!0} - ; CHECK: !llvm.debugify = - ; CHECK: !llvm.module.flags = !{![[VERSION:[0-9]+]]} - ; CHECK: !0 = distinct !DICompileUnit( - ; CHECK: ![[VERSION]] = !{i32 2, !"Debug Info Version", i32 3} + ; ALL: !llvm.dbg.cu = !{!0} + ; ALL: !llvm.debugify = + ; ALL: !llvm.module.flags = !{![[VERSION:[0-9]+]]} + ; ALL: !0 = distinct !DICompileUnit( + ; ALL: ![[VERSION]] = !{i32 2, !"Debug Info Version", i32 3} + ; VALUE: [[VAR1:![0-9]+]] = !DILocalVariable(name: "1" + ; VALUE: [[VAR2:![0-9]+]] = !DILocalVariable(name: "2" ... --- @@ -37,7 +39,9 @@ ; source file anyway. These first three coincide with IR-level information ; and therefore use metadata references. ; ALL: %0:_(s32) = IMPLICIT_DEF debug-location [[L1]] + ; VALUE: DBG_VALUE %0(s32), $noreg, [[VAR1]], !DIExpression(), debug-location [[L1]] ; ALL: %1:_(s32) = IMPLICIT_DEF debug-location [[L2]] + ; VALUE: DBG_VALUE %1(s32), $noreg, [[VAR2]], !DIExpression(), debug-location [[L2]] ; ALL: %2:_(s32) = G_CONSTANT i32 2, debug-location [[L3]] ; ALL: %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: !6) ; ALL: %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: !6)