Index: include/llvm/CodeGen/MachineOperand.h =================================================================== --- include/llvm/CodeGen/MachineOperand.h +++ include/llvm/CodeGen/MachineOperand.h @@ -549,6 +549,11 @@ 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; Index: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ 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 @@ 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 @@ // 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; Index: lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- lib/CodeGen/MachineModuleInfo.cpp +++ 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 @@ DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false; AddrLabelSymbols = nullptr; TheModule = &M; - + if (getDebugMetadataVersionFromModule(M)) + M.getOrInsertNamedMetadata("llvm.dbg.mir"); return false; } Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ 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 @@ 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; } Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -736,7 +736,7 @@ // 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()) { Index: test/DebugInfo/ARM/PR16736.ll =================================================================== --- test/DebugInfo/ARM/PR16736.ll +++ 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: Index: test/DebugInfo/COFF/pieces.ll =================================================================== --- test/DebugInfo/COFF/pieces.ll +++ 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 Index: test/DebugInfo/X86/bbjoin.ll =================================================================== --- test/DebugInfo/X86/bbjoin.ll +++ 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: Index: test/DebugInfo/X86/dbg-value-frame-index.ll =================================================================== --- test/DebugInfo/X86/dbg-value-frame-index.ll +++ test/DebugInfo/X86/dbg-value-frame-index.ll @@ -20,7 +20,7 @@ } ; 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 Index: test/DebugInfo/X86/debug-loc-asan.ll =================================================================== --- test/DebugInfo/X86/debug-loc-asan.ll +++ 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 Index: test/DebugInfo/X86/pieces-4.ll =================================================================== --- test/DebugInfo/X86/pieces-4.ll +++ 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