Index: llvm/lib/CodeGen/LiveDebugValues.cpp =================================================================== --- llvm/lib/CodeGen/LiveDebugValues.cpp +++ llvm/lib/CodeGen/LiveDebugValues.cpp @@ -114,6 +114,7 @@ class LiveDebugValues : public MachineFunctionPass { private: + MachineFunction *CurrentMF; const TargetRegisterInfo *TRI; const TargetInstrInfo *TII; const TargetFrameLowering *TFI; @@ -200,13 +201,13 @@ /// A pair of debug variable and value location. struct VarLoc { - // The location at which a spilled variable resides. It consists of a - // register and an offset. + // The location at which a spilled variable resides. It consists of an + // offset and a size, and is implicitly against the frame register. struct SpillLoc { - unsigned SpillBase; int SpillOffset; + unsigned int SpillSize; bool operator==(const SpillLoc &Other) const { - return SpillBase == Other.SpillBase && SpillOffset == Other.SpillOffset; + return SpillOffset == Other.SpillOffset && SpillSize == Other.SpillSize; } }; @@ -321,12 +322,33 @@ /// Take the variable described by DBG_VALUE MI, and create a VarLoc /// locating it in the specified spill location. - static VarLoc CreateSpillLoc(const MachineInstr &MI, unsigned SpillBase, - int SpillOffset, LexicalScopes &LS) { + static VarLoc CreateSpillLoc(const MachineInstr &MI, SpillLoc Loc, + LexicalScopes &LS) { VarLoc VL(MI, LS); assert(VL.Kind == RegisterKind); VL.Kind = SpillLocKind; - VL.Loc.SpillLocation = {SpillBase, SpillOffset}; + VL.Loc.SpillLocation = Loc; + return VL; + } + + /// Restore a location from a spill. The DBG_VALUE that this location is + /// rooted on could either be a register location that's been spilt in a + /// transfer; or it could be a DBG_VALUE of a stack location, created by + /// the register allocator. Determine which, and create a register + /// location representing the restore. + static VarLoc CreateRestoreLoc(const MachineInstr &MI, LexicalScopes &LS, + unsigned NewReg) { + VarLoc VL(MI, LS); + assert((VL.Kind == RegisterKind || VL.Kind == SpillLocKind) && + "Unexpected type of DBG_VALUE restored"); + + // If this was a spilt register-loc, we can use the expression from the + // original DBG_VALUE. Likewise, for spill locations, as the spill + // offset will not have been baked into the DIExpression yet, the + // expression can be re-used. We need only point the location to the + // new register. + VL.Kind = RegisterKind; + VL.Loc.RegNo = NewReg; return VL; } @@ -336,7 +358,6 @@ /// have been several transfers ago. MachineInstr *BuildDbgValue(MachineFunction &MF) const { const DebugLoc &DbgLoc = MI.getDebugLoc(); - bool Indirect = MI.isIndirectDebugValue(); const auto &IID = MI.getDesc(); const DILocalVariable *Var = MI.getDebugVariable(); const DIExpression *DIExpr = MI.getDebugExpression(); @@ -347,25 +368,34 @@ // expression. The register location of such DBG_VALUE is always the one // from the entry DBG_VALUE, it does not matter if the entry value was // copied in to another register due to some optimizations. - return BuildMI(MF, DbgLoc, IID, Indirect, MI.getOperand(0).getReg(), - Var, Expr); + return BuildMI(MF, DbgLoc, IID, false, MI.getOperand(0).getReg(), Var, + Expr); case RegisterKind: // Register locations are like the source DBG_VALUE, but with the // register number from this VarLoc. - return BuildMI(MF, DbgLoc, IID, Indirect, Loc.RegNo, Var, DIExpr); + return BuildMI(MF, DbgLoc, IID, false, Loc.RegNo, Var, DIExpr); case SpillLocKind: { // Spills are indirect DBG_VALUEs, with a base register and offset. // Use the original DBG_VALUEs expression to build the spilt location - // on top of. FIXME: spill locations created before this pass runs - // are not recognized, and not handled here. - auto *SpillExpr = DIExpression::prepend( - DIExpr, DIExpression::ApplyOffset, Loc.SpillLocation.SpillOffset); - unsigned Base = Loc.SpillLocation.SpillBase; - return BuildMI(MF, DbgLoc, IID, true, Base, Var, SpillExpr); + // on top of. + + auto *TRI = MF.getSubtarget().getRegisterInfo(); + unsigned FrameReg = TRI->getFrameRegister(MF); + if (DIExpr->isImplicit()) { + SmallVector Ops = {dwarf::DW_OP_deref_size, + Loc.SpillLocation.SpillSize}; + DIExpr = DIExpression::prependOpcodes(DIExpr, Ops); + DIExpr = DIExpression::prepend(DIExpr, DIExpression::ApplyOffset, + Loc.SpillLocation.SpillOffset); + } else { + DIExpr = DIExpression::prepend(DIExpr, DIExpression::DerefAfter, + Loc.SpillLocation.SpillOffset); + } + return BuildMI(MF, DbgLoc, IID, false, FrameReg, Var, DIExpr); } case ImmediateKind: { MachineOperand MO = MI.getOperand(0); - return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr); + return BuildMI(MF, DbgLoc, IID, false, MO, Var, DIExpr); } case EntryValueBackupKind: case EntryValueCopyBackupKind: @@ -414,7 +444,8 @@ #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) // TRI can be null. - void dump(const TargetRegisterInfo *TRI, raw_ostream &Out = dbgs()) const { + void dump(const MachineFunction *MF, raw_ostream &Out = dbgs()) const { + const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); dbgs() << "VarLoc("; switch (Kind) { case RegisterKind: @@ -424,7 +455,7 @@ dbgs() << printReg(Loc.RegNo, TRI); break; case SpillLocKind: - dbgs() << printReg(Loc.SpillLocation.SpillBase, TRI); + dbgs() << printReg(TRI->getFrameRegister(*MF), TRI); dbgs() << "[" << Loc.SpillLocation.SpillOffset << "]"; break; case ImmediateKind: @@ -566,7 +597,7 @@ unsigned &Reg); /// Given a spill instruction, extract the register and offset used to /// address the spill location in a target independent way. - VarLoc::SpillLoc extractSpillBaseRegAndOffset(const MachineInstr &MI); + VarLoc::SpillLoc extractSpillLocation(const MachineInstr &MI); void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers, VarLocMap &VarLocIDs, unsigned OldVarID, TransferKind Kind, @@ -603,6 +634,10 @@ SmallPtrSetImpl &ArtificialBlocks, VarLocInMBB &PendingInLocs); + /// Reduce any DBG_VALUE with a stack-slot index in its 1st operand into + /// an operation on the frame pointer. + void rewriteStackLocs(MachineFunction &MF); + /// Create DBG_VALUE insts for inlocs that have been propagated but /// had their instruction creation deferred. void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs); @@ -781,7 +816,7 @@ const VarLoc &VL = VarLocIDs[VLL]; Out << " Var: " << VL.Var.getVar()->getName(); Out << " MI: "; - VL.dump(TRI, Out); + VL.dump(&MF, Out); } } Out << "\n"; @@ -789,7 +824,7 @@ #endif LiveDebugValues::VarLoc::SpillLoc -LiveDebugValues::extractSpillBaseRegAndOffset(const MachineInstr &MI) { +LiveDebugValues::extractSpillLocation(const MachineInstr &MI) { assert(MI.hasOneMemOperand() && "Spill instruction does not have exactly one memory operand?"); auto MMOI = MI.memoperands_begin(); @@ -800,7 +835,8 @@ const MachineBasicBlock *MBB = MI.getParent(); unsigned Reg; int Offset = TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg); - return {Reg, Offset}; + (void)Reg; + return {Offset, (unsigned)(*MMOI)->getSize()}; } /// Try to salvage the debug entry value if we encounter a new debug value @@ -890,8 +926,21 @@ } unsigned ID; - if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() || - MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) { + + unsigned FrameReg = TRI->getFrameRegister(*MI.getMF()); + if (MI.isIndirectDebugValue() && MI.getOperand(0).isReg() && + MI.getOperand(0).getReg() == FrameReg) { + // This is a spill. Its offset should be in the "indirect" operand. + unsigned Reg; + int64_t FrameIdx = MI.getOperand(1).getImm(); + auto &MF = *MI.getMF(); + int64_t Offset = TFI->getFrameIndexReference(MF, FrameIdx, Reg); + unsigned Size = MF.getFrameInfo().getObjectSize(FrameIdx); + VarLoc VL = VarLoc::CreateSpillLoc(MI, {(int)Offset, Size}, LS); + ID = VarLocIDs.insert(VL); + OpenRanges.insert(ID, VL); + } else if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() || + MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) { // Use normal VarLoc constructor for registers and immediates. VarLoc VL(MI, LS); // End all previous ranges of VL.Var. @@ -974,20 +1023,19 @@ ProcessVarLoc(VL); LLVM_DEBUG({ dbgs() << "Creating VarLoc for register copy:"; - VL.dump(TRI); + VL.dump(CurrentMF); }); return; } case TransferKind::TransferSpill: { // Create a DBG_VALUE instruction to describe the Var in its spilled // location. - VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI); - VarLoc VL = VarLoc::CreateSpillLoc(*DebugInstr, SpillLocation.SpillBase, - SpillLocation.SpillOffset, LS); + VarLoc::SpillLoc SpillLocation = extractSpillLocation(MI); + VarLoc VL = VarLoc::CreateSpillLoc(*DebugInstr, SpillLocation, LS); ProcessVarLoc(VL); LLVM_DEBUG({ dbgs() << "Creating VarLoc for spill:"; - VL.dump(TRI); + VL.dump(CurrentMF); }); return; } @@ -996,11 +1044,11 @@ "No register supplied when handling a restore of a debug value"); // DebugInstr refers to the pre-spill location, therefore we can reuse // its expression. - VarLoc VL = VarLoc::CreateCopyLoc(*DebugInstr, LS, NewReg); + VarLoc VL = VarLoc::CreateRestoreLoc(*DebugInstr, LS, NewReg); ProcessVarLoc(VL); LLVM_DEBUG({ dbgs() << "Creating VarLoc for restore:"; - VL.dump(TRI); + VL.dump(CurrentMF); }); return; } @@ -1112,7 +1160,7 @@ // operand. if (MI.getRestoreSize(TII)) { Reg = MI.getOperand(0).getReg(); - return extractSpillBaseRegAndOffset(MI); + return extractSpillLocation(MI); } return None; } @@ -1140,7 +1188,7 @@ // will have changed. VarLocSet KillSet; if (isSpillInstruction(MI, MF)) { - Loc = extractSpillBaseRegAndOffset(MI); + Loc = extractSpillLocation(MI); for (unsigned ID : OpenRanges.getVarLocs()) { const VarLoc &VL = VarLocIDs[ID]; if (VL.Kind == VarLoc::SpillLocKind && VL.Loc.SpillLocation == *Loc) { @@ -1276,7 +1324,7 @@ : OpenRanges.getVarLocs()) { // Copy OpenRanges to OutLocs, if not already present. dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ": "; - VarLocIDs[ID].dump(TRI); + VarLocIDs[ID].dump(CurrentMF); }); VarLocSet &VLS = OutLocs[CurMBB]; Changed = VLS != OpenRanges.getVarLocs(); @@ -1460,6 +1508,42 @@ return Changed; } +void LiveDebugValues::rewriteStackLocs(MachineFunction &MF) { + for (auto &MBB : MF) { + for (auto &MI : MBB) { + if (!MI.isDebugValue()) + continue; + + // Examine only DBG_VALUEs with frame-indexes in the second operand. + if (!MI.getOperand(1).isImm()) + continue; + + // Fetch frame index details, un-set indirect field. + unsigned Reg; + int64_t FrameIdx = MI.getOperand(1).getImm(); + int64_t Offset = TFI->getFrameIndexReference(*MI.getMF(), FrameIdx, Reg); + unsigned Size = MF.getFrameInfo().getObjectSize(FrameIdx); + MI.getOperand(1).ChangeToRegister(0, false); + + const DIExpression *DIExpr = MI.getDebugExpression(); + + // Prepend the correct kind of deref onto the expression: big endian + // machines want to know the size when dealing with implicit locations. + if (DIExpr->isImplicit()) { + SmallVector Ops = {dwarf::DW_OP_deref_size, Size}; + DIExpr = DIExpression::prependOpcodes(DIExpr, Ops); + } else { + SmallVector Ops = {dwarf::DW_OP_deref}; + DIExpr = DIExpression::prependOpcodes(DIExpr, Ops); + } + + // Prepend the stack offset and attach the stack-location expression. + DIExpr = DIExpression::prepend(DIExpr, DIExpression::ApplyOffset, Offset); + MI.getOperand(3).setMetadata(DIExpr); + } + } +} + void LiveDebugValues::flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs) { // PendingInLocs records all locations propagated into blocks, which have @@ -1702,6 +1786,12 @@ // that now. flushPendingLocs(PendingInLocs, VarLocIDs); + // Input DBG_VALUEs that refer to stack spills must be rewritten in terms + // of the frame register and expression calculations. This must happen + // last, to avoid VarLocs creating new DBG_VALUEs based on expressions + // that have stack spill information in them. + rewriteStackLocs(MF); + LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "Final OutLocs", dbgs())); LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, "Final InLocs", dbgs())); return Changed; @@ -1717,6 +1807,7 @@ DICompileUnit::NoDebug) return false; + CurrentMF = &MF; TRI = MF.getSubtarget().getRegisterInfo(); TII = MF.getSubtarget().getInstrInfo(); TFI = MF.getSubtarget().getFrameLowering(); Index: llvm/lib/CodeGen/LiveDebugVariables.cpp =================================================================== --- llvm/lib/CodeGen/LiveDebugVariables.cpp +++ llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -1301,19 +1301,11 @@ ->isValidLocationForIntrinsic(getDebugLoc()) && "Expected inlined-at fields to agree"); - // If the location was spilled, the new DBG_VALUE will be indirect. If the - // original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate - // that the original virtual register was a pointer. Also, add the stack slot - // offset for the spilled register to the expression. - const DIExpression *Expr = Expression; - if (Spilled) - Expr = DIExpression::prepend(Expr, DIExpression::ApplyOffset, SpillOffset); - assert((!Spilled || MO.isFI()) && "a spilled location must be a frame index"); do { - BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE), - Spilled, MO, Variable, Expr); + BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE), Spilled, + MO, Variable, Expression); // Continue and insert DBG_VALUES after every redefinition of register // associated with the debug value within the range Index: llvm/lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1208,7 +1208,6 @@ "operand of a DBG_VALUE machine instruction"); unsigned Reg; unsigned FrameIdx = MI.getOperand(0).getIndex(); - unsigned Size = MF.getFrameInfo().getObjectSize(FrameIdx); int64_t Offset = TFI->getFrameIndexReference(MF, FrameIdx, Reg); @@ -1217,26 +1216,24 @@ const DIExpression *DIExpr = MI.getDebugExpression(); + // If this is an indirect debug value, store the frame offset in + // the "indirect" field, and let LiveDebugValues lower it to a + // DIExpression later. This makes it easier for LiveDebugValues to + // recognise and deal with spills/restores. + if (MI.isIndirectDebugValue()) { + MI.getOperand(1).setImm(FrameIdx); + continue; + } + // If we have a direct DBG_VALUE, and its location expression isn't // currently complex, then adding an offset will morph it into a // complex location that is interpreted as being a memory address. // This changes a pointer-valued variable to dereference that pointer, // which is incorrect. Fix by adding DW_OP_stack_value. unsigned PrependFlags = DIExpression::ApplyOffset; - if (!MI.isIndirectDebugValue() && !DIExpr->isComplex()) + if (!DIExpr->isComplex()) PrependFlags |= DIExpression::StackValue; - // If we have DBG_VALUE that is indirect and has a Implicit location - // expression need to insert a deref before prepending a Memory - // location expression. Also after doing this we change the DBG_VALUE - // to be direct. - if (MI.isIndirectDebugValue() && DIExpr->isImplicit()) { - SmallVector Ops = {dwarf::DW_OP_deref_size, Size}; - bool WithStackValue = true; - DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue); - // Make the DBG_VALUE direct. - MI.getOperand(1).ChangeToRegister(0, false); - } DIExpr = DIExpression::prepend(DIExpr, PrependFlags, Offset); MI.getOperand(3).setMetadata(DIExpr); continue; Index: llvm/test/CodeGen/ARM/dbg-range-extension.mir =================================================================== --- llvm/test/CodeGen/ARM/dbg-range-extension.mir +++ llvm/test/CodeGen/ARM/dbg-range-extension.mir @@ -31,7 +31,7 @@ # CHECK: DBG_VALUE [[REG_B]], $noreg, [[VAR_B]] # CHECK: DBG_VALUE [[REG_A]], $noreg, [[VAR_A]] # CHECK: DBG_VALUE [[REG_C:\$r[0-9]+]], $noreg, [[VAR_C]] -# CHECK: DBG_VALUE 1, 0, [[VAR_I]] +# CHECK: DBG_VALUE 1, $noreg, [[VAR_I]] # CHECK: bb.2.for.body # CHECK: DBG_VALUE [[REG_I:\$r[0-9]+]], $noreg, [[VAR_I]] @@ -239,7 +239,7 @@ $r6 = MOVr killed $r0, 14, $noreg, _, debug-location !26 DBG_VALUE $r6, $noreg, !15, !20, debug-location !27 $r7 = MOVi 1, 14, $noreg, $noreg - DBG_VALUE 1, 0, !18, !20, debug-location !28 + DBG_VALUE 1, $noreg, !18, !20, debug-location !28 B %bb.3.for.cond bb.2.for.body: Index: llvm/test/CodeGen/MIR/X86/diexpr-win32.mir =================================================================== --- llvm/test/CodeGen/MIR/X86/diexpr-win32.mir +++ llvm/test/CodeGen/MIR/X86/diexpr-win32.mir @@ -52,7 +52,7 @@ # CHECK-NEXT: BaseRegister: # CHECK-NEXT: HasSpilledUDTMember: No # CHECK-NEXT: OffsetInParent: 0 -# CHECK-NEXT: BasePointerOffset: -4 +# CHECK-NEXT: BasePointerOffset: 4 # CHECK-NEXT: LocalVariableAddrRange { # CHECK-NEXT: OffsetStart: # CHECK-NEXT: ISectStart: @@ -193,8 +193,8 @@ CFI_INSTRUCTION def_cfa_offset 8 CFI_INSTRUCTION offset $esi, -8 $esi = MOV32rm $esp, 1, _, 8, _ :: (load 4 from %fixed-stack.2) - DBG_VALUE $esp, 0, !26, !10, debug-location !25 - DBG_VALUE $esp, 0, !23, !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref), debug-location !25 + DBG_VALUE $esp, -2, !26, !10, debug-location !25 + DBG_VALUE $esp, -3, !23, !DIExpression(DW_OP_deref), debug-location !25 CALLpcrel32 @getString, csr_32, implicit $esp, implicit-def $esp, implicit-def $eax, debug-location !29 $ecx = MOV32rm $eax, 1, _, 0, _, debug-location !29 :: (dereferenceable load 4 from %ir.1) $edx = MOV32rm $eax, 1, _, 4, _, debug-location !29 :: (dereferenceable load 4 from %ir.1 + 4) @@ -245,7 +245,7 @@ bb.0.entry: $eax = MOV32rm $esp, 1, _, 4, _ :: (load 4 from %fixed-stack.1) $eax = MOV32rm killed $eax, 1, _, 0, _, debug-location !34 :: (load 4 from %ir.0) - DBG_VALUE $eax, 0, !35, !DIExpression(DW_OP_constu, 4, DW_OP_minus), debug-location !34 + DBG_VALUE $eax, -2, !35, !DIExpression(), debug-location !34 $eax = ADD32rm killed $eax, $esp, 1, _, 8, _, implicit-def dead $eflags, debug-location !36 :: (load 4 from %fixed-stack.0) RET 0, $eax, debug-location !36 Index: llvm/test/CodeGen/X86/prologepilog_deref_size.mir =================================================================== --- llvm/test/CodeGen/X86/prologepilog_deref_size.mir +++ llvm/test/CodeGen/X86/prologepilog_deref_size.mir @@ -1,4 +1,4 @@ -# RUN: llc -run-pass=prologepilog -o - %s | FileCheck %s +# RUN: llc -start-before=prologepilog -stop-after=livedebugvalues -o - %s | FileCheck %s --- | ; ModuleID = 'dbg.opt.ll' source_filename = "dbg.c" Index: llvm/test/DebugInfo/AArch64/compiler-gen-bbs-livedebugvalues.mir =================================================================== --- llvm/test/DebugInfo/AArch64/compiler-gen-bbs-livedebugvalues.mir +++ llvm/test/DebugInfo/AArch64/compiler-gen-bbs-livedebugvalues.mir @@ -84,24 +84,24 @@ renamable $w0 = ADDWri killed renamable $w0, 1, 0, debug-location !12 DBG_VALUE renamable $w0, $noreg, !9, !DIExpression(), debug-location !12 STRWui killed $w0, $sp, 3 :: (store 4 into %stack.0) - DBG_VALUE $sp, 0, !9, !DIExpression(DW_OP_plus_uconst, 12), debug-location !12 + DBG_VALUE $sp, 0, !9, !DIExpression(), debug-location !12 ; CHECK: DBG_VALUE renamable $w0, $noreg, !9, !DIExpression(), debug-location !12 ; CHECK-NEXT: STRWui killed $w0, $sp, 3 :: (store 4 into %stack.0) - ; CHECK-NEXT: DBG_VALUE $sp, 0, !9, !DIExpression(DW_OP_plus_uconst, 12) - ; CHECK-NEXT: DBG_VALUE $sp, 0, !9, !DIExpression(DW_OP_plus_uconst, 12) + ; CHECK-NEXT: DBG_VALUE $sp, $noreg, !9, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref) + ; CHECK-NEXT: DBG_VALUE $sp, $noreg, !9, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref) bb.1.artificial-bb-1: ; CHECK-LABEL: bb.1.artificial-bb-1: - ; CHECK: DBG_VALUE $sp, 0, !9, !DIExpression(DW_OP_plus_uconst, 12) + ; CHECK: DBG_VALUE $sp, $noreg, !9, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref) bb.2.artificial-bb-2: ; CHECK-LABEL: bb.2.artificial-bb-2: - ; CHECK: DBG_VALUE $sp, 0, !9, !DIExpression(DW_OP_plus_uconst, 12) + ; CHECK: DBG_VALUE $sp, $noreg, !9, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref) bb.3.return: ; CHECK-LABEL: bb.3.return: - ; CHECK: DBG_VALUE $sp, 0, !9, !DIExpression(DW_OP_plus_uconst, 12) + ; CHECK: DBG_VALUE $sp, $noreg, !9, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref) $w0 = LDRWui $sp, 3 :: (load 4 from %stack.0) BL @use, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit killed $w0 Index: llvm/test/DebugInfo/COFF/pieces.ll =================================================================== --- llvm/test/DebugInfo/COFF/pieces.ll +++ llvm/test/DebugInfo/COFF/pieces.ll @@ -99,12 +99,14 @@ ; 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_plus_uconst [[offset_o_x]], DW_OP_LLVM_fragment 32 32] [$rsp+0] +; ASM: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_plus_uconst [[offset_o_x]], DW_OP_deref, DW_OP_LLVM_fragment 32 32] $rsp ; ASM: #APP ; ASM: #NO_APP ; ASM: movl [[offset_o_x]](%rsp), %eax # 4-byte Reload -; ASM: retq ; ASM-NEXT: [[spill_o_x_end:\.Ltmp[0-9]+]]: +; ASM-NEXT: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 32 32] $eax +; ASM: retq +; ASM-NEXT: .Ltmp ; ASM-NEXT: .Lfunc_end4: @@ -231,7 +233,7 @@ ; ASM: .asciz "bitpiece_spill" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range [[spill_o_x_start]] .Lfunc_end4, reg_rel, 335, 65, 36 +; ASM: .cv_def_range [[spill_o_x_start]] [[spill_o_x_end]], reg_rel, 335, 65, 36 ; OBJ-LABEL: GlobalProcIdSym { ; OBJ: Kind: S_GPROC32_ID (0x1147) Index: llvm/test/DebugInfo/MIR/X86/kill-after-spill.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/kill-after-spill.mir +++ llvm/test/DebugInfo/MIR/X86/kill-after-spill.mir @@ -14,8 +14,8 @@ # ... # # CHECK: bb.1.if.end: -# CHECK: DBG_VALUE $rbp, 0, !37, !DIExpression(DW_OP_constu, 44, DW_OP_minus), debug-location !58 -# CHECK-NOT: DBG_VALUE $rbp, 0, !36, !DIExpression(DW_OP_constu, 48, DW_OP_minus), debug-location !57 +# CHECK: DBG_VALUE $rbp, $noreg, !37, !DIExpression(DW_OP_constu, 44, DW_OP_minus, DW_OP_deref), debug-location !58 +# CHECK-NOT: DBG_VALUE $rbp, $noreg, !36, !DIExpression(DW_OP_constu, 48, DW_OP_minus, DW_OP_deref), debug-location !57 --- | ; ModuleID = '' Index: llvm/test/DebugInfo/MIR/X86/live-debug-values-3preds.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/live-debug-values-3preds.mir +++ llvm/test/DebugInfo/MIR/X86/live-debug-values-3preds.mir @@ -190,7 +190,7 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $r8d = MOV32rr $esi, debug-location !26 $r8d = IMUL32rr killed $r8d, $edi, implicit-def dead $eflags, debug-location !26 TEST32rr $r8d, $r8d, implicit-def $eflags, debug-location !31 @@ -204,7 +204,7 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags bb.3.for.body (align 4): @@ -215,7 +215,7 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 TEST32rr $edi, $edi, implicit-def $eflags, debug-location !35 JCC_1 %bb.4.if.then, 15, implicit $eflags @@ -227,7 +227,7 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 TEST32rr $esi, $esi, implicit-def $eflags, debug-location !39 JCC_1 %bb.6.if.then.4, 15, implicit $eflags @@ -239,7 +239,7 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 TEST32rr $edx, $edx, implicit-def $eflags, debug-location !45 JCC_1 %bb.8.if.then.8, 15, implicit $eflags @@ -251,7 +251,7 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $eax = INC32r killed $eax, implicit-def dead $eflags, debug-location !44 DBG_VALUE $eax, _, !13, !17, debug-location !25 CMP32rr $eax, $r8d, implicit-def $eflags, debug-location !31 @@ -263,9 +263,9 @@ DBG_VALUE $edi, _, !9, !17, debug-location !18 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $ecx = IMUL32rr killed $ecx, killed $edi, implicit-def dead $eflags, debug-location !36 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $eax = MOV32rr killed $ecx, debug-location !50 RETQ $eax, debug-location !50 @@ -274,9 +274,9 @@ DBG_VALUE $esi, _, !10, !17, debug-location !19 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $ecx = IMUL32rr killed $ecx, killed $esi, implicit-def dead $eflags, debug-location !40 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $eax = MOV32rr killed $ecx, debug-location !50 RETQ $eax, debug-location !50 @@ -286,13 +286,13 @@ DBG_VALUE $edx, _, !11, !17, debug-location !21 DBG_VALUE $ecx, _, !12, !17, debug-location !23 - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $ecx = IMUL32rr killed $ecx, killed $edx, implicit-def dead $eflags, debug-location !46 bb.9.for.end: liveins: $ecx - DBG_VALUE 0, 0, !13, !17, debug-location !25 + DBG_VALUE 0, $noreg, !13, !17, debug-location !25 $eax = MOV32rr killed $ecx, debug-location !50 RETQ $eax, debug-location !50 Index: llvm/test/DebugInfo/MIR/X86/live-debug-values-restore-collide.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/live-debug-values-restore-collide.mir +++ llvm/test/DebugInfo/MIR/X86/live-debug-values-restore-collide.mir @@ -10,7 +10,7 @@ # CHECK-LABEL: name: baaar # CHECK-LABEL: bb.0.entry: # CHECK: DBG_VALUE $r9d, $noreg, !{{[0-9]*}}, !DIExpression() -# CHECK: DBG_VALUE $rsp, 0, !{{[0-9]*}}, !DIExpression(DW_OP_plus_uconst, 16) +# CHECK: DBG_VALUE $rsp, $noreg, !{{[0-9]*}}, !DIExpression(DW_OP_plus_uconst, 16, DW_OP_deref) # CHECK-NOT: DBG_VALUE --- | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @@ -72,7 +72,7 @@ ; Spill MOV32mr $rsp, 1, $noreg, 16, $noreg, $r9d :: (store 4 into %stack.0) - DBG_VALUE $rsp, 0, !9, !DIExpression(DW_OP_plus_uconst, 16), debug-location !10 + DBG_VALUE $rsp, 0, !9, !DIExpression(), debug-location !10 ; This load from the stack can be misinterpreted as a stack restore of ; any DBG_VALUe pointing at $rsp. Index: llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir +++ llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir @@ -29,7 +29,7 @@ # Ascertain that the spill has been recognized and manifested in a DBG_VALUE. # CHECK: MOV64mr $rsp,{{.*-8.*}}killed{{.*}}$rdi :: (store 8 into %stack.0) -# CHECK-NEXT: DBG_VALUE $rsp,{{.*}}![[PVAR]],{{.*}}!DIExpression(DW_OP_constu, 8, DW_OP_minus) +# CHECK-NEXT: DBG_VALUE $rsp, $noreg, ![[PVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref) # Check for the restore. # CHECK: $rdi = MOV64rm $rsp,{{.*-8.*}}:: (load 8 from %stack.0) @@ -408,15 +408,12 @@ # This third function tests that complex expressions are spilt, and restored # correctly within a basic block. -# FIXME: the spilt location below is wrong, there should be a deref between -# the spill-offset and the DW_OP_plus_uconst. - # CHECK-LABEL: name: h # CHECK-LABEL: bb.0.entry: # CHECK: DBG_VALUE $rdi, $noreg, ![[RVAR]], !DIExpression(DW_OP_plus_uconst, 1) # CHECK-LABEL: bb.1.if.then: # CHECK: DBG_VALUE $rdi, $noreg, ![[RVAR]], !DIExpression(DW_OP_plus_uconst, 1) -# CHECK: DBG_VALUE $rsp, 0, ![[RVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 1) +# CHECK: DBG_VALUE $rsp, $noreg, ![[RVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_plus_uconst, 1) # CHECK: DBG_VALUE $rdi, $noreg, ![[RVAR]], !DIExpression(DW_OP_plus_uconst, 1) # CHECK-LABEL: bb.2.if.end: # CHECK: DBG_VALUE $rdi, $noreg, ![[RVAR]], !DIExpression(DW_OP_plus_uconst, 1) @@ -518,8 +515,6 @@ # bb 2 and 3, neither of which modifies the stack loc. The exit block (3) # should still be tracking the spill, and restore it on stack load. -# FIXME: this test too contains a broken spill location. - # Summary: loc is in $rdi in bb0, spills to stack in bb1, remains in stack # in bb2, starts in stack then loaded in bb3. @@ -528,11 +523,11 @@ # CHECK: DBG_VALUE $rdi, $noreg, ![[SVAR]], !DIExpression(DW_OP_plus_uconst, 1) # CHECK-LABEL: bb.1.foo: # CHECK: DBG_VALUE $rdi, $noreg, ![[SVAR]], !DIExpression(DW_OP_plus_uconst, 1) -# CHECK: DBG_VALUE $rsp, 0, ![[SVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 1) +# CHECK: DBG_VALUE $rsp, $noreg, ![[SVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_plus_uconst, 1) # CHECK-LABEL: bb.2.if.then: -# CHECK: DBG_VALUE $rsp, 0, ![[SVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 1) +# CHECK: DBG_VALUE $rsp, $noreg, ![[SVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_plus_uconst, 1) # CHECK-LABEL: bb.3.if.end -# CHECK: DBG_VALUE $rsp, 0, ![[SVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 1) +# CHECK: DBG_VALUE $rsp, $noreg, ![[SVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_plus_uconst, 1) # CHECK: DBG_VALUE $rdi, $noreg, ![[SVAR]], !DIExpression(DW_OP_plus_uconst, 1) name: i alignment: 16 @@ -633,17 +628,15 @@ ... --- # Test that if an unspilt DBG_VALUE starts as an indirect DBG_VALUE, then it -# is restored as an indirect DBG_VALUE. FIXME: Note that for the intervening -# period of being a spilt location there is still a missing layer of -# indirection. +# is restored as an indirect DBG_VALUE. # CHECK-LABEL: name: j # CHECK-LABEL: bb.0.entry: -# CHECK: DBG_VALUE $rdi, 0, ![[TVAR]], !DIExpression() +# CHECK: DBG_VALUE $rdi, $noreg, ![[TVAR]], !DIExpression(DW_OP_deref) # CHECK-LABEL: bb.1.if.then: -# CHECK: DBG_VALUE $rsp, 0, ![[TVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus) +# CHECK: DBG_VALUE $rsp, $noreg, ![[TVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_deref) # CHECK: INLINEASM -# CHECK: DBG_VALUE ${{[a-zA-Z0-9]+}}, 0, ![[TVAR]], !DIExpression() +# CHECK: DBG_VALUE ${{[a-zA-Z0-9]+}}, $noreg, ![[TVAR]], !DIExpression(DW_OP_deref) # CHECK-LABEL: bb.2.if.end name: j @@ -684,8 +677,8 @@ successors: %bb.2, %bb.1 liveins: $rdi, $rbx, $r12, $r13, $r14, $r15, $rbp - DBG_VALUE $rdi, 0, !404, !DIExpression(), debug-location !405 - DBG_VALUE $rdi, 0, !404, !DIExpression(), debug-location !405 + DBG_VALUE $rdi, $noreg, !404, !DIExpression(DW_OP_deref), debug-location !405 + DBG_VALUE $rdi, $noreg, !404, !DIExpression(DW_OP_deref), debug-location !405 TEST64rr renamable $rdi, renamable $rdi, implicit-def $eflags, debug-location !406 JCC_1 %bb.2, 4, implicit $eflags, debug-location !408 Index: llvm/test/DebugInfo/MIR/X86/live-debug-values-spill.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/live-debug-values-spill.mir +++ llvm/test/DebugInfo/MIR/X86/live-debug-values-spill.mir @@ -53,29 +53,29 @@ # # GENERATE: bb.1.if.end: # GENERATE: MOV32mr $rbp, 1, $noreg, -48, $noreg, killed $edx :: (store 4 into %stack.5) -# GENERATE-NEXT: DBG_VALUE $rbp, 0, ![[INT0]], !DIExpression(DW_OP_constu, 48, DW_OP_minus) +# GENERATE-NEXT: DBG_VALUE $rbp, $noreg, ![[INT0]], !DIExpression(DW_OP_constu, 48, DW_OP_minus, DW_OP_deref) # GENERATE: MOV32mr $rbp, 1, $noreg, -52, $noreg, killed $r8d :: (store 4 into %stack.4) -# GENERATE-NEXT: DBG_VALUE $rbp, 0, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus) +# GENERATE-NEXT: DBG_VALUE $rbp, $noreg, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus, DW_OP_deref) # GENERATE: MOV32mr $rbp, 1, $noreg, -56, $noreg, killed $esi :: (store 4 into %stack.3) -# GENERATE-NEXT: DBG_VALUE $rbp, 0, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus) +# GENERATE-NEXT: DBG_VALUE $rbp, $noreg, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus, DW_OP_deref) # # Check that the spill locations that are valid at the end of bb.1.if.end are # propagated to subsequent BBs. # # GENERATE: bb.2.if.then4: # GENERATE-NOT: bb.3: -# GENERATE-DAG: DBG_VALUE $rbp, 0, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus) -# GENERATE-DAG: DBG_VALUE $rbp, 0, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus) +# GENERATE-DAG: DBG_VALUE $rbp, $noreg, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus, DW_OP_deref) +# GENERATE-DAG: DBG_VALUE $rbp, $noreg, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus, DW_OP_deref) # # GENERATE: bb.3: # GENERATE-NOT: bb.4.if.end13: -# GENERATE-DAG: DBG_VALUE $rbp, 0, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus) -# GENERATE-DAG: DBG_VALUE $rbp, 0, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus) +# GENERATE-DAG: DBG_VALUE $rbp, $noreg, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus, DW_OP_deref) +# GENERATE-DAG: DBG_VALUE $rbp, $noreg, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus, DW_OP_deref) # # GENERATE: bb.4.if.end13: # GENERATE-NOT: bb.5.cleanup: -# GENERATE-DAG: DBG_VALUE $rbp, 0, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus) -# GENERATE-DAG: DBG_VALUE $rbp, 0, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus) +# GENERATE-DAG: DBG_VALUE $rbp, $noreg, ![[INTD]], !DIExpression(DW_OP_constu, 56, DW_OP_minus, DW_OP_deref) +# GENERATE-DAG: DBG_VALUE $rbp, $noreg, ![[INTB]], !DIExpression(DW_OP_constu, 52, DW_OP_minus, DW_OP_deref) # # Check that the spill location rbp-48 (the variable int0) is not propagated # because int0 is redefined within the same basic block. @@ -369,31 +369,31 @@ CFI_INSTRUCTION offset $r13, -40 CFI_INSTRUCTION offset $r14, -32 CFI_INSTRUCTION offset $r15, -24 - DBG_VALUE $edi, _, !24, !38, debug-location !39 - DBG_VALUE $esi, _, !25, !38, debug-location !40 - DBG_VALUE $edx, _, !26, !38, debug-location !41 - DBG_VALUE $ecx, _, !27, !38, debug-location !42 - DBG_VALUE $r8d, _, !28, !38, debug-location !43 - DBG_VALUE $r9d, _, !29, !38, debug-location !44 + DBG_VALUE $edi, $noreg, !24, !38, debug-location !39 + DBG_VALUE $esi, $noreg, !25, !38, debug-location !40 + DBG_VALUE $edx, $noreg, !26, !38, debug-location !41 + DBG_VALUE $ecx, $noreg, !27, !38, debug-location !42 + DBG_VALUE $r8d, $noreg, !28, !38, debug-location !43 + DBG_VALUE $r9d, $noreg, !29, !38, debug-location !44 $r14d = MOV32rr $r8d - DBG_VALUE $r14d, _, !28, !38, debug-location !43 + DBG_VALUE $r14d, $noreg, !28, !38, debug-location !43 $r12d = MOV32rr $esi DBG_VALUE $r12d, _, !25, !38, debug-location !40 $eax = MOV32rr $edi - DBG_VALUE $eax, _, !24, !38, debug-location !39 + DBG_VALUE $eax, $noreg, !24, !38, debug-location !39 $r13d = MOV32rm $rip, 1, _, @glob0, _, debug-location !46 :: (dereferenceable load 4 from @glob0, !tbaa !47) - DBG_VALUE $r13d, _, !31, !38, debug-location !51 + DBG_VALUE $r13d, $noreg, !31, !38, debug-location !51 $r8d = MOV32rm $rip, 1, _, @glob1, _, debug-location !52 :: (dereferenceable load 4 from @glob1, !tbaa !47) - DBG_VALUE $r8d, _, !32, !38, debug-location !53 + DBG_VALUE $r8d, $noreg, !32, !38, debug-location !53 $r15d = MOV32rm $rip, 1, _, @glob2, _, debug-location !54 :: (dereferenceable load 4 from @glob2, !tbaa !47) - DBG_VALUE $r15d, _, !33, !38, debug-location !55 + DBG_VALUE $r15d, $noreg, !33, !38, debug-location !55 $esi = MOV32rm $rip, 1, _, @glob3, _, debug-location !56 :: (dereferenceable load 4 from @glob3, !tbaa !47) - DBG_VALUE $esi, _, !34, !38, debug-location !57 + DBG_VALUE $esi, $noreg, !34, !38, debug-location !57 $ebx = MOV32rm $rip, 1, _, @glob4, _, debug-location !59 :: (dereferenceable load 4 from @glob4, !tbaa !47) - DBG_VALUE $ebx, _, !35, !38, debug-location !60 + DBG_VALUE $ebx, $noreg, !35, !38, debug-location !60 MOV32mr $rbp, 1, _, -44, _, $ebx, debug-location !60 :: (store 4 into %ir.inte, !tbaa !47) $edi = MOV32rm $rip, 1, _, @glob5, _, debug-location !62 :: (dereferenceable load 4 from @glob5, !tbaa !47) - DBG_VALUE $edi, _, !36, !38, debug-location !63 + DBG_VALUE $edi, $noreg, !36, !38, debug-location !63 MOV32mr $rbp, 1, _, -60, _, $edi, debug-location !63 :: (store 4 into %ir.intf, !tbaa !47) TEST32rr killed $eax, $eax, implicit-def $eflags, debug-location !67 JCC_1 %bb.5.cleanup, 5, implicit $eflags @@ -405,11 +405,11 @@ MOV32mr $rbp, 1, _, -48, _, killed $edx :: (store 4 into %stack.5) MOV32mr $rbp, 1, _, -52, _, killed $r8d :: (store 4 into %stack.4) MOV32mr $rbp, 1, _, -56, _, killed $esi :: (store 4 into %stack.3) - DBG_VALUE _, _, !30, !38, debug-location !45 + DBG_VALUE $noreg, $noreg, !30, !38, debug-location !45 $r14d = ADD32rr killed $r14d, killed $ecx, implicit-def dead $eflags, debug-location !68 $r14d = ADD32rr killed $r14d, killed $r9d, implicit-def dead $eflags, debug-location !69 $r14d = IMUL32rm killed $r14d, $rbp, 1, _, 16, _, implicit-def dead $eflags, debug-location !70 :: (load 4 from %fixed-stack.6, align 16) - DBG_VALUE $r14d, _, !26, !38, debug-location !41 + DBG_VALUE $r14d, $noreg, !26, !38, debug-location !41 CALL64pcrel32 @use, csr_64, implicit $rsp, implicit $edi, implicit-def $rsp, debug-location !72 $edi = MOV32rr killed $ebx, debug-location !73 CALL64pcrel32 @use, csr_64, implicit $rsp, implicit $edi, implicit-def $rsp, debug-location !73 @@ -421,21 +421,21 @@ liveins: $r14d, $r15d, $rbp $rdi = LEA64r $rbp, 1, _, -44, _ - DBG_VALUE $rbp, -44, !35, !38, debug-location !60 + DBG_VALUE $rbp, 0, !35, !38, debug-location !60 $rsi = LEA64r $rbp, 1, _, -60, _ - DBG_VALUE $rbp, -60, !36, !38, debug-location !63 + DBG_VALUE $rbp, 1, !36, !38, debug-location !63 $rdx = LEA64r $rbp, 1, _, -64, _ - DBG_VALUE $rbp, -64, !37, !38, debug-location !78 + DBG_VALUE $rbp, 2, !37, !38, debug-location !78 CALL64pcrel32 @set, csr_64, implicit $rsp, implicit $rdi, implicit $rsi, implicit $rdx, implicit-def $rsp, debug-location !79 $eax = MOV32rm $rbp, 1, _, -44, _, debug-location !81 :: (dereferenceable load 4 from %ir.inte, !tbaa !47) - DBG_VALUE $eax, _, !35, !38, debug-location !60 + DBG_VALUE $eax, $noreg, !35, !38, debug-location !60 $r15d = ADD32rm killed $r15d, $rbp, 1, _, -52, _, implicit-def dead $eflags, debug-location !82 :: (load 4 from %stack.4) $r15d = IMUL32rr killed $r15d, $eax, implicit-def dead $eflags, debug-location !82 $r15d = ADD32rm killed $r15d, $rbp, 1, _, -56, _, implicit-def dead $eflags, debug-location !83 :: (load 4 from %stack.3) $r15d = IMUL32rr killed $r15d, killed $eax, implicit-def dead $eflags, debug-location !84 - DBG_VALUE $r15d, _, !31, !38, debug-location !51 + DBG_VALUE $r15d, $noreg, !31, !38, debug-location !51 $r13d = MOV32rr killed $r15d - DBG_VALUE $r13d, _, !31, !38, debug-location !51 + DBG_VALUE $r13d, $noreg, !31, !38, debug-location !51 JMP_1 %bb.4.if.end13 bb.2: @@ -443,17 +443,17 @@ liveins: $r13d, $r14d, $rbp $r14d = ADD32rm killed $r14d, $rbp, 1, _, -48, _, implicit-def dead $eflags, debug-location !71 :: (load 4 from %stack.5) - DBG_VALUE $r14d, _, !26, !38, debug-location !41 + DBG_VALUE $r14d, $noreg, !26, !38, debug-location !41 bb.4.if.end13: successors: %bb.5.cleanup(0x80000000) liveins: $r13d, $r14d, $rbp - DBG_VALUE $r14d, _, !26, !38, debug-location !41 - DBG_VALUE $r13d, _, !31, !38, debug-location !51 + DBG_VALUE $r14d, $noreg, !26, !38, debug-location !41 + DBG_VALUE $r13d, $noreg, !31, !38, debug-location !51 $r13d = IMUL32rm killed $r13d, $rbp, 1, _, 16, _, implicit-def dead $eflags, debug-location !86 :: (load 4 from %fixed-stack.6, align 16) $r13d = ADD32rr killed $r13d, killed $r14d, implicit-def dead $eflags, debug-location !87 - DBG_VALUE $r13d, _, !26, !38, debug-location !41 + DBG_VALUE $r13d, $noreg, !26, !38, debug-location !41 $edi = MOV32rr killed $r13d, debug-location !88 CALL64pcrel32 @use, csr_64, implicit $rsp, implicit $edi, implicit-def $rsp, debug-location !88 Index: llvm/test/DebugInfo/MIR/X86/live-debug-values-stack-clobber.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/live-debug-values-stack-clobber.mir +++ llvm/test/DebugInfo/MIR/X86/live-debug-values-stack-clobber.mir @@ -36,9 +36,11 @@ # These variables should be spilt, # CHECK-LABEL: bb.1.if.end: # CHECK: MOV64mr $rsp, 1, $noreg, 16, $noreg, killed renamable $rsi -# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[BNUM]], !DIExpression( +# CHECK-NEXT: DBG_VALUE $rsp, $noreg, ![[BNUM]], !DIExpression( +# CHECK-SAME: DW_OP_plus_uconst, 16, DW_OP_deref) # CHECK-NEXT: MOV64mr $rsp, 1, $noreg, 8, $noreg, killed renamable $rdi -# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[ANUM]], !DIExpression( +# CHECK-NEXT: DBG_VALUE $rsp, $noreg, ![[ANUM]], !DIExpression( +# CHECK-SAME: DW_OP_plus_uconst, 8, DW_OP_deref) # CHECK-NEXT: INLINEASM # # Then the location of "a" should be terminated when overwritten Index: llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir +++ llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir @@ -19,7 +19,7 @@ # CHECK-NEXT: DBG_VALUE $rsp, $noreg, ![[VAR3]], !DIExpression(DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_LLVM_tag_offset, 0, DW_OP_stack_value) # CHECK-NEXT: DBG_VALUE 1834104526 # CHECK-NEXT: MOV64mr -# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[VAR]], !DIExpression(DW_OP_plus_uconst, {{[0-9]+}}) +# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[VAR]], !DIExpression() --- | ; ModuleID = 'out.ll' Index: llvm/test/DebugInfo/PowerPC/live-debug-vars-subreg-offset.ll =================================================================== --- llvm/test/DebugInfo/PowerPC/live-debug-vars-subreg-offset.ll +++ llvm/test/DebugInfo/PowerPC/live-debug-vars-subreg-offset.ll @@ -33,7 +33,7 @@ ; CHECK: ![[VAR:.*]] = !DILocalVariable(name: "spilled" ; CHECK: STD $x3, 0, %stack.0 -; CHECK-NEXT: DBG_VALUE %stack.0, 0, ![[VAR]], !DIExpression(DW_OP_plus_uconst, 4) +; CHECK-NEXT: DBG_VALUE %stack.0, 0, ![[VAR]], !DIExpression() ; Function Attrs: noreturn nounwind define signext i32 @main() local_unnamed_addr #0 !dbg !8 { Index: llvm/test/DebugInfo/X86/dbg-declare-arg.ll =================================================================== --- llvm/test/DebugInfo/X86/dbg-declare-arg.ll +++ llvm/test/DebugInfo/X86/dbg-declare-arg.ll @@ -17,10 +17,14 @@ ; return my_a; ; } +; dbg.declare for agg.result becomes a single DBG_VALUE, appearing first in a +; spill slot, which is later restored into rcx. + ; CHECK: DW_AT_name {{.*}}"j" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ( -; CHECK-NEXT: [0x{{.*}}, 0x{{.*}}): DW_OP_breg7 RSP+16, DW_OP_deref) +; CHECK-NEXT: [0x{{.*}}, 0x{{.*}}): DW_OP_breg7 RSP+16, DW_OP_deref +; CHECK-NEXT: [0x{{.*}}, 0x{{.*}}): DW_OP_breg2 RCX+0) ; CHECK-NEXT: DW_AT_name {{.*}}"my_a" %class.A = type { i32, i32, i32, i32 } Index: llvm/test/DebugInfo/X86/dbg-value-of-spill-with-fp.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/dbg-value-of-spill-with-fp.ll @@ -0,0 +1,83 @@ +; RUN: llc -start-after=codegenprepare %s -mtriple=i386-unknown-unknown -filetype=obj -o - | llvm-dwarfdump - --name=result | FileCheck %s + +; Like dbg-value-when-spilt.ll, but testing what happens when we have a stack +; spill location and the stack pointer is modified. LiveDebugValues could +; interpret the spilt-location as being invalidated by $esp being def'd, for +; example by pushing a value onto the stack during a call (@extern below). +; It shouldn't -- the debugger should be aware of the call site and take +; account of it. + +; FIXME: While LiveDebugValues handles this correctly, +; DbgEntityHistoryCalculator still terminates the location of 'result' early, +; hence there's a gap (and repeated location spec) in the DWARF produced. + +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_location +; CHECK-NEXT: DW_OP_breg4 ESP+[[SLOT:[0-9]]] +; CHECK-NEXT: DW_OP_breg4 ESP+[[SLOT]] +; CHECK-NEXT: DW_OP_reg0 EAX) + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@someglobal = global i32 0 + +define i32 @_Z10get_stringv() !dbg !7 { +entry: + %somearg = load i32, i32 *@someglobal + %nrvo = alloca i1, align 1 + store i1 false, i1* %nrvo, align 1, !dbg !24 + call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{edx},~{esi},~{edi},~{ebp},~{dirflag},~{fpsr},~{flags}"(), !dbg !24, !srcloc !28 + call void @llvm.dbg.value(metadata i32 %somearg, metadata !23, metadata !DIExpression()), !dbg !24 + call void @extern(i32 0), !dbg !24 + call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{edx},~{esi},~{edi},~{ebp},~{dirflag},~{fpsr},~{flags}"(), !dbg !24, !srcloc !28 + store i1 true, i1* %nrvo, align 1, !dbg !24 + %nrvo.val = load i1, i1* %nrvo, align 1, !dbg !24 + br i1 %nrvo.val, label %blocka, label %blockb, !dbg !24 + +blocka: + store i32 0, i32 *@someglobal + br label %exit, !dbg !24 + +blockb: + store i32 1, i32 *@someglobal + br label %exit, !dbg !24 + +exit: + ret i32 %somearg, !dbg !24 +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) + +declare void @extern(i32) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 6.0.0 "} +!7 = distinct !DISubprogram(name: "get_string", linkageName: "_Z10get_stringv", scope: !1, file: !1, line: 13, type: !8, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !22) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 7, size: 32, elements: !11, identifier: "_ZTS6string") +!11 = !{!12, !14, !18, !21} +!12 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 11, baseType: !13, size: 32) +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DISubprogram(name: "string", scope: !10, file: !1, line: 8, type: !15, isLocal: false, isDefinition: false, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17} +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!18 = !DISubprogram(name: "string", scope: !10, file: !1, line: 9, type: !19, isLocal: false, isDefinition: false, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true) +!19 = !DISubroutineType(types: !20) +!20 = !{null, !17, !13} +!21 = !DISubprogram(name: "~string", scope: !10, file: !1, line: 10, type: !15, isLocal: false, isDefinition: false, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: true) +!22 = !{!23} +!23 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 14, type: !10) +!24 = !DILocation(line: 14, column: 3, scope: !7) +!28 = !{i32 -2147471175} Index: llvm/test/DebugInfo/X86/dbg-value-when-spilt.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/dbg-value-when-spilt.ll @@ -0,0 +1,79 @@ +; RUN: llc -start-after=codegenprepare %s -mtriple=x86_64-unknown-unknown -filetype=obj -o - | llvm-dwarfdump - --name=result | FileCheck %s + +; This is a copy of spill-indirect-nrvo.ll, testing that if we have a +; dbg.value of a Value at a point where it's in a spill slot, then we should +; be able to track through subsequent loads, regardless of implementation. + +; FIXME: Originally there was a conditional a call before return +; (see spill-indirect-nrvo.ll); the spilt value was loaded into $rbx before +; the call, but LiveDebugValues missed the later copy to $rax for return. + +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_location +; CHECK-NEXT: DW_OP_breg7 RSP+{{[0-9]}} +; CHECK-NEXT: DW_OP_reg0 RAX) + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64--linux" + +@someglobal = global i32 0 + +define i32 @_Z10get_stringv(i32 %somearg) !dbg !7 { +entry: + %nrvo = alloca i1, align 1 + store i1 false, i1* %nrvo, align 1, !dbg !24 + call void @extern(i32 %somearg), !dbg !24 + call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"(), !dbg !24, !srcloc !28 + call void @llvm.dbg.value(metadata i32 %somearg, metadata !23, metadata !DIExpression()), !dbg !24 + call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"(), !dbg !24, !srcloc !28 + store i1 true, i1* %nrvo, align 1, !dbg !24 + %nrvo.val = load i1, i1* %nrvo, align 1, !dbg !24 + br i1 %nrvo.val, label %blocka, label %blockb, !dbg !24 + +blocka: + store i32 0, i32 *@someglobal + br label %exit, !dbg !24 + +blockb: + store i32 1, i32 *@someglobal + br label %exit, !dbg !24 + +exit: + ret i32 %somearg, !dbg !24 +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) + +declare void @extern(i32) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 6.0.0 "} +!7 = distinct !DISubprogram(name: "get_string", linkageName: "_Z10get_stringv", scope: !1, file: !1, line: 13, type: !8, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !22) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 7, size: 32, elements: !11, identifier: "_ZTS6string") +!11 = !{!12, !14, !18, !21} +!12 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 11, baseType: !13, size: 32) +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DISubprogram(name: "string", scope: !10, file: !1, line: 8, type: !15, isLocal: false, isDefinition: false, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17} +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!18 = !DISubprogram(name: "string", scope: !10, file: !1, line: 9, type: !19, isLocal: false, isDefinition: false, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true) +!19 = !DISubroutineType(types: !20) +!20 = !{null, !17, !13} +!21 = !DISubprogram(name: "~string", scope: !10, file: !1, line: 10, type: !15, isLocal: false, isDefinition: false, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: true) +!22 = !{!23} +!23 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 14, type: !10) +!24 = !DILocation(line: 14, column: 3, scope: !7) +!28 = !{i32 -2147471175} Index: llvm/test/DebugInfo/X86/fission-ranges.ll =================================================================== --- llvm/test/DebugInfo/X86/fission-ranges.ll +++ llvm/test/DebugInfo/X86/fission-ranges.ll @@ -10,11 +10,11 @@ ; LiveDebugValues should produce DBG_VALUEs for variable "b" in successive ; blocks once we recognize that it is spilled. ; CHECK-MIR: ![[BDIVAR:[0-9]+]] = !DILocalVariable(name: "b" -; CHECK-MIR: DBG_VALUE $rsp, 0, ![[BDIVAR]], !DIExpression(DW_OP_constu, 32, DW_OP_minus) +; CHECK-MIR: DBG_VALUE $rsp, $noreg, ![[BDIVAR]], !DIExpression(DW_OP_constu, 32, DW_OP_minus, DW_OP_deref) ; CHECK-MIR-LABEL: bb.6.for.inc13: -; CHECK-MIR: DBG_VALUE $rsp, 0, ![[BDIVAR]], !DIExpression(DW_OP_constu, 32, DW_OP_minus) +; CHECK-MIR: DBG_VALUE $rsp, $noreg, ![[BDIVAR]], !DIExpression(DW_OP_constu, 32, DW_OP_minus, DW_OP_deref) ; CHECK-MIR-LABEL: bb.7.for.inc16: -; CHECK-MIR: DBG_VALUE $rsp, 0, ![[BDIVAR]], !DIExpression(DW_OP_constu, 32, DW_OP_minus) +; CHECK-MIR: DBG_VALUE $rsp, $noreg, ![[BDIVAR]], !DIExpression(DW_OP_constu, 32, DW_OP_minus, DW_OP_deref) ; CHECK: .debug_info contents: Index: llvm/test/DebugInfo/X86/op_deref.ll =================================================================== --- llvm/test/DebugInfo/X86/op_deref.ll +++ llvm/test/DebugInfo/X86/op_deref.ll @@ -27,6 +27,10 @@ ; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s --check-prefix=PRETTY-PRINT ; PRETTY-PRINT: DIExpression() +; XFAIL: * +; See the for.body block, LiveDebugValues sees a stack load and moves the +; variable location with it, rather than leaving it alone. + define void @testVLAwithSize(i32 %s) nounwind uwtable ssp !dbg !5 { entry: %s.addr = alloca i32, align 4 @@ -56,6 +60,12 @@ %mul = mul nsw i32 %5, %6, !dbg !23 %7 = load i32, i32* %i, align 4, !dbg !23 %idxprom = sext i32 %7 to i64, !dbg !23 +; XXX FIXME +; The restore of vla here causes the stack location to be clobbered going +; back around the loop. Ideally in the future, LLVM should be clever enough +; to know that the variable location of vla is best left on the stack through +; the body of the loop, rather than eagerly promoting it and losing it. +; Some more example of poor decisions are in PR42834. %arrayidx = getelementptr inbounds i32, i32* %vla, i64 %idxprom, !dbg !23 store i32 %mul, i32* %arrayidx, align 4, !dbg !23 br label %for.inc, !dbg !25 Index: llvm/test/DebugInfo/X86/parameters.ll =================================================================== --- llvm/test/DebugInfo/X86/parameters.ll +++ llvm/test/DebugInfo/X86/parameters.ll @@ -32,6 +32,7 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}} = "f" +; Argument "g" enters in RSI, is spilt, then restored to RAX. ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name{{.*}} = "func2" ; CHECK: DW_TAG_formal_parameter @@ -39,7 +40,8 @@ ; CHECK: DW_TAG_formal_parameter ; CHECK: DW_AT_location{{.*}}( ; CHECK-NEXT: {{.*}}: DW_OP_breg4 RSI+0{{$}} -; CHECK-NEXT: {{.*}}: DW_OP_breg7 RSP+8, DW_OP_deref) +; CHECK-NEXT: {{.*}}: DW_OP_breg7 RSP+8, DW_OP_deref{{$}} +; CHECK-NEXT: {{.*}}: DW_OP_breg0 RAX+0){{$}} ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name{{.*}} = "g" Index: llvm/test/DebugInfo/X86/pieces-4.ll =================================================================== --- llvm/test/DebugInfo/X86/pieces-4.ll +++ llvm/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_plus_uconst [[offs]], DW_OP_LLVM_fragment 0 32] [$rsp+0] +; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_plus_uconst [[offs]], DW_OP_deref, DW_OP_LLVM_fragment 0 32] $rsp ; CHECK: #APP ; CHECK: #NO_APP ; CHECK: movl [[offs]](%rsp), %eax # 4-byte Reload Index: llvm/test/DebugInfo/X86/pr34545.ll =================================================================== --- llvm/test/DebugInfo/X86/pr34545.ll +++ llvm/test/DebugInfo/X86/pr34545.ll @@ -1,10 +1,10 @@ -; RUN: llc -O1 -filetype=asm -mtriple x86_64-unknown-linux-gnu -mcpu=x86-64 -o - %s -stop-after=livedebugvars | FileCheck %s +; RUN: llc -O1 -filetype=asm -mtriple x86_64-unknown-linux-gnu -mcpu=x86-64 -o - %s -stop-after=livedebugvalues | FileCheck %s ; CHECK: $eax = MOV32rm ; CHECK: DBG_VALUE $eax ; CHECK: $eax = SHL32rCL killed renamable $eax ; CHECK: DBG_VALUE $eax -; CHECK: DBG_VALUE $rsp, 0, !{{[0-9]+}}, !DIExpression(DW_OP_constu, 4, DW_OP_minus) +; CHECK: DBG_VALUE $rsp, $noreg, !{{[0-9]+}}, !DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_deref) ; CHECK: DBG_VALUE $eax ; CHECK: $eax = SHL32rCL killed renamable $eax ; CHECK: DBG_VALUE $eax Index: llvm/test/DebugInfo/X86/prolog-params.mir =================================================================== --- llvm/test/DebugInfo/X86/prolog-params.mir +++ llvm/test/DebugInfo/X86/prolog-params.mir @@ -147,10 +147,11 @@ # CHECK-NEXT: DBG_VALUE $r9d, $noreg, ![[P5]], !DIExpression() # CHECK-NEXT: frame-setup PUSH64r -# Locals and stack parameters are emitted after the prologue code. -# CHECK: DBG_VALUE $rsp, 0, ![[P6]], !DIExpression(DW_OP_plus_uconst, 16) +# Locals and stack parameters are emitted after the prologue code. The +# second operand records their (negative) frame index, printed unsigned. +# CHECK: DBG_VALUE $rsp, 4294967293, ![[P6]], !DIExpression() # CHECK-NEXT: DBG_VALUE $r9d, $noreg, ![[P6]], !DIExpression() -# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[P7]], !DIExpression(DW_OP_plus_uconst, 24) -# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[P8]], !DIExpression(DW_OP_plus_uconst, 32) +# CHECK-NEXT: DBG_VALUE $rsp, 4294967294, ![[P7]], !DIExpression() +# CHECK-NEXT: DBG_VALUE $rsp, 4294967295, ![[P8]], !DIExpression() # CHECK-NEXT: DBG_VALUE $edi, $noreg, ![[LOCAL1]], !DIExpression() -# CHECK-NEXT: DBG_VALUE $rsp, 0, ![[LOCAL2]], !DIExpression(DW_OP_plus_uconst, 16) +# CHECK-NEXT: DBG_VALUE $rsp, 4294967293, ![[LOCAL2]], !DIExpression() Index: llvm/test/DebugInfo/X86/spill-indirect-nrvo.ll =================================================================== --- llvm/test/DebugInfo/X86/spill-indirect-nrvo.ll +++ llvm/test/DebugInfo/X86/spill-indirect-nrvo.ll @@ -23,10 +23,12 @@ ; CHECK-LABEL: _Z10get_stringv: ; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_deref] $rdi ; CHECK: movq %rdi, [[OFFS:[0-9]+]](%rsp) # 8-byte Spill -; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_plus_uconst [[OFFS]], DW_OP_deref] [$rsp+0] +; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_plus_uconst [[OFFS]], DW_OP_deref, DW_OP_deref] $rsp ; CHECK: callq _ZN6stringC1Ei ; CHECK: #APP ; CHECK: #NO_APP +; CHECK: movq [[OFFS]](%rsp), %[[LOADREG:r[abcds][xi]]] # 8-byte Reload +; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_deref] $[[LOADREG]] ; ModuleID = 't.cpp' source_filename = "t.cpp" Index: llvm/test/DebugInfo/X86/spill-nontrivial-param.ll =================================================================== --- llvm/test/DebugInfo/X86/spill-nontrivial-param.ll +++ llvm/test/DebugInfo/X86/spill-nontrivial-param.ll @@ -22,7 +22,7 @@ ; CHECK-LABEL: _Z3foo10NonTrivial: ; CHECK: #DEBUG_VALUE: foo:nt <- [DW_OP_deref] $rdi ; CHECK: movq %rdi, -8(%rsp) # 8-byte Spill -; CHECK: #DEBUG_VALUE: foo:nt <- [DW_OP_constu 8, DW_OP_minus, DW_OP_deref] [$rsp+0] +; CHECK: #DEBUG_VALUE: foo:nt <- [DW_OP_constu 8, DW_OP_minus, DW_OP_deref, DW_OP_deref] $rsp ; CHECK: #APP ; CHECK: #NO_APP ; CHECK: movq -8(%rsp), %rax # 8-byte Reload Index: llvm/test/DebugInfo/X86/spill-nospill.ll =================================================================== --- llvm/test/DebugInfo/X86/spill-nospill.ll +++ llvm/test/DebugInfo/X86/spill-nospill.ll @@ -24,7 +24,7 @@ ; CHECK-LABEL: f: # @f ; CHECK: callq g ; CHECK: movl %eax, [[X_OFFS:[0-9]+]](%rsp) # 4-byte Spill -; CHECK: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[X_OFFS]]] [$rsp+0] +; CHECK: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[X_OFFS]], DW_OP_deref] $rsp ; CHECK: #APP ; CHECK: #NO_APP ; CHECK: callq g Index: llvm/test/DebugInfo/X86/sret.ll =================================================================== --- llvm/test/DebugInfo/X86/sret.ll +++ llvm/test/DebugInfo/X86/sret.ll @@ -3,8 +3,8 @@ ; Based on the debuginfo-tests/sret.cpp code. -; CHECK-DWO: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x51ac5644b1937aa1) -; CHECK-DWO: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x51ac5644b1937aa1) +; CHECK-DWO: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x29bc2656bdb2e5dc) +; CHECK-DWO: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x29bc2656bdb2e5dc) ; RUN: llc -O0 -fast-isel=true -mtriple=x86_64-apple-darwin -filetype=obj -o - %s | llvm-dwarfdump -v - | FileCheck %s ; RUN: llc -O0 -fast-isel=false -mtriple=x86_64-apple-darwin -filetype=obj -o - %s | llvm-dwarfdump -v - | FileCheck %s @@ -12,7 +12,8 @@ ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000 ; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_breg5 RDI+0 -; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_breg6 RBP-24, DW_OP_deref) +; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_breg6 RBP-24, DW_OP_deref +; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_breg5 RDI+0 ; CHECK-NEXT: DW_AT_name {{.*}}"a" %class.A = type { i32 (...)**, i32 }