diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 61 |
1 files changed, 34 insertions, 27 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); |