diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst --- a/llvm/docs/MIRLangRef.rst +++ b/llvm/docs/MIRLangRef.rst @@ -747,7 +747,7 @@ .. code-block:: text - DBG_INSTR_REF !123, !DIExpression(), dbg-instr-ref(1, 0), debug-location !456 + DBG_INSTR_REF !123, !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !456 CFIIndex Operands ^^^^^^^^^^^^^^^^^ @@ -913,7 +913,7 @@ .. code-block:: text $rbp = MOV64ri 0, debug-instr-number 1, debug-location !12 - DBG_INSTR_REF !123, !DIExpression(), dbg-instr-ref(1, 0), debug-location !456 + DBG_INSTR_REF !123, !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !456 Instruction numbers are directly attached to machine instructions with an optional ``debug-instr-number`` attachment, before the optional diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2741,6 +2741,11 @@ /// it cannot be a simple register location. bool isComplex() const; + /// Return whether the evaluated expression makes use of a single location at + /// the start of the expression, i.e. if it contains only a single + /// DW_OP_LLVM_arg op as its first operand, or if it contains none. + bool isSingleLocationExpression() const; + /// Append \p Ops with operations to apply the \p Offset. static void appendOffset(SmallVectorImpl &Ops, int64_t Offset); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1137,10 +1137,16 @@ OS << " <- "; const DIExpression *Expr = MI->getDebugExpression(); + if (Expr->getNumElements() && Expr->isSingleLocationExpression() && + Expr->expr_op_begin()->getOp() == dwarf::DW_OP_LLVM_arg) { + SmallVector Ops( + make_range(Expr->elements_begin() + 2, Expr->elements_end())); + Expr = DIExpression::get(Expr->getContext(), Ops); + } if (Expr->getNumElements()) { OS << '['; ListSeparator LS; - for (auto Op : Expr->expr_ops()) { + for (auto &Op : Expr->expr_ops()) { OS << LS << dwarf::OperationEncodingString(Op.getOp()); for (unsigned I = 0; I < Op.getNumArgs(); ++I) OS << ' ' << Op.getArg(I); diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -116,13 +116,7 @@ public: DbgValueLoc(const DIExpression *Expr, ArrayRef Locs) : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()), - IsVariadic(true) { -#ifndef NDEBUG - // Currently, DBG_VALUE_VAR expressions must use stack_value. - assert(Expr && Expr->isValid() && - is_contained(Locs, dwarf::DW_OP_stack_value)); -#endif - } + IsVariadic(true) {} DbgValueLoc(const DIExpression *Expr, ArrayRef Locs, bool IsVariadic) @@ -133,10 +127,6 @@ !any_of(Locs, [](auto LE) { return LE.isLocation(); })); if (!IsVariadic) { assert(ValueLocEntries.size() == 1); - } else { - // Currently, DBG_VALUE_VAR expressions must use stack_value. - assert(Expr && Expr->isValid() && - is_contained(Expr->getElements(), dwarf::DW_OP_stack_value)); } #endif } diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -1218,7 +1218,7 @@ // the pointer to the variable loaded off the stack with a deref: assert(!Expr->isImplicit()); OffsetOps.push_back(dwarf::DW_OP_deref); - } else if (UseDerefSize && !Properties.IsVariadic) { + } else if (UseDerefSize && Expr->isSingleLocationExpression()) { // TODO: Figure out how to handle deref size issues for variadic // values. // We're loading a value off the stack that's not the same size as the @@ -1227,7 +1227,7 @@ OffsetOps.push_back(dwarf::DW_OP_deref_size); OffsetOps.push_back(DerefSizeInBytes); StackValue = true; - } else if (Expr->isComplex()) { + } else if (Expr->isComplex() || Properties.IsVariadic) { // A variable with no size ambiguity, but with extra elements in it's // expression. Manually dereference the stack location. OffsetOps.push_back(dwarf::DW_OP_deref); diff --git a/llvm/lib/CodeGen/LiveDebugVariables.cpp b/llvm/lib/CodeGen/LiveDebugVariables.cpp --- a/llvm/lib/CodeGen/LiveDebugVariables.cpp +++ b/llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -137,8 +137,7 @@ // Turn this into an undef debug value list; right now, the simplest form // of this is an expression with one arg, and an undef debug operand. Expression = - DIExpression::get(Expr.getContext(), {dwarf::DW_OP_LLVM_arg, 0, - dwarf::DW_OP_stack_value}); + DIExpression::get(Expr.getContext(), {dwarf::DW_OP_LLVM_arg, 0}); if (auto FragmentInfoOpt = Expr.getFragmentInfo()) Expression = *DIExpression::createFragmentExpression( Expression, FragmentInfoOpt->OffsetInBits, diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1360,6 +1360,7 @@ switch (It.getOp()) { case dwarf::DW_OP_LLVM_tag_offset: case dwarf::DW_OP_LLVM_fragment: + case dwarf::DW_OP_LLVM_arg: continue; default: return true; @@ -1369,6 +1370,23 @@ return false; } +bool DIExpression::isSingleLocationExpression() const { + if (!isValid()) + return false; + + if (getNumElements() == 0) + return true; + + auto ExprOpBegin = expr_ops().begin(); + auto ExprOpEnd = expr_ops().end(); + if (ExprOpBegin->getOp() == dwarf::DW_OP_LLVM_arg) + ++ExprOpBegin; + + return !std::any_of(ExprOpBegin, ExprOpEnd, [](auto Op) { + return Op.getOp() == dwarf::DW_OP_LLVM_arg; + }); +} + Optional DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) { for (auto I = Start; I != End; ++I) @@ -1482,10 +1500,21 @@ SmallVector NewOps; for (auto Op : Expr->expr_ops()) { + // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment. + if (StackValue) { + if (Op.getOp() == dwarf::DW_OP_stack_value) + StackValue = false; + else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) { + NewOps.push_back(dwarf::DW_OP_stack_value); + StackValue = false; + } + } Op.appendToVector(NewOps); if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo) NewOps.insert(NewOps.end(), Ops.begin(), Ops.end()); } + if (StackValue) + NewOps.push_back(dwarf::DW_OP_stack_value); return DIExpression::get(Expr->getContext(), NewOps); } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1782,8 +1782,8 @@ MaxDebugArgs) { DII->addVariableLocationOps(AdditionalValues, SalvagedExpr); } else { - // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is - // currently only valid for stack value expressions. + // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is not + // currently supported in those instructions. // Also do not salvage if the resulting DIArgList would contain an // unreasonably large number of values. Value *Undef = UndefValue::get(I.getOperand(0)->getType());