aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfExpression.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.cpp95
1 files changed, 75 insertions, 20 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index 2858afaa1cf1..1c5a244d7c5d 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/ErrorHandling.h"
@@ -97,7 +98,7 @@ void DwarfExpression::addAnd(unsigned Mask) {
bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI,
unsigned MachineReg, unsigned MaxSize) {
- if (!TRI.isPhysicalRegister(MachineReg)) {
+ if (!llvm::Register::isPhysicalRegister(MachineReg)) {
if (isFrameRegister(TRI, MachineReg)) {
DwarfRegs.push_back({-1, 0, nullptr});
return true;
@@ -241,15 +242,22 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
return false;
}
- // Handle simple register locations.
- if (!isMemoryLocation() && !HasComplexExpression) {
+ // Handle simple register locations. If we are supposed to emit
+ // 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())) {
for (auto &Reg : DwarfRegs) {
if (Reg.DwarfRegNo >= 0)
addReg(Reg.DwarfRegNo, Reg.Comment);
addOpPiece(Reg.Size);
}
- if (isEntryValue() && DwarfVersion >= 4)
+ if (isEntryValue())
+ finalizeEntryValue();
+
+ if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4)
emitOp(dwarf::DW_OP_stack_value);
DwarfRegs.clear();
@@ -275,19 +283,27 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
// Pattern-match combinations for which more efficient representations exist.
// [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset].
if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) {
- SignedOffset = Op->getArg(0);
- ExprCursor.take();
+ uint64_t Offset = Op->getArg(0);
+ uint64_t IntMax = static_cast<uint64_t>(std::numeric_limits<int>::max());
+ if (Offset <= IntMax) {
+ SignedOffset = Offset;
+ ExprCursor.take();
+ }
}
// [Reg, DW_OP_constu, Offset, DW_OP_plus] --> [DW_OP_breg, Offset]
// [Reg, DW_OP_constu, 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_constu) {
+ uint64_t Offset = Op->getArg(0);
+ uint64_t IntMax = static_cast<uint64_t>(std::numeric_limits<int>::max());
auto N = ExprCursor.peekNext();
- if (N && (N->getOp() == dwarf::DW_OP_plus ||
- (N->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
- int Offset = Op->getArg(0);
- SignedOffset = (N->getOp() == dwarf::DW_OP_minus) ? -Offset : Offset;
+ if (N && N->getOp() == dwarf::DW_OP_plus && Offset <= IntMax) {
+ SignedOffset = Offset;
+ ExprCursor.consume(2);
+ } else if (N && N->getOp() == dwarf::DW_OP_minus &&
+ !SubRegisterSizeInBits && Offset <= IntMax + 1) {
+ SignedOffset = -static_cast<int64_t>(Offset);
ExprCursor.consume(2);
}
}
@@ -300,17 +316,34 @@ 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);
+ (void)Op;
+ 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");
- if (DwarfVersion >= 5)
- emitOp(dwarf::DW_OP_entry_value);
- else
- emitOp(dwarf::DW_OP_GNU_entry_value);
- emitUnsigned(Op->getArg(0));
+ emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));
+ 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?".
@@ -340,7 +373,17 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
while (ExprCursor) {
auto Op = ExprCursor.take();
- switch (Op->getOp()) {
+ uint64_t OpNum = Op->getOp();
+
+ if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
+ emitOp(OpNum);
+ continue;
+ } else if (OpNum >= dwarf::DW_OP_breg0 && OpNum <= dwarf::DW_OP_breg31) {
+ addBReg(OpNum - dwarf::DW_OP_breg0, Op->getArg(0));
+ continue;
+ }
+
+ switch (OpNum) {
case dwarf::DW_OP_LLVM_fragment: {
unsigned SizeInBits = Op->getArg(1);
unsigned FragmentOffset = Op->getArg(0);
@@ -389,10 +432,13 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
case dwarf::DW_OP_lit0:
case dwarf::DW_OP_not:
case dwarf::DW_OP_dup:
- emitOp(Op->getOp());
+ emitOp(OpNum);
break;
case dwarf::DW_OP_deref:
assert(!isRegisterLocation());
+ // For more detailed explanation see llvm.org/PR43343.
+ assert(!isParameterValue() && "Parameter entry values should not be "
+ "dereferenced due to safety reasons.");
if (!isMemoryLocation() && ::isMemoryLocation(ExprCursor))
// Turning this into a memory location description makes the deref
// implicit.
@@ -458,12 +504,21 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
case dwarf::DW_OP_LLVM_tag_offset:
TagOffset = Op->getArg(0);
break;
+ case dwarf::DW_OP_regx:
+ emitOp(dwarf::DW_OP_regx);
+ emitUnsigned(Op->getArg(0));
+ break;
+ case dwarf::DW_OP_bregx:
+ emitOp(dwarf::DW_OP_bregx);
+ emitUnsigned(Op->getArg(0));
+ emitSigned(Op->getArg(1));
+ break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
}
- if (isImplicitLocation())
+ if (isImplicitLocation() && !isParameterValue())
// Turn this into an implicit location description.
addStackValue();
}