summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/LangRef.rst17
-rw-r--r--llvm/docs/SourceLevelDebugging.rst22
-rw-r--r--llvm/include/llvm/CodeGen/MachineInstrBuilder.h5
-rw-r--r--llvm/include/llvm/IR/DebugInfoMetadata.h5
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp1
-rw-r--r--llvm/lib/Bitcode/Reader/MetadataLoader.cpp57
-rw-r--r--llvm/lib/Bitcode/Reader/MetadataLoader.h3
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp5
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp12
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp25
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp7
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp146
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h13
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp5
-rw-r--r--llvm/lib/CodeGen/InlineSpiller.cpp16
-rw-r--r--llvm/lib/CodeGen/MachineInstr.cpp28
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp14
-rw-r--r--llvm/lib/CodeGen/SafeStack.cpp6
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FastISel.cpp6
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp16
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h2
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp8
-rw-r--r--llvm/test/Bitcode/DIExpression-aggresult.ll36
-rw-r--r--llvm/test/Bitcode/DIExpression-aggresult.ll.bcbin0 -> 1344 bytes
-rw-r--r--llvm/test/Bitcode/DIExpression-deref.ll27
-rw-r--r--llvm/test/Bitcode/DIExpression-deref.ll.bcbin0 -> 1012 bytes
-rw-r--r--llvm/test/DebugInfo/ARM/selectiondag-deadcode.ll2
-rw-r--r--llvm/test/DebugInfo/Generic/block-asan.ll2
-rw-r--r--llvm/test/DebugInfo/X86/dbg-declare-arg.ll16
-rw-r--r--llvm/test/DebugInfo/X86/dbg_value_direct.ll2
-rw-r--r--llvm/test/DebugInfo/X86/debug-info-block-captured-self.ll4
-rw-r--r--llvm/test/DebugInfo/X86/dw_op_minus.ll13
-rw-r--r--llvm/test/DebugInfo/X86/dw_op_minus_direct.ll6
-rw-r--r--llvm/test/DebugInfo/X86/sret.ll20
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/debug_info.ll6
-rw-r--r--llvm/test/Transforms/SafeStack/X86/debug-loc.ll4
37 files changed, 381 insertions, 178 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d17bbc18ab7..2cb640370bb 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4380,7 +4380,7 @@ referenced LLVM variable relates to the source language variable.
The current supported vocabulary is limited:
-- ``DW_OP_deref`` dereferences the working expression.
+- ``DW_OP_deref`` dereferences the top of the expression stack.
- ``DW_OP_plus, 93`` adds ``93`` to the working expression.
- ``DW_OP_LLVM_fragment, 16, 8`` specifies the offset and size (``16`` and ``8``
here, respectively) of the variable fragment from the working expression. Note
@@ -4396,12 +4396,17 @@ DIExpression nodes that contain a ``DW_OP_stack_value`` operator are standalone
location descriptions that describe constant values. This form is used to
describe global constants that have been optimized away. All other expressions
are modifiers to another location: A debug intrinsic ties a location and a
-DIExpression together. Contrary to DWARF expressions, a DIExpression always
-describes the *value* of a source variable and never its *address*. In DWARF
-terminology, a DIExpression can always be considered an implicit location
-description regardless whether it contains a ``DW_OP_stack_value`` or not.
+DIExpression together.
-.. code-block:: text
+DWARF specifies three kinds of simple location descriptions: Register, memory,
+and implicit location descriptions. Register and memory location descriptions
+describe the *location* of a source variable (in the sense that a debugger might
+modify its value), whereas implicit locations describe merely the *value* of a
+source variable. DIExpressions also follow this model: A DIExpression that
+doesn't have a trailing ``DW_OP_stack_value`` will describe an *address* when
+combined with a concrete location.
+
+.. code-block:: llvm
!0 = !DIExpression(DW_OP_deref)
!1 = !DIExpression(DW_OP_plus, 3)
diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst
index 41f8dbfab3d..a9f5c3a0814 100644
--- a/llvm/docs/SourceLevelDebugging.rst
+++ b/llvm/docs/SourceLevelDebugging.rst
@@ -180,11 +180,27 @@ provide debug information at various points in generated code.
void @llvm.dbg.declare(metadata, metadata, metadata)
-This intrinsic provides information about a local element (e.g., variable).
-The first argument is metadata holding the alloca for the variable. The second
+This intrinsic provides information about a local element (e.g., variable). The
+first argument is metadata holding the alloca for the variable. The second
argument is a `local variable <LangRef.html#dilocalvariable>`_ containing a
description of the variable. The third argument is a `complex expression
-<LangRef.html#diexpression>`_.
+<LangRef.html#diexpression>`_. An `llvm.dbg.declare` instrinsic describes the
+*location* of a source variable.
+
+.. code-block:: llvm
+
+ %i.addr = alloca i32, align 4
+ call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !1, metadata !2), !dbg !3
+ !1 = !DILocalVariable(name: "i", ...) ; int i
+ !2 = !DIExpression()
+ !3 = !DILocation(...)
+ ...
+ %buffer = alloca [256 x i8], align 8
+ ; The address of i is buffer+64.
+ call void @llvm.dbg.declare(metadata [256 x i8]* %buffer, metadata !1, metadata !2)
+ !1 = !DILocalVariable(name: "i", ...) ; int i
+ !2 = !DIExpression(DW_OP_plus, 64)
+
``llvm.dbg.value``
^^^^^^^^^^^^^^^^^^
diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index ef4226d30fe..412c55d542e 100644
--- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -413,6 +413,11 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
unsigned Reg, unsigned Offset,
const MDNode *Variable, const MDNode *Expr);
+/// Clone a DBG_VALUE whose value has been spilled to FrameIndex.
+MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I,
+ const MachineInstr &Orig, int FrameIndex);
+
inline unsigned getDefRegState(bool B) {
return B ? RegState::Define : 0;
}
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 8a924b40143..8041e35e0e0 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2232,6 +2232,9 @@ public:
expr_op_iterator expr_op_end() const {
return expr_op_iterator(elements_end());
}
+ iterator_range<expr_op_iterator> expr_ops() const {
+ return {expr_op_begin(), expr_op_end()};
+ }
/// @}
bool isValid() const;
@@ -2240,7 +2243,7 @@ public:
return MD->getMetadataID() == DIExpressionKind;
}
- /// Is the first element a DW_OP_deref?.
+ /// Return whether the first element a DW_OP_deref.
bool startsWithDeref() const {
return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref;
}
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 2de6bccf751..6d727ce8334 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2631,6 +2631,7 @@ Error BitcodeReader::globalCleanup() {
// Look for intrinsic functions which need to be upgraded at some point
for (Function &F : *TheModule) {
+ MDLoader->upgradeDebugIntrinsics(F);
Function *NewFn;
if (UpgradeIntrinsicFunction(&F, NewFn))
UpgradedIntrinsics[&F] = NewFn;
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 274dfe89cce..d089684a052 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -54,6 +54,7 @@
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
@@ -452,6 +453,7 @@ class MetadataLoader::MetadataLoaderImpl {
bool StripTBAA = false;
bool HasSeenOldLoopTags = false;
bool NeedUpgradeToDIGlobalVariableExpression = false;
+ bool NeedDeclareExpressionUpgrade = false;
/// True if metadata is being parsed for a module being ThinLTO imported.
bool IsImporting = false;
@@ -511,6 +513,26 @@ class MetadataLoader::MetadataLoaderImpl {
}
}
+ /// Remove a leading DW_OP_deref from DIExpressions in a dbg.declare that
+ /// describes a function argument.
+ void upgradeDeclareExpressions(Function &F) {
+ if (!NeedDeclareExpressionUpgrade)
+ return;
+
+ for (auto &BB : F)
+ for (auto &I : BB)
+ if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
+ if (auto *DIExpr = DDI->getExpression())
+ if (DIExpr->startsWithDeref() &&
+ dyn_cast_or_null<Argument>(DDI->getAddress())) {
+ SmallVector<uint64_t, 8> Ops;
+ Ops.append(std::next(DIExpr->elements_begin()),
+ DIExpr->elements_end());
+ auto *E = DIExpression::get(Context, Ops);
+ DDI->setOperand(2, MetadataAsValue::get(Context, E));
+ }
+ }
+
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
@@ -565,6 +587,7 @@ public:
unsigned size() const { return MetadataList.size(); }
void shrinkTo(unsigned N) { MetadataList.shrinkTo(N); }
+ void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); }
};
static Error error(const Twine &Message) {
@@ -1520,12 +1543,32 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
return error("Invalid record");
IsDistinct = Record[0] & 1;
- bool HasOpFragment = Record[0] & 2;
+ uint64_t Version = Record[0] >> 1;
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
- if (!HasOpFragment)
- if (unsigned N = Elts.size())
- if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
- Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
+ unsigned N = Elts.size();
+ // Perform various upgrades.
+ switch (Version) {
+ case 0:
+ if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
+ Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
+ LLVM_FALLTHROUGH;
+ case 1:
+ // Move DW_OP_deref to the end.
+ if (N && Elts[0] == dwarf::DW_OP_deref) {
+ auto End = Elts.end();
+ if (Elts.size() >= 3 && *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
+ End = std::prev(End, 3);
+ std::move(std::next(Elts.begin()), End, Elts.begin());
+ *std::prev(End) = dwarf::DW_OP_deref;
+ }
+ NeedDeclareExpressionUpgrade = true;
+ LLVM_FALLTHROUGH;
+ case 2:
+ // Up-to-date!
+ break;
+ default:
+ return error("Invalid record");
+ }
MetadataList.assignValue(
GET_OR_DISTINCT(DIExpression, (Context, makeArrayRef(Record).slice(1))),
@@ -1858,3 +1901,7 @@ bool MetadataLoader::isStrippingTBAA() { return Pimpl->isStrippingTBAA(); }
unsigned MetadataLoader::size() const { return Pimpl->size(); }
void MetadataLoader::shrinkTo(unsigned N) { return Pimpl->shrinkTo(N); }
+
+void MetadataLoader::upgradeDebugIntrinsics(Function &F) {
+ return Pimpl->upgradeDebugIntrinsics(F);
+}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.h b/llvm/lib/Bitcode/Reader/MetadataLoader.h
index 442dfc94e4e..f23dcc06cc9 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.h
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.h
@@ -79,6 +79,9 @@ public:
unsigned size() const;
void shrinkTo(unsigned N);
+
+ /// Perform bitcode upgrades on llvm.dbg.* calls.
+ void upgradeDebugIntrinsics(Function &F);
};
}
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index ee1b70da8ab..1d3cde2f5dd 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1771,9 +1771,8 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.reserve(N->getElements().size() + 1);
-
- const uint64_t HasOpFragmentFlag = 1 << 1;
- Record.push_back((uint64_t)N->isDistinct() | HasOpFragmentFlag);
+ const uint64_t Version = 2 << 1;
+ Record.push_back((uint64_t)N->isDistinct() | Version);
Record.append(N->elements_begin(), N->elements_end());
Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev);
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 5d099be7740..b18dd7d0067 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -834,9 +834,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
OS << " <- ";
// The second operand is only an offset if it's an immediate.
- bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
- int64_t Offset = Deref ? MI->getOperand(1).getImm() : 0;
-
+ bool Deref = false;
+ bool MemLoc = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
+ int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0;
for (unsigned i = 0; i < Expr->getNumElements(); ++i) {
uint64_t Op = Expr->getElement(i);
if (Op == dwarf::DW_OP_LLVM_fragment) {
@@ -844,7 +844,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
break;
} else if (Deref) {
// We currently don't support extra Offsets or derefs after the first
- // one. Bail out early instead of emitting an incorrect comment
+ // one. Bail out early instead of emitting an incorrect comment.
OS << " [complex expression]";
AP.OutStreamer->emitRawComment(OS.str());
return true;
@@ -899,12 +899,12 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
AP.OutStreamer->emitRawComment(OS.str());
return true;
}
- if (Deref)
+ if (MemLoc || Deref)
OS << '[';
OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo());
}
- if (Deref)
+ if (MemLoc || Deref)
OS << '+' << Offset << ']';
// NOTE: Want this comment at start of line, don't emit with AddComment.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index a550ff2fb90..4a092ffbdc0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -547,18 +547,19 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
for (auto &Fragment : DV.getFrameIndexExprs()) {
unsigned FrameReg = 0;
+ const DIExpression *Expr = Fragment.Expr;
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
- DwarfExpr.addFragmentOffset(Fragment.Expr);
+ DwarfExpr.addFragmentOffset(Expr);
SmallVector<uint64_t, 8> Ops;
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Offset);
- Ops.push_back(dwarf::DW_OP_deref);
- Ops.append(Fragment.Expr->elements_begin(), Fragment.Expr->elements_end());
- DIExpressionCursor Expr(Ops);
- DwarfExpr.addMachineRegExpression(
- *Asm->MF->getSubtarget().getRegisterInfo(), Expr, FrameReg);
- DwarfExpr.addExpression(std::move(Expr));
+ Ops.append(Expr->elements_begin(), Expr->elements_end());
+ DIExpressionCursor Cursor(Ops);
+ DwarfExpr.addMachineLocExpression(
+ *Asm->MF->getSubtarget().getRegisterInfo(), Cursor,
+ MachineLocation(FrameReg));
+ DwarfExpr.addExpression(std::move(Cursor));
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
@@ -781,14 +782,13 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
SmallVector<uint64_t, 8> Ops;
- if (Location.isIndirect()) {
+ if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
- Ops.push_back(dwarf::DW_OP_deref);
}
DIExpressionCursor Cursor(Ops);
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
- if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
+ if (!DwarfExpr.addMachineLocExpression(TRI, Cursor, Location))
return;
DwarfExpr.addExpression(std::move(Cursor));
@@ -809,15 +809,14 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
DwarfExpr.addFragmentOffset(DIExpr);
SmallVector<uint64_t, 8> Ops;
- if (Location.isIndirect()) {
+ if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
- Ops.push_back(dwarf::DW_OP_deref);
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
DIExpressionCursor Cursor(Ops);
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
- if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
+ if (!DwarfExpr.addMachineLocExpression(TRI, Cursor, Location))
return;
DwarfExpr.addExpression(std::move(Cursor));
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index af90f6f60a1..b5a99aa5545 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1517,18 +1517,15 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
DwarfExpr.addUnsignedConstant(Value.getInt());
} else if (Value.isLocation()) {
MachineLocation Location = Value.getLoc();
-
SmallVector<uint64_t, 8> Ops;
- // FIXME: Should this condition be Location.isIndirect() instead?
- if (Location.getOffset()) {
+ if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
- Ops.push_back(dwarf::DW_OP_deref);
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
DIExpressionCursor Cursor(Ops);
const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
- if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
+ if (!DwarfExpr.addMachineLocExpression(TRI, Cursor, Location))
return;
return DwarfExpr.addExpression(std::move(Cursor));
} else if (Value.isConstantFP()) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index debe88f3b1e..d21288f4b81 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -23,9 +23,12 @@
using namespace llvm;
void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
- assert(DwarfReg >= 0 && "invalid negative dwarf register number");
- if (DwarfReg < 32) {
- emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
+ assert(DwarfReg >= 0 && "invalid negative dwarf register number");
+ assert((LocationKind == Unknown || LocationKind == Register) &&
+ "location description already locked down");
+ LocationKind = Register;
+ if (DwarfReg < 32) {
+ emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
} else {
emitOp(dwarf::DW_OP_regx, Comment);
emitUnsigned(DwarfReg);
@@ -34,6 +37,7 @@ void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
void DwarfExpression::addBReg(int DwarfReg, int Offset) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
+ assert(LocationKind != Register && "location description already locked down");
if (DwarfReg < 32) {
emitOp(dwarf::DW_OP_breg0 + DwarfReg);
} else {
@@ -156,18 +160,23 @@ void DwarfExpression::addStackValue() {
}
void DwarfExpression::addSignedConstant(int64_t Value) {
+ assert(LocationKind == Implicit || LocationKind == Unknown);
+ LocationKind = Implicit;
emitOp(dwarf::DW_OP_consts);
emitSigned(Value);
- addStackValue();
}
void DwarfExpression::addUnsignedConstant(uint64_t Value) {
+ assert(LocationKind == Implicit || LocationKind == Unknown);
+ LocationKind = Implicit;
emitOp(dwarf::DW_OP_constu);
emitUnsigned(Value);
- addStackValue();
}
void DwarfExpression::addUnsignedConstant(const APInt &Value) {
+ assert(LocationKind == Implicit || LocationKind == Unknown);
+ LocationKind = Implicit;
+
unsigned Size = Value.getBitWidth();
const uint64_t *Data = Value.getRawData();
@@ -178,15 +187,20 @@ void DwarfExpression::addUnsignedConstant(const APInt &Value) {
addUnsignedConstant(*Data++);
if (Offset == 0 && Size <= 64)
break;
- addOpPiece(std::min(Size-Offset, 64u), Offset);
+ addStackValue();
+ addOpPiece(std::min(Size - Offset, 64u), Offset);
Offset += 64;
}
}
-bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
+bool DwarfExpression::addMachineLocExpression(const TargetRegisterInfo &TRI,
DIExpressionCursor &ExprCursor,
- unsigned MachineReg,
+ MachineLocation Loc,
unsigned FragmentOffsetInBits) {
+ if (Loc.isIndirect())
+ LocationKind = Memory;
+
+ unsigned MachineReg = Loc.getReg();
auto Fragment = ExprCursor.getFragmentInfo();
if (!addMachineReg(TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U))
return false;
@@ -206,7 +220,7 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
}
// Handle simple register locations.
- if (!HasComplexExpression) {
+ if (LocationKind != Memory && !HasComplexExpression) {
for (auto &Reg : DwarfRegs) {
if (Reg.DwarfRegNo >= 0)
addReg(Reg.DwarfRegNo, Reg.Comment);
@@ -216,62 +230,58 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
return true;
}
+ // FIXME:
+ // Don't emit locations that cannot be expressed without DW_OP_stack_value.
+
assert(DwarfRegs.size() == 1);
auto Reg = DwarfRegs[0];
- bool FBReg = isFrameRegister(TRI, MachineReg);
+ bool FBReg = isFrameRegister(TRI, MachineReg);
+ int SignedOffset = 0;
assert(Reg.Size == 0 && "subregister has same size as superregister");
// Pattern-match combinations for which more efficient representations exist.
- switch (Op->getOp()) {
- default: {
- if (FBReg)
- addFBReg(0);
- else
- addReg(Reg.DwarfRegNo, 0);
- break;
+ // [Reg, Offset, DW_OP_plus] --> [DW_OP_breg, Offset].
+ // [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset].
+ // If Reg is a subregister we need to mask it out before subtracting.
+ if (Op && ((Op->getOp() == dwarf::DW_OP_plus) ||
+ (Op->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
+ int Offset = Op->getArg(0);
+ SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
+ ExprCursor.take();
}
- case dwarf::DW_OP_plus:
- case dwarf::DW_OP_minus: {
- // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset].
- // [DW_OP_reg,Offset,DW_OP_minus,DW_OP_deref] --> [DW_OP_breg,-Offset].
- auto N = ExprCursor.peekNext();
- if (N && N->getOp() == dwarf::DW_OP_deref) {
- int Offset = Op->getArg(0);
- int SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
- if (FBReg)
- addFBReg(SignedOffset);
- else
- addBReg(Reg.DwarfRegNo, SignedOffset);
+ if (FBReg)
+ addFBReg(SignedOffset);
+ else
+ addBReg(Reg.DwarfRegNo, SignedOffset);
+ DwarfRegs.clear();
+ return true;
+}
- ExprCursor.consume(2);
+/// Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?".
+static bool isMemoryLocation(DIExpressionCursor ExprCursor) {
+ while (ExprCursor) {
+ auto Op = ExprCursor.take();
+ switch (Op->getOp()) {
+ case dwarf::DW_OP_deref:
+ case dwarf::DW_OP_LLVM_fragment:
break;
+ default:
+ return false;
}
- addReg(Reg.DwarfRegNo, 0);
- break;
- }
- case dwarf::DW_OP_deref:
- // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
- if (FBReg)
- addFBReg(0);
- else
- addBReg(Reg.DwarfRegNo, 0);
- ExprCursor.take();
- break;
}
- DwarfRegs.clear();
return true;
}
void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
unsigned FragmentOffsetInBits) {
+ // If we need to mask out a subregister, do it now, unless the next
+ // operation would emit an OpPiece anyway.
+ auto N = ExprCursor.peek();
+ if (SubRegisterSizeInBits && N && (N->getOp() != dwarf::DW_OP_LLVM_fragment))
+ maskSubRegister();
+
while (ExprCursor) {
auto Op = ExprCursor.take();
-
- // If we need to mask out a subregister, do it now, unless the next
- // operation would emit an OpPiece anyway.
- if (SubRegisterSizeInBits && Op->getOp() != dwarf::DW_OP_LLVM_fragment)
- maskSubRegister();
-
switch (Op->getOp()) {
case dwarf::DW_OP_LLVM_fragment: {
unsigned SizeInBits = Op->getArg(1);
@@ -281,50 +291,74 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
// location.
assert(OffsetInBits >= FragmentOffset && "fragment offset not added?");
- // If \a addMachineReg already emitted DW_OP_piece operations to represent
+ // If addMachineReg already emitted DW_OP_piece operations to represent
// a super-register by splicing together sub-registers, subtract the size
// of the pieces that was already emitted.
SizeInBits -= OffsetInBits - FragmentOffset;
- // If \a addMachineReg requested a DW_OP_bit_piece to stencil out a
+ // If addMachineReg requested a DW_OP_bit_piece to stencil out a
// sub-register that is smaller than the current fragment's size, use it.
if (SubRegisterSizeInBits)
SizeInBits = std::min<unsigned>(SizeInBits, SubRegisterSizeInBits);
-
+
+ // Emit a DW_OP_stack_value for implicit location descriptions.
+ if (LocationKind == Implicit)
+ addStackValue();
+
+ // Emit the DW_OP_piece.
addOpPiece(SizeInBits, SubRegisterOffsetInBits);
setSubRegisterPiece(0, 0);
- break;
+ // Reset the location description kind.
+ LocationKind = Unknown;
+ return;
}
case dwarf::DW_OP_plus:
+ assert(LocationKind != Register);
emitOp(dwarf::DW_OP_plus_uconst);
emitUnsigned(Op->getArg(0));
break;
case dwarf::DW_OP_minus:
- // There is no OP_minus_uconst.
+ assert(LocationKind != Register);
+ // There is no DW_OP_minus_uconst.
emitOp(dwarf::DW_OP_constu);
emitUnsigned(Op->getArg(0));
emitOp(dwarf::DW_OP_minus);
break;
- case dwarf::DW_OP_deref:
- emitOp(dwarf::DW_OP_deref);
+ case dwarf::DW_OP_deref: {
+ assert(LocationKind != Register);
+ if (LocationKind != Memory && isMemoryLocation(ExprCursor))
+ // Turning this into a memory location description makes the deref
+ // implicit.
+ LocationKind = Memory;
+ else
+ emitOp(dwarf::DW_OP_deref);
break;
+ }
case dwarf::DW_OP_constu:
+ assert(LocationKind != Register);
emitOp(dwarf::DW_OP_constu);
emitUnsigned(Op->getArg(0));
break;
case dwarf::DW_OP_stack_value:
- addStackValue();
+ assert(LocationKind == Unknown || LocationKind == Implicit);
+ LocationKind = Implicit;
break;
case dwarf::DW_OP_swap:
+ assert(LocationKind != Register);
emitOp(dwarf::DW_OP_swap);
break;
case dwarf::DW_OP_xderef:
+ assert(LocationKind != Register);
emitOp(dwarf::DW_OP_xderef);
break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
}
+
+ if (LocationKind == Implicit)
+ // Turn this into an implicit location description.
+ addStackValue();
}
/// add masking operations to stencil out a subregister.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index e8dc211eb3c..00734fd6843 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -16,6 +16,7 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/MC/MachineLocation.h"
namespace llvm {
@@ -102,6 +103,9 @@ protected:
unsigned SubRegisterSizeInBits = 0;
unsigned SubRegisterOffsetInBits = 0;
+ /// The kind of location description being produced.
+ enum { Unknown = 0, Register, Memory, Implicit } LocationKind = Unknown;
+
/// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
/// to represent a subregister.
void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
@@ -109,6 +113,8 @@ protected:
SubRegisterOffsetInBits = OffsetInBits;
}
+ void setMemoryLocationKind();
+
/// Add masking operations to stencil out a subregister.
void maskSubRegister();
@@ -122,7 +128,8 @@ protected:
/// current function.
virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
- /// Emit a DW_OP_reg operation.
+ /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
+ /// register location description.
void addReg(int DwarfReg, const char *Comment = nullptr);
/// Emit a DW_OP_breg operation.
void addBReg(int DwarfReg, int Offset);
@@ -194,8 +201,8 @@ public:
/// fragment inside the entire variable.
/// \return false if no DWARF register exists
/// for MachineReg.
- bool addMachineRegExpression(const TargetRegisterInfo &TRI,
- DIExpressionCursor &Expr, unsigned MachineReg,
+ bool addMachineLocExpression(const TargetRegisterInfo &TRI,
+ DIExpressionCursor &Expr, MachineLocation Loc,
unsigned FragmentOffsetInBits = 0);
/// Emit all remaining operations in the DIExpressionCursor.
///
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 89ab4a3c1ce..f5dccd17295 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -474,10 +474,9 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
SmallVector<uint64_t, 9> Ops;
- if (Location.isIndirect()) {
+ if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
- Ops.push_back(dwarf::DW_OP_deref);
}
// If we started with a pointer to the __Block_byref... struct, then
// the first thing we need to do is dereference the pointer (DW_OP_deref).
@@ -506,7 +505,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
DIExpressionCursor Cursor(Ops);
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
- if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
+ if (!DwarfExpr.addMachineLocExpression(TRI, Cursor, Location))
return;
DwarfExpr.addExpression(std::move(Cursor));
diff --git a/llvm/lib/CodeGen/InlineSpiller.cpp b/llvm/lib/CodeGen/InlineSpiller.cpp
index a1cb0a0695b..b7ab404070b 100644
--- a/llvm/lib/CodeGen/InlineSpiller.cpp
+++ b/llvm/lib/CodeGen/InlineSpiller.cpp
@@ -888,20 +888,10 @@ void InlineSpiller::spillAroundUses(unsigned Reg) {
// Debug values are not allowed to affect codegen.
if (MI->isDebugValue()) {
// Modify DBG_VALUE now that the value is in a spill slot.
- bool IsIndirect = MI->isIndirectDebugValue();
- uint64_t Offset = IsIndirect ? MI->getOperand(1).getImm() : 0;
- const MDNode *Var = MI->getDebugVariable();
- const MDNode *Expr = MI->getDebugExpression();
- DebugLoc DL = MI->getDebugLoc();
- DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI);
MachineBasicBlock *MBB = MI->getParent();
- assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
- "Expected inlined-at fields to agree");
- BuildMI(*MBB, MBB->erase(MI), DL, TII.get(TargetOpcode::DBG_VALUE))
- .addFrameIndex(StackSlot)
- .addImm(Offset)
- .addMetadata(Var)
- .addMetadata(Expr);
+ DEBUG(dbgs() << "Modifying debug info due to spill:\t" << *MI);
+ buildDbgValueForSpill(*MBB, MI, *MI, StackSlot);
+ MBB->erase(MI);
continue;
}
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index c0a8b95ed8a..4bd5fbfe38e 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2351,3 +2351,31 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI);
}
+
+MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I,
+ const MachineInstr &Orig,
+ int FrameIndex) {
+ const MDNode *Var = Orig.getDebugVariable();
+ auto *Expr = cast_or_null<DIExpression>(Orig.getDebugExpression());
+ bool IsIndirect = Orig.isIndirectDebugValue();
+ uint64_t Offset = IsIndirect ? Orig.getOperand(1).getImm() : 0;
+ DebugLoc DL = Orig.getDebugLoc();
+ assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
+ "Expected inlined-at fields to agree");
+ // If the DBG_VALUE already was a memory location, add an extra
+ // DW_OP_deref. Otherwise just turning this from a register into a
+ // memory/indirect location is sufficient.
+ if (IsIndirect) {
+ SmallVector<uint64_t, 8> Ops;
+ Ops.push_back(dwarf::DW_OP_deref);
+ if (Expr)
+ Ops.append(Expr->elements_begin(), Expr->elements_end());
+ Expr = DIExpression::get(Expr->getContext(), Ops);
+ }
+ return BuildMI(BB, I, DL, Orig.getDesc())
+ .addFrameIndex(FrameIndex)
+ .addImm(Offset)
+ .addMetadata(Var)
+ .addMetadata(Expr);
+}
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index fd759bc372b..283d84629f8 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -304,19 +304,7 @@ void RAFast::spillVirtReg(MachineBasicBlock::iterator MI,
LiveDbgValueMap[LRI->VirtReg];
for (unsigned li = 0, le = LRIDbgValues.size(); li != le; ++li) {
MachineInstr *DBG = LRIDbgValues[li];
- const MDNode *Var = DBG->getDebugVariable();
- const MDNode *Expr = DBG->getDebugExpression();
- bool IsIndirect = DBG->isIndirectDebugValue();
- uint64_t Offset = IsIndirect ? DBG->getOperand(1).getImm() : 0;
- DebugLoc DL = DBG->getDebugLoc();
- assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
- "Expected inlined-at fields to agree");
- MachineInstr *NewDV =
- BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::DBG_VALUE))
- .addFrameIndex(FI)
- .addImm(Offset)
- .addMetadata(Var)
- .addMetadata(Expr);
+ MachineInstr *NewDV = buildDbgValueForSpill(*MBB, MI, *DBG, FI);
assert(NewDV->getParent() == MBB && "dangling parent pointer");
(void)NewDV;
DEBUG(dbgs() << "Inserting debug info due to spill:" << "\n" << *NewDV);
diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp
index fa68411284e..7fa379d80c6 100644
--- a/llvm/lib/CodeGen/SafeStack.cpp
+++ b/llvm/lib/CodeGen/SafeStack.cpp
@@ -550,7 +550,7 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack(
// Replace alloc with the new location.
replaceDbgDeclare(Arg, BasePointer, BasePointer->getNextNode(), DIB,
- /*Deref=*/true, -Offset);
+ /*Deref=*/false, -Offset);
Arg->replaceAllUsesWith(NewArg);
IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode());
IRB.CreateMemCpy(Off, Arg, Size, Arg->getParamAlignment());
@@ -565,7 +565,7 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack(
if (Size == 0)
Size = 1; // Don't create zero-sized stack objects.
- replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -Offset);
+ replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/false, -Offset);
replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset);
// Replace uses of the alloca with the new location.
@@ -655,7 +655,7 @@ void SafeStack::moveDynamicAllocasToUnsafeStack(
if (AI->hasName() && isa<Instruction>(NewAI))
NewAI->takeName(AI);
- replaceDbgDeclareForAlloca(AI, NewAI, DIB, /*Deref=*/true);
+ replaceDbgDeclareForAlloca(AI, NewAI, DIB, /*Deref=*/false);
AI->replaceAllUsesWith(NewAI);
AI->eraseFromParent();
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 0584ab9f60d..6fb26fc3b73 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1164,9 +1164,11 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
"Expected inlined-at fields to agree");
if (Op->isReg()) {
Op->setIsDebug(true);
+ // A dbg.declare describes the address of a source variable, so lower it
+ // into an indirect DBG_VALUE.
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::DBG_VALUE), false, Op->getReg(), 0,
- DI->getVariable(), DI->getExpression());
+ TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true,
+ Op->getReg(), 0, DI->getVariable(), DI->getExpression());
} else
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(TargetOpcode::DBG_VALUE))
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8708f58f1e6..5d1992068dd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4674,7 +4674,7 @@ static unsigned getUnderlyingArgReg(const SDValue &N) {
/// At the end of instruction selection, they will be inserted to the entry BB.
bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
const Value *V, DILocalVariable *Variable, DIExpression *Expr,
- DILocation *DL, int64_t Offset, bool IsIndirect, const SDValue &N) {
+ DILocation *DL, int64_t Offset, bool IsDbgDeclare, const SDValue &N) {
const Argument *Arg = dyn_cast<Argument>(V);
if (!Arg)
return false;
@@ -4688,6 +4688,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
if (!Variable->getScope()->getSubprogram()->describes(MF.getFunction()))
return false;
+ bool IsIndirect = false;
Optional<MachineOperand> Op;
// Some arguments' frame index is recorded during argument lowering.
if (int FI = FuncInfo.getArgumentFrameIndex(Arg))
@@ -4701,15 +4702,19 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
if (PR)
Reg = PR;
}
- if (Reg)
+ if (Reg) {
Op = MachineOperand::CreateReg(Reg, false);
+ IsIndirect = IsDbgDeclare;
+ }
}
if (!Op) {
// Check if ValueMap has reg number.
DenseMap<const Value *, unsigned>::iterator VMI = FuncInfo.ValueMap.find(V);
- if (VMI != FuncInfo.ValueMap.end())
+ if (VMI != FuncInfo.ValueMap.end()) {
Op = MachineOperand::CreateReg(VMI->second, false);
+ IsIndirect = IsDbgDeclare;
+ }
}
if (!Op && N.getNode())
@@ -4955,8 +4960,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
} else if (isa<Argument>(Address)) {
// Address is an argument, so try to emit its dbg value using
// virtual register info from the FuncInfo.ValueMap.
- EmitFuncArgumentDbgValue(Address, Variable, Expression, dl, 0, false,
- N);
+ EmitFuncArgumentDbgValue(Address, Variable, Expression, dl, 0, true, N);
return nullptr;
} else {
SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(),
@@ -4966,7 +4970,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
} else {
// If Address is an argument then try to emit its dbg value using
// virtual register info from the FuncInfo.ValueMap.
- if (!EmitFuncArgumentDbgValue(Address, Variable, Expression, dl, 0, false,
+ if (!EmitFuncArgumentDbgValue(Address, Variable, Expression, dl, 0, true,
N)) {
// If variable is pinned by a alloca in dominating bb then
// use StaticAllocaMap.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index c6acc09b660..9e34590cc39 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -928,7 +928,7 @@ private:
/// instruction selection, they will be inserted to the entry BB.
bool EmitFuncArgumentDbgValue(const Value *V, DILocalVariable *Variable,
DIExpression *Expr, DILocation *DL,
- int64_t Offset, bool IsIndirect,
+ int64_t Offset, bool IsDbgDeclare,
const SDValue &N);
/// Return the next block after MBB, or nullptr if there is none.
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 94cfc69ed55..036dd8d39a0 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -2586,7 +2586,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
Value *NewAllocaPtr = IRB.CreateIntToPtr(
IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)),
AI->getType());
- replaceDbgDeclareForAlloca(AI, NewAllocaPtr, DIB, /*Deref=*/true);
+ replaceDbgDeclareForAlloca(AI, NewAllocaPtr, DIB, /*Deref=*/false);
AI->replaceAllUsesWith(NewAllocaPtr);
}
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 18b29226c2e..8c544276264 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1227,13 +1227,9 @@ bool llvm::LowerDbgDeclare(Function &F) {
// This is a call by-value or some other instruction that
// takes a pointer to the variable. Insert a *value*
// intrinsic that describes the alloca.
- SmallVector<uint64_t, 1> NewDIExpr;
- auto *DIExpr = DDI->getExpression();
- NewDIExpr.push_back(dwarf::DW_OP_deref);
- NewDIExpr.append(DIExpr->elements_begin(), DIExpr->elements_end());
DIB.insertDbgValueIntrinsic(AI, 0, DDI->getVariable(),
- DIB.createExpression(NewDIExpr),
- DDI->getDebugLoc(), CI);
+ DDI->getExpression(), DDI->getDebugLoc(),
+ CI);
}
}
DDI->eraseFromParent();
diff --git a/llvm/test/Bitcode/DIExpression-aggresult.ll b/llvm/test/Bitcode/DIExpression-aggresult.ll
new file mode 100644
index 00000000000..5ce936d7074
--- /dev/null
+++ b/llvm/test/Bitcode/DIExpression-aggresult.ll
@@ -0,0 +1,36 @@
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+%class.A = type { i32, i32, i32, i32 }
+
+define void @_Z3fooi(%class.A* sret %agg.result) #0 !dbg !3 {
+ ; CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[EXPR:[0-9]+]]), !dbg
+ ; CHECK: ![[EXPR]] = !DIExpression()
+ call void @llvm.dbg.declare(metadata %class.A* %agg.result, metadata !13, metadata !16), !dbg !17
+ ret void, !dbg !17
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { ssp }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "a.cc", directory: "/tmp")
+!2 = !{i32 1, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 4, type: !4, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
+!4 = !DISubroutineType(types: !5)
+!5 = !{!6}
+!6 = !DICompositeType(tag: DW_TAG_class_type, name: "A", scope: !0, file: !1, line: 2, size: 128, align: 32, elements: !7)
+!7 = !{!8, !10, !11, !12}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !1, file: !1, line: 2, baseType: !9, size: 32, align: 32)
+!9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !1, file: !1, line: 2, baseType: !9, size: 32, align: 32, offset: 32)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !1, file: !1, line: 2, baseType: !9, size: 32, align: 32, offset: 64)
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "o", scope: !1, file: !1, line: 2, baseType: !9, size: 32, align: 32, offset: 96)
+!13 = !DILocalVariable(name: "my_a", scope: !14, file: !1, line: 9, type: !15)
+!14 = distinct !DILexicalBlock(scope: !3, file: !1, line: 4, column: 14)
+!15 = !DIDerivedType(tag: DW_TAG_reference_type, file: !1, baseType: !6)
+!16 = !DIExpression(DW_OP_deref)
+!17 = !DILocation(line: 9, column: 5, scope: !3)
diff --git a/llvm/test/Bitcode/DIExpression-aggresult.ll.bc b/llvm/test/Bitcode/DIExpression-aggresult.ll.bc
new file mode 100644
index 00000000000..bcf6e175b4d
--- /dev/null
+++ b/llvm/test/Bitcode/DIExpression-aggresult.ll.bc
Binary files differ
diff --git a/llvm/test/Bitcode/DIExpression-deref.ll b/llvm/test/Bitcode/DIExpression-deref.ll
new file mode 100644
index 00000000000..3a161b8ee4d
--- /dev/null
+++ b/llvm/test/Bitcode/DIExpression-deref.ll
@@ -0,0 +1,27 @@
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!20, !21}
+
+!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true)
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang (llvm/trunk 288154)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
+!2 = !DIFile(filename: "a.c", directory: "/")
+!3 = !{}
+!4 = !{!10, !11, !12, !13}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; DW_OP_deref should be moved to the back of the expression.
+;
+; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32)
+!6 = !DIExpression(DW_OP_deref, DW_OP_plus, 0, DW_OP_LLVM_fragment, 8, 32)
+; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref)
+!7 = !DIExpression(DW_OP_deref, DW_OP_plus, 0)
+; CHECK: !DIExpression(DW_OP_plus, 1, DW_OP_deref)
+!8 = !DIExpression(DW_OP_plus, 1, DW_OP_deref)
+; CHECK: !DIExpression(DW_OP_deref)
+!9 = !DIExpression(DW_OP_deref)
+!10 = !DIGlobalVariableExpression(var: !0, expr: !6)
+!11 = !DIGlobalVariableExpression(var: !0, expr: !7)
+!12 = !DIGlobalVariableExpression(var: !0, expr: !8)
+!13 = !DIGlobalVariableExpression(var: !0, expr: !9)
+!20 = !{i32 2, !"Dwarf Version", i32 4}
+!21 = !{i32 2, !"Debug Info Version", i32 3}
diff --git a/llvm/test/Bitcode/DIExpression-deref.ll.bc b/llvm/test/Bitcode/DIExpression-deref.ll.bc
new file mode 100644
index 00000000000..5297bf9f17b
--- /dev/null
+++ b/llvm/test/Bitcode/DIExpression-deref.ll.bc
Binary files differ
diff --git a/llvm/test/DebugInfo/ARM/selectiondag-deadcode.ll b/llvm/test/DebugInfo/ARM/selectiondag-deadcode.ll
index fe5e87658dd..d4d0207bf07 100644
--- a/llvm/test/DebugInfo/ARM/selectiondag-deadcode.ll
+++ b/llvm/test/DebugInfo/ARM/selectiondag-deadcode.ll
@@ -13,7 +13,7 @@ _ZN7Vector39NormalizeEv.exit: ; preds = %1, %0
; and SelectionDAGISel crashes. It should definitely not
; crash. Drop the dbg_value instead.
; CHECK-NOT: "matrix"
- tail call void @llvm.dbg.declare(metadata %class.Matrix3.0.6.10* %agg.result, metadata !45, metadata !DIExpression(DW_OP_deref))
+ tail call void @llvm.dbg.declare(metadata %class.Matrix3.0.6.10* %agg.result, metadata !45, metadata !DIExpression())
%2 = getelementptr inbounds %class.Matrix3.0.6.10, %class.Matrix3.0.6.10* %agg.result, i32 0, i32 0, i32 8
ret void
}
diff --git a/llvm/test/DebugInfo/Generic/block-asan.ll b/llvm/test/DebugInfo/Generic/block-asan.ll
index 96072b1ccfb..f1f8b35df27 100644
--- a/llvm/test/DebugInfo/Generic/block-asan.ll
+++ b/llvm/test/DebugInfo/Generic/block-asan.ll
@@ -13,7 +13,7 @@
; Check that the location of the ASAN instrumented __block variable is
; correct.
-; CHECK: !DIExpression(DW_OP_deref, DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24)
+; CHECK: !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24)
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/DebugInfo/X86/dbg-declare-arg.ll b/llvm/test/DebugInfo/X86/dbg-declare-arg.ll
index 7fd6296c7ee..ca865ab5982 100644
--- a/llvm/test/DebugInfo/X86/dbg-declare-arg.ll
+++ b/llvm/test/DebugInfo/X86/dbg-declare-arg.ll
@@ -1,9 +1,17 @@
-; RUN: llc -O0 -fast-isel=false < %s | FileCheck %s
+; RUN: llc -O0 -fast-isel=true -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-macosx10.6.7"
-;Radar 9321650
-
-;CHECK: ##DEBUG_VALUE: my_a
+; rdar://problem/9321650
+;
+; CHECK: DW_AT_name {{.*}}"j"
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000)
+; CHECK-NEXT: DW_AT_name {{.*}}"my_a"
+; CHECK: .debug_loc contents:
+; CHECK: 0x00000000: Beginning address offset:
+; CHECK-NEXT: Ending address offset:
+; CHECK-NEXT: Location description: 77 08
+; rsp+8
%class.A = type { i32, i32, i32, i32 }
diff --git a/llvm/test/DebugInfo/X86/dbg_value_direct.ll b/llvm/test/DebugInfo/X86/dbg_value_direct.ll
index 58560e4c81d..12adf125fad 100644
--- a/llvm/test/DebugInfo/X86/dbg_value_direct.ll
+++ b/llvm/test/DebugInfo/X86/dbg_value_direct.ll
@@ -70,7 +70,7 @@ entry:
; <label>:28 ; preds = %22, %entry
store i32 %0, i32* %3, align 4
- call void @llvm.dbg.declare(metadata %struct.A* %agg.result, metadata !24, metadata !DIExpression(DW_OP_deref)), !dbg !25
+ call void @llvm.dbg.declare(metadata %struct.A* %agg.result, metadata !24, metadata !DIExpression()), !dbg !25
call void @_ZN1AC1Ev(%struct.A* %agg.result), !dbg !25
store i64 1172321806, i64* %4, !dbg !26
%29 = inttoptr i64 %10 to i32*, !dbg !26
diff --git a/llvm/test/DebugInfo/X86/debug-info-block-captured-self.ll b/llvm/test/DebugInfo/X86/debug-info-block-captured-self.ll
index e3cfca19955..1085eaef0d4 100644
--- a/llvm/test/DebugInfo/X86/debug-info-block-captured-self.ll
+++ b/llvm/test/DebugInfo/X86/debug-info-block-captured-self.ll
@@ -107,5 +107,5 @@ define internal void @"__24-[Main initWithContext:]_block_invoke_2"(i8* %.block_
!106 = !DILocation(line: 40, scope: !42)
!107 = !DIFile(filename: "llvm/tools/clang/test/CodeGenObjC/debug-info-block-captured-self.m", directory: "")
!108 = !{i32 1, !"Debug Info Version", i32 3}
-!109 = !DIExpression(DW_OP_deref, DW_OP_plus, 32)
-!110 = !DIExpression(DW_OP_deref, DW_OP_plus, 32)
+!109 = !DIExpression(DW_OP_plus, 32, DW_OP_deref)
+!110 = !DIExpression(DW_OP_plus, 32, DW_OP_deref)
diff --git a/llvm/test/DebugInfo/X86/dw_op_minus.ll b/llvm/test/DebugInfo/X86/dw_op_minus.ll
index e76f2933fdd..8e65b489c27 100644
--- a/llvm/test/DebugInfo/X86/dw_op_minus.ll
+++ b/llvm/test/DebugInfo/X86/dw_op_minus.ll
@@ -10,7 +10,7 @@
; Capture(buf);
; }
; }
-; The interesting part is !DIExpression(DW_OP_deref, DW_OP_minus, 400)
+; The interesting part is !DIExpression(DW_OP_minus, 400)
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@@ -56,20 +56,17 @@ declare void @Capture(i32*)
!14 = !{i32 2, !"Debug Info Version", i32 3}
!15 = !{!"clang version 3.8.0 (trunk 248518) (llvm/trunk 248512)"}
!16 = !DILocation(line: 5, column: 3, scope: !4)
-!17 = !DIExpression(DW_OP_deref, DW_OP_minus, 400)
+!17 = !DIExpression(DW_OP_minus, 400)
!18 = !DILocation(line: 5, column: 7, scope: !4)
!19 = !DILocation(line: 6, column: 11, scope: !4)
!20 = !DILocation(line: 6, column: 3, scope: !4)
!21 = !DILocation(line: 7, column: 1, scope: !4)
; RCX - 400
-; CHECK: .short 6 # Loc expr size
+; CHECK: .short 3 # Loc expr size
; CHECK-NEXT: .byte 114 # DW_OP_breg2
-; CHECK-NEXT: .byte 0 # 0
-; CHECK-NEXT: .byte 16 # DW_OP_constu
-; CHECK-NEXT: .byte 144 # 400
-; CHECK-NEXT: .byte 3 # DW_OP_minus
-; CHECK-NEXT: .byte 28
+; CHECK-NEXT: .byte 240 # -400
+; CHECK-NEXT: .byte 124
; RCX is clobbered in call @Capture, but there is a spilled copy.
; *(RSP + 8) - 400
diff --git a/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll b/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll
index 29e07213abb..a204b29848f 100644
--- a/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll
+++ b/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll
@@ -8,8 +8,8 @@
; CHECK: Beginning address offset: 0x0000000000000000
; CHECK: Ending address offset: 0x0000000000000004
-; CHECK: Location description: 50 10 ff ff ff ff 0f 1a 10 01 1c
-; rax, constu 0xffffffff, and, constu 0x00000001, minus
+; CHECK: Location description: 70 00 10 ff ff ff ff 0f 1a 10 01 1c 9f
+; rax+0, constu 0xffffffff, and, constu 0x00000001, minus, stack-value
source_filename = "minus.c"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
@@ -42,7 +42,7 @@ attributes #1 = { nounwind readnone }
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10)
-!13 = !DIExpression(DW_OP_minus, 1)
+!13 = !DIExpression(DW_OP_minus, 1, DW_OP_stack_value)
!14 = !DILocation(line: 1, column: 13, scope: !7)
!15 = !DILocation(line: 2, column: 11, scope: !7)
!16 = !DILocation(line: 2, column: 3, scope: !7)
diff --git a/llvm/test/DebugInfo/X86/sret.ll b/llvm/test/DebugInfo/X86/sret.ll
index 84d67193488..c4bb005a366 100644
--- a/llvm/test/DebugInfo/X86/sret.ll
+++ b/llvm/test/DebugInfo/X86/sret.ll
@@ -1,10 +1,22 @@
; RUN: llc -split-dwarf=Enable -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t
-; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s
+; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s --check-prefix=CHECK-DWO
; Based on the debuginfo-tests/sret.cpp code.
-; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x51ac5644b1937aa1)
-; CHECK: 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] (0x51ac5644b1937aa1)
+
+; RUN: llc -O0 -fast-isel=true -mtriple=x86_64-apple-darwin -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+; RUN: llc -O0 -fast-isel=false -mtriple=x86_64-apple-darwin -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+; CHECK: _ZN1B9AInstanceEv
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000)
+; CHECK-NEXT: DW_AT_name {{.*}}"a"
+; CHECK: .debug_loc contents:
+; CHECK: 0x00000000: Beginning address offset:
+; CHECK-NEXT: Ending address offset:
+; CHECK-NEXT: Location description: 75 00
+; rdi+0
%class.A = type { i32 (...)**, i32 }
%class.B = type { i8 }
@@ -98,7 +110,7 @@ entry:
call void @llvm.dbg.declare(metadata %class.B** %this.addr, metadata !89, metadata !DIExpression()), !dbg !91
%this1 = load %class.B*, %class.B** %this.addr
store i1 false, i1* %nrvo, !dbg !92
- call void @llvm.dbg.declare(metadata %class.A* %agg.result, metadata !93, metadata !DIExpression(DW_OP_deref)), !dbg !92
+ call void @llvm.dbg.declare(metadata %class.A* %agg.result, metadata !93, metadata !DIExpression()), !dbg !92
call void @_ZN1AC1Ei(%class.A* %agg.result, i32 12), !dbg !92
store i1 true, i1* %nrvo, !dbg !94
store i32 1, i32* %cleanup.dest.slot
diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
index cc79cbbce9e..0366c0008d3 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
@@ -24,9 +24,9 @@ entry:
; CHECK: entry:
; Verify that llvm.dbg.declare calls are in the entry basic block.
; CHECK-NOT: %entry
-; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[ARG_ID:[0-9]+]], metadata ![[OPDEREF:[0-9]+]])
+; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[ARG_ID:[0-9]+]], metadata ![[EMPTY:[0-9]+]])
; CHECK-NOT: %entry
-; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[VAR_ID:[0-9]+]], metadata ![[OPDEREF:[0-9]+]])
+; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[VAR_ID:[0-9]+]], metadata ![[EMPTY:[0-9]+]])
declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
@@ -47,7 +47,7 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
; Verify that debug descriptors for argument and local variable will be replaced
; with descriptors that end with OpDeref (encoded as 2).
; CHECK: ![[ARG_ID]] = !DILocalVariable(name: "p", arg: 1,{{.*}} line: 1
-; CHECK: ![[OPDEREF]] = !DIExpression(DW_OP_deref)
+; CHECK: ![[EMPTY]] = !DIExpression()
; CHECK: ![[VAR_ID]] = !DILocalVariable(name: "r",{{.*}} line: 2
; Verify that there are no more variable descriptors.
; CHECK-NOT: !DILocalVariable(tag: DW_TAG_arg_variable
diff --git a/llvm/test/Transforms/SafeStack/X86/debug-loc.ll b/llvm/test/Transforms/SafeStack/X86/debug-loc.ll
index fc0b6f911f7..88cda693b29 100644
--- a/llvm/test/Transforms/SafeStack/X86/debug-loc.ll
+++ b/llvm/test/Transforms/SafeStack/X86/debug-loc.ll
@@ -37,10 +37,10 @@ entry:
; CHECK-DAG: ![[VAR_ARG]] = !DILocalVariable(name: "zzz"
; 100 aligned up to 8
-; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_deref, DW_OP_minus, 104
+; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_minus, 104)
; CHECK-DAG: ![[VAR_LOCAL]] = !DILocalVariable(name: "xxx"
-; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_deref, DW_OP_minus, 208
+; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_minus, 208)
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
OpenPOWER on IntegriCloud