diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index ce4aae3d319..329737c0cab 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -42,6 +42,9 @@ public: void EmitOp(uint8_t Op, const char* Comment) override; void EmitSigned(int Value) override; void EmitUnsigned(unsigned Value) override; + unsigned getFrameRegister() override { + llvm_unreachable("not available"); + }; }; void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char* Comment) { diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 01c9e2497dd..2b6911e32e8 100644 --- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -65,6 +65,22 @@ void DwarfExpression::AddShr(unsigned ShiftBy) { EmitOp(dwarf::DW_OP_shr); } +bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) { + const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); + int DwarfReg = TRI->getDwarfRegNum(MachineReg, false); + if (DwarfReg < 0) + return false; + + if (MachineReg == getFrameRegister()) { + // If variable offset is based in frame register then use fbreg. + EmitOp(dwarf::DW_OP_fbreg); + EmitSigned(Offset); + } else { + AddRegIndirect(DwarfReg, Offset); + } + return true; +} + void DwarfExpression::AddMachineRegPiece(unsigned MachineReg, unsigned PieceSizeInBits, unsigned PieceOffsetInBits) { diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.h b/lib/CodeGen/AsmPrinter/DwarfExpression.h index 193f4307d88..ffee3bc43a2 100644 --- a/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -24,6 +24,7 @@ class TargetMachine; /// independently of whether they are emitted into a DIE or into a .debug_loc /// entry. class DwarfExpression { +protected: TargetMachine &TM; public: DwarfExpression(TargetMachine &TM) : TM(TM) {} @@ -31,6 +32,9 @@ public: virtual void EmitOp(uint8_t Op, const char* Comment = nullptr) = 0; virtual void EmitSigned(int Value) = 0; virtual void EmitUnsigned(unsigned Value) = 0; + + virtual unsigned getFrameRegister() = 0; + /// Emit a dwarf register operation. void AddReg(int DwarfReg, const char* Comment = nullptr); /// Emit an (double-)indirect dwarf register operation. @@ -43,6 +47,10 @@ public: /// Emit a shift-right dwarf expression. void AddShr(unsigned ShiftBy); + /// Emit an indirect dwarf register operation for the given machine register. + /// Returns false if no DWARF register exists for MachineReg. + bool AddMachineRegIndirect(unsigned MachineReg, int Offset); + /// \brief Emit a partial DWARF register operation. /// \param MLoc the register /// \param PieceSize size and diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index e3205466a2e..16cdbbc7e7e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -16,6 +16,7 @@ #include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" #include "DwarfDebug.h" +#include "DwarfExpression.h" #include "llvm/ADT/APFloat.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DIBuilder.h" @@ -43,6 +44,35 @@ GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, cl::desc("Generate DWARF4 type units."), cl::init(false)); +/// DwarfExpression implementation for DwarfUnit. +class DIEDwarfExpression : public DwarfExpression { + DwarfUnit &DU; + DIELoc &DIE; +public: + DIEDwarfExpression(TargetMachine &TM, DwarfUnit &DU, DIELoc &DIE) + : DwarfExpression(TM), DU(DU), DIE(DIE) {} + + void EmitOp(uint8_t Op, const char* Comment = nullptr) override; + void EmitSigned(int Value) override; + void EmitUnsigned(unsigned Value) override; + unsigned getFrameRegister() override; +}; + +void DIEDwarfExpression::EmitOp(uint8_t Op, const char* Comment) { + DU.addUInt(DIE, dwarf::DW_FORM_data1, Op); +} +void DIEDwarfExpression::EmitSigned(int Value) { + DU.addSInt(DIE, dwarf::DW_FORM_sdata, Value); +} +void DIEDwarfExpression::EmitUnsigned(unsigned Value) { + DU.addUInt(DIE, dwarf::DW_FORM_udata, Value); +} +unsigned DIEDwarfExpression::getFrameRegister() { + const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); + return TRI->getFrameRegister(*DU.getAsmPrinter()->MF); +} + + /// Unit - Unit constructor. DwarfUnit::DwarfUnit(unsigned UID, dwarf::Tag UnitTag, DICompileUnit Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU) @@ -463,22 +493,8 @@ bool DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg, /// addRegisterOffset - Add register offset. bool DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset) { - const TargetRegisterInfo *TRI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); - int DWReg = TRI->getDwarfRegNum(Reg, false); - if (DWReg < 0) - return false; - - if (Reg == TRI->getFrameRegister(*Asm->MF)) - // If variable offset is based in frame register then use fbreg. - addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); - else if (DWReg < 32) - addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + DWReg); - else { - addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(TheDie, dwarf::DW_FORM_udata, DWReg); - } - addSInt(TheDie, dwarf::DW_FORM_sdata, Offset); - return true; + DIEDwarfExpression Expr(Asm->TM, *this, TheDie); + return Expr.AddMachineRegIndirect(Reg, Offset); } /* Byref variables, in Blocks, are declared by the programmer as "SomeType diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index ed54e64ee49..9cfa5d06c0f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -138,6 +138,7 @@ public: } // Accessors. + AsmPrinter* getAsmPrinter() const { return Asm; } unsigned getUniqueID() const { return UniqueID; } uint16_t getLanguage() const { return CUNode.getLanguage(); } DICompileUnit getCUNode() const { return CUNode; }