summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp61
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h2
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp12
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h13
4 files changed, 46 insertions, 42 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index e0f11714b84..218f8db9cde 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -949,11 +949,19 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
}
}
+static bool canUseReferenceType(const DbgVariableLocation &Loc) {
+ return !Loc.LoadChain.empty() && Loc.LoadChain.back() == 0;
+}
+
+static bool needsReferenceType(const DbgVariableLocation &Loc) {
+ return Loc.LoadChain.size() == 2 && Loc.LoadChain.back() == 0;
+}
+
void CodeViewDebug::calculateRanges(
LocalVariable &Var, const DbgValueHistoryMap::InstrRanges &Ranges) {
const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();
- // calculate the definition ranges.
+ // Calculate the definition ranges.
for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
const InsnRange &Range = *I;
const MachineInstr *DVInst = Range.first;
@@ -965,39 +973,37 @@ void CodeViewDebug::calculateRanges(
if (!Location)
continue;
- // Because we cannot express DW_OP_deref in CodeView directly,
- // we use a trick: we encode the type as a reference to the
- // real type.
- if (Var.Deref) {
- // When we're encoding the type as a reference to the original type,
- // we need to remove a level of indirection from incoming locations.
- // E.g. [RSP+8] with DW_OP_deref becomes [RSP+8],
- // and [RCX+0] without DW_OP_deref becomes RCX.
- if (!Location->Deref) {
- if (Location->InMemory)
- Location->InMemory = false;
- else
- continue;
- }
- } else if (Location->Deref) {
- // We've encountered a Deref range when we had not applied the
- // reference encoding. Start over using reference encoding.
- Var.Deref = true;
+ // CodeView can only express variables in register and variables in memory
+ // at a constant offset from a register. However, for variables passed
+ // indirectly by pointer, it is common for that pointer to be spilled to a
+ // stack location. For the special case of one offseted load followed by a
+ // zero offset load (a pointer spilled to the stack), we change the type of
+ // the local variable from a value type to a reference type. This tricks the
+ // debugger into doing the load for us.
+ if (Var.UseReferenceType) {
+ // We're using a reference type. Drop the last zero offset load.
+ if (canUseReferenceType(*Location))
+ Location->LoadChain.pop_back();
+ else
+ continue;
+ } else if (needsReferenceType(*Location)) {
+ // This location can't be expressed without switching to a reference type.
+ // Start over using that.
+ Var.UseReferenceType = true;
Var.DefRanges.clear();
calculateRanges(Var, Ranges);
return;
}
- // If we don't know how to handle this range, skip past it.
- if (Location->Register == 0 || (Location->Offset && !Location->InMemory))
+ // We can only handle a register or an offseted load of a register.
+ if (Location->Register == 0 || Location->LoadChain.size() > 1)
continue;
-
- // Handle the two cases we can handle: indirect in memory and in register.
{
LocalVarDefRange DR;
DR.CVRegister = TRI->getCodeViewRegNum(Location->Register);
- DR.InMemory = Location->InMemory;
- DR.DataOffset = Location->Offset;
+ DR.InMemory = !Location->LoadChain.empty();
+ DR.DataOffset =
+ !Location->LoadChain.empty() ? Location->LoadChain.back() : 0;
if (Location->FragmentInfo) {
DR.IsSubfield = true;
DR.StructOffset = Location->FragmentInfo->OffsetInBits / 8;
@@ -2113,8 +2119,9 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
Flags |= LocalSymFlags::IsOptimizedOut;
OS.AddComment("TypeIndex");
- TypeIndex TI = Var.Deref ? getTypeIndexForReferenceTo(Var.DIVar->getType())
- : getCompleteTypeIndex(Var.DIVar->getType());
+ TypeIndex TI = Var.UseReferenceType
+ ? getTypeIndexForReferenceTo(Var.DIVar->getType())
+ : getCompleteTypeIndex(Var.DIVar->getType());
OS.EmitIntValue(TI.getIndex(), 4);
OS.AddComment("Flags");
OS.EmitIntValue(static_cast<uint16_t>(Flags), 2);
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 4345bb4d1c2..fe4f0a0092c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -94,7 +94,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
struct LocalVariable {
const DILocalVariable *DIVar = nullptr;
SmallVector<LocalVarDefRange, 1> DefRanges;
- bool Deref = false;
+ bool UseReferenceType = false;
};
struct InlineSite {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index ee8b38f6502..de3bc914d8d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -34,8 +34,6 @@ DbgVariableLocation::extractFromMachineInstruction(
if (!Instruction.getOperand(0).isReg())
return None;
Location.Register = Instruction.getOperand(0).getReg();
- Location.InMemory = Instruction.getOperand(1).isImm();
- Location.Deref = false;
Location.FragmentInfo.reset();
// We only handle expressions generated by DIExpression::appendOffset,
// which doesn't require a full stack machine.
@@ -67,7 +65,8 @@ DbgVariableLocation::extractFromMachineInstruction(
Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)};
break;
case dwarf::DW_OP_deref:
- Location.Deref = true;
+ Location.LoadChain.push_back(Offset);
+ Offset = 0;
break;
default:
return None;
@@ -75,7 +74,12 @@ DbgVariableLocation::extractFromMachineInstruction(
++Op;
}
- Location.Offset = Offset;
+ // Do one final implicit DW_OP_deref if this was an indirect DBG_VALUE
+ // instruction.
+ // FIXME: Replace these with DIExpression.
+ if (Instruction.isIndirectDebugValue())
+ Location.LoadChain.push_back(Offset);
+
return Location;
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
index 90f8287e76e..245d70038de 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
@@ -30,19 +30,12 @@ class MachineModuleInfo;
/// Represents the location at which a variable is stored.
struct DbgVariableLocation {
- /// Offset relative to base register.
- int64_t Offset;
-
/// Base register.
unsigned Register;
- /// If false, Register is the location. If true,
- /// Register+Offset point at the location.
- unsigned InMemory : 1;
-
- /// If false, the location holds the variable's value.
- /// If true, the location holds the variable's address.
- unsigned Deref : 1;
+ /// Chain of offsetted loads necessary to load the value if it lives in
+ /// memory. Every load except for the last is pointer-sized.
+ SmallVector<int64_t, 1> LoadChain;
/// Present if the location is part of a larger variable.
llvm::Optional<llvm::DIExpression::FragmentInfo> FragmentInfo;
OpenPOWER on IntegriCloud