Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2468,6 +2468,9 @@ /// it cannot be a simple register location. bool isComplex() const; + /// Return whether this is an operation with a constant offset. + bool isOpWithOffset() const; + /// Append \p Ops with operations to apply the \p Offset. static void appendOffset(SmallVectorImpl &Ops, int64_t Offset); Index: llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -246,8 +246,8 @@ // a call site parameter expression and if that expression is just a register // location, emit it with addBReg and offset 0, because we should emit a DWARF // expression representing a value, rather than a location. - if (!isMemoryLocation() && !HasComplexExpression && - (!isParameterValue() || isEntryValue())) { + if ((!isMemoryLocation() && !HasComplexExpression && !isParameterValue()) || + isEntryValue()) { for (auto &Reg : DwarfRegs) { if (Reg.DwarfRegNo >= 0) addReg(Reg.DwarfRegNo, Reg.Comment); @@ -257,8 +257,8 @@ if (isEntryValue()) finalizeEntryValue(); - if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4) - emitOp(dwarf::DW_OP_stack_value); + if (isEntryValue() && !isParameterValue() && isRegisterLocation()) + LocationKind = Implicit; DwarfRegs.clear(); return true; Index: llvm/lib/CodeGen/LiveDebugValues.cpp =================================================================== --- llvm/lib/CodeGen/LiveDebugValues.cpp +++ llvm/lib/CodeGen/LiveDebugValues.cpp @@ -411,9 +411,16 @@ // A copy like instruction that moves the entry value around. MachineInstr *DbgEntryValueMovement; + // A debug info expression describing the debug entry value modification. + DIExpression *DbgEntryValueModification; + void setDbgEntryValueMovement(MachineInstr *MI) { DbgEntryValueMovement = MI; } + + void setDbgEntryValueModification(DIExpression *Expr) { + DbgEntryValueModification = Expr; + } }; using DebugParamMap = SmallDenseMap; @@ -740,6 +747,17 @@ MI.getOperand(0).getReg() == EntryValueCopyReg) { if (MI.getDebugExpression()->getNumElements() == 0) return; + else if (Expr->isOpWithOffset()) { + // Handle the debug entry value modification. + DIExpression *NewEntryValExpr = + DebugEntryVals[Var].DbgEntryValueModification; + NewEntryValExpr = + DIExpression::prepend(Expr, DIExpression::ApplyOffset); + DebugEntryVals[Var].setDbgEntryValueModification(NewEntryValExpr); + return; + } + // Stop tracking the entry value. + DebugEntryVals.erase(Var); } } @@ -821,6 +839,16 @@ DIExpression *NewExpr = DIExpression::prepend( ParamDebugInstr->getDebugExpression(), DIExpression::EntryValue); + // Follow the modification of the debug entry value if any. + DIExpression *EntryValModification = + ParamEntryValue->second.DbgEntryValueModification; + if (EntryValModification->getNumElements() != 0) { + ArrayRef elements = NewExpr->getElements(); + SmallVector Ops; + Ops.append(elements.begin(), elements.end()); + NewExpr = DIExpression::prependOpcodes(EntryValModification, Ops); + } + auto getEntryLoc = [ParamDebugInstr, ParamEntryValMovement, NewExpr](LexicalScopes &LS) { if (ParamEntryValMovement) @@ -1438,8 +1466,6 @@ // unmodified throughout the function and located in a register. // TODO: Add support for parameters with non-empty debug expressions (for // example fragments). - // TODO: Add support for modified arguments that can be expressed - // by using its entry value. // TODO: Add support for local variables that are expressed in terms of // parameters entry values. for (auto &MI : First_MBB) @@ -1448,8 +1474,12 @@ !MI.isIndirectDebugValue() && isRegOtherThanSPAndFP(MI.getOperand(0), MI, TRI) && !DebugEntryVals.count(MI.getDebugVariable()) && - MI.getDebugExpression()->getNumElements() == 0) - DebugEntryVals[MI.getDebugVariable()] = EntryValue{&MI, nullptr}; + MI.getDebugExpression()->getNumElements() == 0) { + DIExpression *EntryValueModificationExpr = + DIExpression::get(MF.getFunction().getContext(), {}); + DebugEntryVals[MI.getDebugVariable()] = + EntryValue{&MI, nullptr, EntryValueModificationExpr}; + } // Initialize per-block structures and scan for fragment overlaps. for (auto &MBB : MF) { Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -896,8 +896,7 @@ // entry values of a simple register location. One reason for this is that // we currently can't calculate the size of the resulting DWARF block for // other expressions. - return I->get() == expr_op_begin()->get() && I->getArg(0) == 1 && - getNumElements() == 2; + return I->get() == expr_op_begin()->get() && I->getArg(0) == 1; } case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_LLVM_tag_offset: @@ -964,6 +963,21 @@ return false; } +bool DIExpression::isOpWithOffset() const { + if (getNumElements() == 0) + return false; + + if (getNumElements() == 3 && Elements[0] == dwarf::DW_OP_plus_uconst) + return true; + + if (getNumElements() == 4 && Elements[0] == dwarf::DW_OP_constu) + if (Elements[2] == dwarf::DW_OP_plus || + Elements[2] == dwarf::DW_OP_minus) + return true; + + return false; +} + Optional DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) { for (auto I = Start; I != End; ++I) Index: llvm/test/DebugInfo/MIR/X86/entry-value-of-modified-param.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/entry-value-of-modified-param.mir +++ llvm/test/DebugInfo/MIR/X86/entry-value-of-modified-param.mir @@ -19,7 +19,7 @@ # CHECK: DBG_VALUE $edi, $noreg, !16, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}} # CHECK: DBG_VALUE $edx, $noreg, !18, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}} # CHECK: DBG_VALUE $edi, $noreg, !16, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}} -# CHECK-NOT: DBG_VALUE $esi, $noreg, !17, !DIExpression(DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 7, DW_OP_stack_value), debug-location {{.*}} +# CHECK: DBG_VALUE $esi, $noreg, !17, !DIExpression(DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 7, DW_OP_stack_value), debug-location {{.*}} # --- | ; ModuleID = 'test.c'