From 2cd77a84868638c82bda5b620838e775dbf4997c Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 1 Aug 2017 21:45:24 +0000 Subject: [PATCH] Remove PrologEpilogInserter's usage of DBG_VALUE's offset field In the last half-dozen commits to LLVM I removed code that became dead after removing the offset parameter from llvm.dbg.value gradually proceeding from IR towards the backend. Before I can move on to DwarfDebug and friends there is one last side-called offset I need to remove: This patch modifies PrologEpilogInserter's use of the DBG_VALUE's offset argument to use a DIExpression instead. Because the PrologEpilogInserter runs at the Machine level I had to play a little trick with a named llvm.dbg.mir node to get the DIExpressions to print in MIR dumps (which print the llvm::Module followed by the MachineFunction dump). I also had to add rudimentary DwarfExpression support to CodeView and as a side-effect also fixed a bug (CodeViewDebug::collectVariableInfo was supposed to give up on variables with complex DIExpressions, but would fail to do so for fragments, which are also modeled as DIExpressions). With this last holdover removed we will have only one canonical way of representing offsets to debug locations which will simplify the code in DwarfDebug (and future versions of CodeViewDebug once it starts handling more complex expressions) and make it easier to reason about. This patch is NFC-ish: All test case changes are for assembler comments and the binary output does not change. rdar://problem/33580047 Differential Revision: https://reviews.llvm.org/D36125 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309751 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineOperand.h | 5 +++++ lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 21 ++++++++++++++++----- lib/CodeGen/MachineModuleInfo.cpp | 4 +++- lib/CodeGen/PrologEpilogInserter.cpp | 13 +++++++++---- lib/IR/Verifier.cpp | 2 +- test/CodeGen/ARM/debug-info-arg.ll | 2 +- test/DebugInfo/ARM/PR16736.ll | 2 +- test/DebugInfo/COFF/pieces.ll | 2 +- test/DebugInfo/X86/bbjoin.ll | 3 ++- test/DebugInfo/X86/dbg-value-frame-index.ll | 2 +- test/DebugInfo/X86/debug-loc-asan.ll | 2 +- test/DebugInfo/X86/pieces-4.ll | 2 +- 12 files changed, 42 insertions(+), 18 deletions(-) diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 2560399bcf5..f1e6ac77860 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -549,6 +549,11 @@ public: Contents.OffsetedInfo.Val.Index = Idx; } + void setMetadata(const MDNode *MD) { + assert(isMetadata() && "Wrong MachineOperand mutator"); + Contents.MD = MD; + } + void setMBB(MachineBasicBlock *MBB) { assert(isMBB() && "Wrong MachineOperand mutator"); Contents.MBB = MBB; diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 38ae15cbd98..833e5bae1cf 100644 --- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeViewDebug.h" +#include "DwarfExpression.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -983,17 +984,29 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) { const MachineInstr *DVInst = Range.first; assert(DVInst->isDebugValue() && "Invalid History entry"); const DIExpression *DIExpr = DVInst->getDebugExpression(); + bool InMemory = DVInst->getOperand(1).isImm(); bool IsSubfield = false; unsigned StructOffset = 0; + // Recognize a +Offset expression. + int Offset = 0; + DIExpressionCursor Ops(DIExpr); + auto Op = Ops.peek(); + if (Op && Op->getOp() == dwarf::DW_OP_plus_uconst) { + Offset = Op->getArg(0); + Ops.take(); + } // Handle fragments. - auto Fragment = DIExpr->getFragmentInfo(); + auto Fragment = Ops.getFragmentInfo(); if (Fragment) { IsSubfield = true; StructOffset = Fragment->OffsetInBits / 8; - } else if (DIExpr->getNumElements() > 0) { - continue; // Ignore unrecognized exprs. } + // Ignore unrecognized exprs. + if (Ops.peek() && Ops.peek()->getOp() != dwarf::DW_OP_LLVM_fragment) + continue; + if (!InMemory && Offset) + continue; // Bail if operand 0 is not a valid register. This means the variable is a // simple constant, or is described by a complex expression. @@ -1006,8 +1019,6 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) { // Handle the two cases we can handle: indirect in memory and in register. unsigned CVReg = TRI->getCodeViewRegNum(Reg); - bool InMemory = DVInst->getOperand(1).isImm(); - int Offset = InMemory ? DVInst->getOperand(1).getImm() : 0; { LocalVarDefRange DR; DR.CVRegister = CVReg; diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 825290a438a..3999cd5eb7e 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -16,6 +16,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" @@ -209,7 +210,8 @@ bool MachineModuleInfo::doInitialization(Module &M) { DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false; AddrLabelSymbols = nullptr; TheModule = &M; - + if (getDebugMetadataVersionFromModule(M)) + M.getOrInsertNamedMetadata("llvm.dbg.mir"); return false; } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 63c839fcb0b..cbb43203b5c 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -31,6 +31,7 @@ #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/WinEHFuncInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" @@ -1079,11 +1080,15 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, assert(i == 0 && "Frame indices can only appear as the first " "operand of a DBG_VALUE machine instruction"); unsigned Reg; - MachineOperand &Offset = MI.getOperand(1); - Offset.setImm( - Offset.getImm() + - TFI->getFrameIndexReference(Fn, MI.getOperand(0).getIndex(), Reg)); + int64_t Offset = + TFI->getFrameIndexReference(Fn, MI.getOperand(0).getIndex(), Reg); MI.getOperand(0).ChangeToRegister(Reg, false /*isDef*/); + auto *DIExpr = DIExpression::prepend(MI.getDebugExpression(), + DIExpression::NoDeref, Offset); + MI.getOperand(3).setMetadata(DIExpr); + const Module *M = Fn.getMMI().getModule(); + // Add the expression to the metadata graph so isn't lost in MIR dumps. + M->getNamedMetadata("llvm.dbg.mir")->addOperand(DIExpr); continue; } diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 454a56a7692..e7362ea99b5 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -736,7 +736,7 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { // There used to be various other llvm.dbg.* nodes, but we don't support // upgrading them and we want to reserve the namespace for future uses. if (NMD.getName().startswith("llvm.dbg.")) - AssertDI(NMD.getName() == "llvm.dbg.cu", + AssertDI(NMD.getName() == "llvm.dbg.cu" || NMD.getName() == "llvm.dbg.mir", "unrecognized named metadata node in the llvm.dbg namespace", &NMD); for (const MDNode *MD : NMD.operands()) { diff --git a/test/CodeGen/ARM/debug-info-arg.ll b/test/CodeGen/ARM/debug-info-arg.ll index 5cf78f57dbc..026d45853d7 100644 --- a/test/CodeGen/ARM/debug-info-arg.ll +++ b/test/CodeGen/ARM/debug-info-arg.ll @@ -11,7 +11,7 @@ define void @foo(%struct.tag_s* nocapture %this, %struct.tag_s* %c, i64 %x, i64 tail call void @llvm.dbg.value(metadata %struct.tag_s* %c, metadata !13, metadata !DIExpression()), !dbg !21 tail call void @llvm.dbg.value(metadata i64 %x, metadata !14, metadata !DIExpression()), !dbg !22 tail call void @llvm.dbg.value(metadata i64 %y, metadata !17, metadata !DIExpression()), !dbg !23 -;CHECK: @DEBUG_VALUE: foo:y <- [%R7+8] +;CHECK: @DEBUG_VALUE: foo:y <- [DW_OP_plus_uconst 8] [%R7+0] tail call void @llvm.dbg.value(metadata %struct.tag_s* %ptr1, metadata !18, metadata !DIExpression()), !dbg !24 tail call void @llvm.dbg.value(metadata %struct.tag_s* %ptr2, metadata !19, metadata !DIExpression()), !dbg !25 %1 = icmp eq %struct.tag_s* %c, null, !dbg !26 diff --git a/test/DebugInfo/ARM/PR16736.ll b/test/DebugInfo/ARM/PR16736.ll index 59fb225902c..331495e8e91 100644 --- a/test/DebugInfo/ARM/PR16736.ll +++ b/test/DebugInfo/ARM/PR16736.ll @@ -2,7 +2,7 @@ ; RUN: llc -filetype=obj < %s \ ; RUN: | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF ; -; CHECK: @DEBUG_VALUE: h:x <- [%R{{.*}}+{{.*}}] +; CHECK: @DEBUG_VALUE: h:x <- [DW_OP_plus_uconst {{.*}}] [%R{{.*}}+0] ; DWARF: Location description: {{7[0-9] [0-9]+ $}} ; DW_OP_breg. +.. ; generated from: diff --git a/test/DebugInfo/COFF/pieces.ll b/test/DebugInfo/COFF/pieces.ll index 0832904ad4f..6d363cf5443 100644 --- a/test/DebugInfo/COFF/pieces.ll +++ b/test/DebugInfo/COFF/pieces.ll @@ -89,7 +89,7 @@ ; ASM: callq g ; ASM: movl %eax, [[offset_o_x:[0-9]+]](%rsp) # 4-byte Spill ; ASM: [[spill_o_x_start:\.Ltmp[0-9]+]]: -; ASM: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 32 32] [%RSP+[[offset_o_x]]] +; ASM: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_plus_uconst [[offset_o_x]], DW_OP_LLVM_fragment 32 32] [%RSP+0] ; ASM: #APP ; ASM: #NO_APP ; ASM: movl [[offset_o_x]](%rsp), %eax # 4-byte Reload diff --git a/test/DebugInfo/X86/bbjoin.ll b/test/DebugInfo/X86/bbjoin.ll index 2307a97b315..d9d0b1707df 100644 --- a/test/DebugInfo/X86/bbjoin.ll +++ b/test/DebugInfo/X86/bbjoin.ll @@ -9,10 +9,11 @@ ; ++x; ; return x; // check that x is not a constant here. ; } +; CHECK: ![[EXPR:.*]] = !DIExpression(DW_OP_plus_uconst, 4, DW_OP_deref) ; CHECK: ![[X:.*]] = !DILocalVariable(name: "x", ; CHECK: bb.0.entry: ; CHECK: DBG_VALUE 23, 0, ![[X]], -; CHECK: DBG_VALUE %rsp, 4, ![[X]] +; CHECK: DBG_VALUE %rsp, 0, ![[X]], ![[EXPR]], ; CHECK: bb.1.if.then: ; CHECK: DBG_VALUE 43, 0, ![[X]], ; CHECK: bb.2.if.end: diff --git a/test/DebugInfo/X86/dbg-value-frame-index.ll b/test/DebugInfo/X86/dbg-value-frame-index.ll index 0ac4dde3df0..30d91c8051e 100644 --- a/test/DebugInfo/X86/dbg-value-frame-index.ll +++ b/test/DebugInfo/X86/dbg-value-frame-index.ll @@ -20,7 +20,7 @@ while.end: } ; CHECK-LABEL: test -; CHECK: #DEBUG_VALUE: test:w <- [%RSP+8] +; CHECK: #DEBUG_VALUE: test:w <- [DW_OP_plus_uconst 8] [%RSP+0] ; DWARF: Location description: 77 08 ; DW_OP_breg7 +8 diff --git a/test/DebugInfo/X86/debug-loc-asan.ll b/test/DebugInfo/X86/debug-loc-asan.ll index ece93b9e89f..00790a4f092 100644 --- a/test/DebugInfo/X86/debug-loc-asan.ll +++ b/test/DebugInfo/X86/debug-loc-asan.ll @@ -17,7 +17,7 @@ ; CHECK: #DEBUG_VALUE: bar:y <- [DW_OP_deref] [%RDI+0] ; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp) ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]] -; CHECK-NEXT: #DEBUG_VALUE: bar:y <- [DW_OP_deref, DW_OP_deref] +; CHECK-NEXT: #DEBUG_VALUE: bar:y <- [DW_OP_plus_uconst [[OFFSET]], DW_OP_deref, DW_OP_deref] ; This location should be valid until the end of the function. ; CHECK: movq %rbp, %rsp diff --git a/test/DebugInfo/X86/pieces-4.ll b/test/DebugInfo/X86/pieces-4.ll index 105f4bed16d..c210272ed29 100644 --- a/test/DebugInfo/X86/pieces-4.ll +++ b/test/DebugInfo/X86/pieces-4.ll @@ -17,7 +17,7 @@ ; CHECK: callq g ; CHECK: movl %eax, [[offs:[0-9]+]](%rsp) # 4-byte Spill ; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 32 32] 0 -; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 0 32] [%RSP+[[offs]]] +; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_plus_uconst [[offs]], DW_OP_LLVM_fragment 0 32] [%RSP+0] ; CHECK: #APP ; CHECK: #NO_APP ; CHECK: movl [[offs]](%rsp), %eax # 4-byte Reload -- 2.11.0