summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDavid Stenberg <david.stenberg@ericsson.com>2019-10-15 11:31:21 +0000
committerDavid Stenberg <david.stenberg@ericsson.com>2019-10-15 11:31:21 +0000
commit1ae2d9a2bdce054560104f428e92eaef736e5c7f (patch)
tree934b8a328d536d2beacb483d90573b4e6ee07fac /llvm/lib
parent0e62011df891d0e7ad904524edf705d07d12d5d4 (diff)
downloadbcm5719-llvm-1ae2d9a2bdce054560104f428e92eaef736e5c7f.tar.gz
bcm5719-llvm-1ae2d9a2bdce054560104f428e92eaef736e5c7f.zip
[DebugInfo] Add a DW_OP_LLVM_entry_value operation
Summary: Internally in LLVM's metadata we use DW_OP_entry_value operations with the same semantics as DWARF; that is, its operand specifies the number of bytes that the entry value covers. At the time of emitting entry values we don't know the emitted size of the DWARF expression that the entry value will cover. Currently the size is hardcoded to 1 in DIExpression, and other values causes the verifier to fail. As the size is 1, that effectively means that we can only have valid entry values for registers that can be encoded in one byte, which are the registers with DWARF numbers 0 to 31 (as they can be encoded as single-byte DW_OP_reg0..DW_OP_reg31 rather than a multi-byte DW_OP_regx). It is a bit confusing, but it seems like llvm-dwarfdump will print an operation "correctly", even if the byte size is less than that, which may make it seem that we emit correct DWARF for registers with DWARF numbers > 31. If you instead use readelf for such cases, it will interpret the number of specified bytes as a DWARF expression. This seems like a limitation in llvm-dwarfdump. As suggested in D66746, a way forward would be to add an internal variant of DW_OP_entry_value, DW_OP_LLVM_entry_value, whose operand instead specifies the number of operations that the entry value covers, and we then translate that into the byte size at the time of emission. In this patch that internal operation is added. This patch keeps the limitation that a entry value can only be applied to simple register locations, but it will fix the issue with the size operand being incorrect for DWARF numbers > 31. Reviewers: aprantl, vsk, djtodoro, NikolaPrica Reviewed By: aprantl Subscribers: jyknight, fedor.sergeev, hiraditya, llvm-commits Tags: #debug-info, #llvm Differential Revision: https://reviews.llvm.org/D67492 llvm-svn: 374881
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/BinaryFormat/Dwarf.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp2
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp2
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp9
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp28
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h14
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp14
-rw-r--r--llvm/lib/IR/Verifier.cpp15
8 files changed, 68 insertions, 19 deletions
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index cb92f80318e..d06cccdf0df 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -149,6 +149,8 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
return "DW_OP_LLVM_fragment";
case DW_OP_LLVM_tag_offset:
return "DW_OP_LLVM_tag_offset";
+ case DW_OP_LLVM_entry_value:
+ return "DW_OP_LLVM_entry_value";
}
}
@@ -160,6 +162,7 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
.Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert)
.Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
.Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
+ .Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value)
.Default(0);
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
index 9d05cfe9bdc..7f9d6c618ad 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
@@ -41,7 +41,7 @@ using EntryIndex = DbgValueHistoryMap::EntryIndex;
static Register isDescribedByReg(const MachineInstr &MI) {
assert(MI.isDebugValue());
assert(MI.getNumOperands() == 4);
- // If the location of variable is an entry value (DW_OP_entry_value)
+ // If the location of variable is an entry value (DW_OP_LLVM_entry_value)
// do not consider it as a register location.
if (MI.getDebugExpression()->isEntryValue())
return 0;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index d284d4ffa44..a61c98ec1c1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1205,7 +1205,7 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
if (DIExpr->isEntryValue()) {
DwarfExpr.setEntryValueFlag();
- DwarfExpr.addEntryValueExpression(Cursor);
+ DwarfExpr.beginEntryValueExpression(Cursor);
}
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 7d7cadcce17..91eb27ca258 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -669,10 +669,9 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
// Emit the call site parameter's value as an entry value.
if (ShouldTryEmitEntryVals) {
- // Create an entry value expression where the expression following
- // the 'DW_OP_entry_value' will be the size of 1 (a register operation).
- DIExpression *EntryExpr = DIExpression::get(MF->getFunction().getContext(),
- {dwarf::DW_OP_entry_value, 1});
+ // Create an expression where the register's entry value is used.
+ DIExpression *EntryExpr = DIExpression::get(
+ MF->getFunction().getContext(), {dwarf::DW_OP_LLVM_entry_value, 1});
for (auto RegEntry : ForwardedRegWorklist) {
unsigned FwdReg = RegEntry;
auto EntryValReg = RegsForEntryValues.find(RegEntry);
@@ -2200,7 +2199,7 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
if (DIExpr->isEntryValue()) {
DwarfExpr.setEntryValueFlag();
- DwarfExpr.addEntryValueExpression(Cursor);
+ DwarfExpr.beginEntryValueExpression(Cursor);
}
const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index ea42e60344d..42a7f5607e7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -254,6 +254,9 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
addOpPiece(Reg.Size);
}
+ if (isEntryValue())
+ finalizeEntryValue();
+
if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4)
emitOp(dwarf::DW_OP_stack_value);
@@ -313,14 +316,33 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
return true;
}
-void DwarfExpression::addEntryValueExpression(DIExpressionCursor &ExprCursor) {
+void DwarfExpression::beginEntryValueExpression(
+ DIExpressionCursor &ExprCursor) {
auto Op = ExprCursor.take();
- assert(Op && Op->getOp() == dwarf::DW_OP_entry_value);
+ assert(Op && Op->getOp() == dwarf::DW_OP_LLVM_entry_value);
assert(!isMemoryLocation() &&
"We don't support entry values of memory locations yet");
+ assert(!IsEmittingEntryValue && "Already emitting entry value?");
+ assert(Op->getArg(0) == 1 &&
+ "Can currently only emit entry values covering a single operation");
emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));
- emitUnsigned(Op->getArg(0));
+ IsEmittingEntryValue = true;
+ enableTemporaryBuffer();
+}
+
+void DwarfExpression::finalizeEntryValue() {
+ assert(IsEmittingEntryValue && "Entry value not open?");
+ disableTemporaryBuffer();
+
+ // Emit the entry value's size operand.
+ unsigned Size = getTemporaryBufferSize();
+ emitUnsigned(Size);
+
+ // Emit the entry value's DWARF block operand.
+ commitTemporaryBuffer();
+
+ IsEmittingEntryValue = false;
}
/// Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?".
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index a4b566669c2..1ad46669f9b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -111,6 +111,9 @@ protected:
const char *Comment;
};
+ /// Whether we are currently emitting an entry value operation.
+ bool IsEmittingEntryValue = false;
+
DwarfCompileUnit &CU;
/// The register location, if any.
@@ -260,6 +263,10 @@ protected:
/// expression. See PR21176 for more details.
void addStackValue();
+ /// Finalize an entry value by emitting its size operand, and committing the
+ /// DWARF block which has been emitted to the temporary buffer.
+ void finalizeEntryValue();
+
~DwarfExpression() = default;
public:
@@ -310,8 +317,11 @@ public:
DIExpressionCursor &Expr, unsigned MachineReg,
unsigned FragmentOffsetInBits = 0);
- /// Emit entry value dwarf operation.
- void addEntryValueExpression(DIExpressionCursor &ExprCursor);
+ /// Begin emission of an entry value dwarf operation. The entry value's
+ /// first operand is the size of the DWARF block (its second operand),
+ /// which needs to be calculated at time of emission, so we don't emit
+ /// any operands here.
+ void beginEntryValueExpression(DIExpressionCursor &ExprCursor);
/// Emit all remaining operations in the DIExpressionCursor.
///
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 2fe9d33ac76..94ec3abfa7a 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -843,7 +843,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
case dwarf::DW_OP_deref_size:
case dwarf::DW_OP_plus_uconst:
case dwarf::DW_OP_LLVM_tag_offset:
- case dwarf::DW_OP_entry_value:
+ case dwarf::DW_OP_LLVM_entry_value:
case dwarf::DW_OP_regx:
return 2;
default:
@@ -890,10 +890,12 @@ bool DIExpression::isValid() const {
return false;
break;
}
- case dwarf::DW_OP_entry_value: {
- // An entry value operator must appear at the begin and the size
- // of following expression should be 1, because we support only
- // entry values of a simple register location.
+ case dwarf::DW_OP_LLVM_entry_value: {
+ // An entry value operator must appear at the beginning and the number of
+ // operations it cover can currently only be 1, because we support only
+ // 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;
}
@@ -1050,7 +1052,7 @@ DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,
assert(Expr && "Can't prepend ops to this expression");
if (EntryValue) {
- Ops.push_back(dwarf::DW_OP_entry_value);
+ Ops.push_back(dwarf::DW_OP_LLVM_entry_value);
// Add size info needed for entry value expression.
// Add plus one for target register operand.
Ops.push_back(Expr->getNumElements() + 1);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 173d69471fc..b17fc433ed7 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -518,6 +518,7 @@ private:
DIExpression::FragmentInfo Fragment,
ValueOrMetadata *Desc);
void verifyFnArgs(const DbgVariableIntrinsic &I);
+ void verifyNotEntryValue(const DbgVariableIntrinsic &I);
/// Module-level debug info verification...
void verifyCompileUnits();
@@ -4213,8 +4214,10 @@ void Verifier::visitInstruction(Instruction &I) {
visitMDNode(*N);
}
- if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I))
+ if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) {
verifyFragmentExpression(*DII);
+ verifyNotEntryValue(*DII);
+ }
InstsInThisBlock.insert(&I);
}
@@ -5047,6 +5050,16 @@ void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) {
Prev, Var);
}
+void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) {
+ DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());
+
+ // We don't know whether this intrinsic verified correctly.
+ if (!E || !E->isValid())
+ return;
+
+ AssertDI(!E->isEntryValue(), "Entry values are only allowed in MIR", &I);
+}
+
void Verifier::verifyCompileUnits() {
// When more than one Module is imported into the same context, such as during
// an LTO build before linking the modules, ODR type uniquing may cause types
OpenPOWER on IntegriCloud