diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 939324976d7..56dae2c514e 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -24,6 +24,7 @@ namespace llvm { class AsmPrinterHandler; class BlockAddress; + class ByteStreamer; class GCStrategy; class Constant; class ConstantArray; @@ -429,7 +430,7 @@ namespace llvm { virtual unsigned getISAEncoding() { return 0; } /// EmitDwarfRegOp - Emit dwarf register operation. - virtual void EmitDwarfRegOp(const MachineLocation &MLoc, + virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, bool Indirect) const; //===------------------------------------------------------------------===// diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 3741ef0398d..338ed4cdae4 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "asm-printer" +#include "ByteStreamer.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/Twine.h" @@ -185,58 +186,47 @@ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, } /// Emit a dwarf register operation. -static void emitDwarfRegOp(const AsmPrinter &AP, int Reg) { +static void emitDwarfRegOp(ByteStreamer &Streamer, int Reg) { assert(Reg >= 0); if (Reg < 32) { - AP.OutStreamer.AddComment( - dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); - AP.EmitInt8(dwarf::DW_OP_reg0 + Reg); + Streamer.EmitInt8(dwarf::DW_OP_reg0 + Reg, + dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); } else { - AP.OutStreamer.AddComment("DW_OP_regx"); - AP.EmitInt8(dwarf::DW_OP_regx); - AP.OutStreamer.AddComment(Twine(Reg)); - AP.EmitULEB128(Reg); + Streamer.EmitInt8(dwarf::DW_OP_regx, "DW_OP_regx"); + Streamer.EmitULEB128(Reg, Twine(Reg)); } } /// Emit an (double-)indirect dwarf register operation. -static void emitDwarfRegOpIndirect(const AsmPrinter &AP, int Reg, int Offset, +static void emitDwarfRegOpIndirect(ByteStreamer &Streamer, int Reg, int Offset, bool Deref) { assert(Reg >= 0); if (Reg < 32) { - AP.OutStreamer.AddComment( - dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg)); - AP.EmitInt8(dwarf::DW_OP_breg0 + Reg); + Streamer.EmitInt8(dwarf::DW_OP_breg0 + Reg, + dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg)); } else { - AP.OutStreamer.AddComment("DW_OP_bregx"); - AP.EmitInt8(dwarf::DW_OP_bregx); - AP.OutStreamer.AddComment(Twine(Reg)); - AP.EmitULEB128(Reg); + Streamer.EmitInt8(dwarf::DW_OP_bregx, "DW_OP_bregx"); + Streamer.EmitULEB128(Reg, Twine(Reg)); } - AP.EmitSLEB128(Offset); + Streamer.EmitSLEB128(Offset); if (Deref) - AP.EmitInt8(dwarf::DW_OP_deref); + Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); } /// Emit a dwarf register operation for describing /// - a small value occupying only part of a register or /// - a small register representing only part of a value. -static void emitDwarfOpPiece(const AsmPrinter &AP, unsigned Size, +static void emitDwarfOpPiece(ByteStreamer &Streamer, unsigned Size, unsigned Offset) { assert(Size > 0); if (Offset > 0) { - AP.OutStreamer.AddComment("DW_OP_bit_piece"); - AP.EmitInt8(dwarf::DW_OP_bit_piece); - AP.OutStreamer.AddComment(Twine(Size)); - AP.EmitULEB128(Size); - AP.OutStreamer.AddComment(Twine(Offset)); - AP.EmitULEB128(Offset); + Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece"); + Streamer.EmitULEB128(Size, Twine(Size)); + Streamer.EmitULEB128(Offset, Twine(Offset)); } else { - AP.OutStreamer.AddComment("DW_OP_piece"); - AP.EmitInt8(dwarf::DW_OP_piece); + Streamer.EmitInt8(dwarf::DW_OP_piece, "DW_OP_piece"); unsigned ByteSize = Size / 8; // Assuming 8 bits per byte. - AP.OutStreamer.AddComment(Twine(ByteSize)); - AP.EmitULEB128(ByteSize); + Streamer.EmitULEB128(ByteSize, Twine(ByteSize)); } } @@ -244,7 +234,7 @@ static void emitDwarfOpPiece(const AsmPrinter &AP, unsigned Size, /// register. This function attempts to emit a dwarf register by /// emitting a piece of a super-register or by piecing together /// multiple subregisters that alias the register. -static void EmitDwarfRegOpPiece(const AsmPrinter &AP, +static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP, const MachineLocation &MLoc) { assert(!MLoc.isIndirect()); const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo(); @@ -259,8 +249,8 @@ static void EmitDwarfRegOpPiece(const AsmPrinter &AP, unsigned Size = TRI->getSubRegIdxSize(Idx); unsigned Offset = TRI->getSubRegIdxOffset(Idx); AP.OutStreamer.AddComment("super-register"); - emitDwarfRegOp(AP, Reg); - emitDwarfOpPiece(AP, Size, Offset); + emitDwarfRegOp(Streamer, Reg); + emitDwarfOpPiece(Streamer, Size, Offset); return; } } @@ -292,8 +282,8 @@ static void EmitDwarfRegOpPiece(const AsmPrinter &AP, // its range, emit a DWARF piece for it. if (Reg >= 0 && Intersection.any()) { AP.OutStreamer.AddComment("sub-register"); - emitDwarfRegOp(AP, Reg); - emitDwarfOpPiece(AP, Size, Offset == CurPos ? 0 : Offset); + emitDwarfRegOp(Streamer, Reg); + emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset); CurPos = Offset + Size; // Mark it as emitted. @@ -303,13 +293,14 @@ static void EmitDwarfRegOpPiece(const AsmPrinter &AP, if (CurPos == 0) { // FIXME: We have no reasonable way of handling errors in here. - AP.OutStreamer.AddComment("nop (could not find a dwarf register number)"); - AP.EmitInt8(dwarf::DW_OP_nop); + Streamer.EmitInt8(dwarf::DW_OP_nop, + "nop (could not find a dwarf register number)"); } } /// EmitDwarfRegOp - Emit dwarf register operation. -void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc, +void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, + const MachineLocation &MLoc, bool Indirect) const { const TargetRegisterInfo *TRI = TM.getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); @@ -320,23 +311,22 @@ void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc, // caller might be in the middle of a dwarf expression. We should // probably assert that Reg >= 0 once debug info generation is more // mature. - OutStreamer.AddComment( - "nop (invalid dwarf register number for indirect loc)"); - EmitInt8(dwarf::DW_OP_nop); + Streamer.EmitInt8(dwarf::DW_OP_nop, + "nop (invalid dwarf register number for indirect loc)"); return; } // Attempt to find a valid super- or sub-register. if (!Indirect && !MLoc.isIndirect()) - return EmitDwarfRegOpPiece(*this, MLoc); + return EmitDwarfRegOpPiece(Streamer, *this, MLoc); } if (MLoc.isIndirect()) - emitDwarfRegOpIndirect(*this, Reg, MLoc.getOffset(), Indirect); + emitDwarfRegOpIndirect(Streamer, Reg, MLoc.getOffset(), Indirect); else if (Indirect) - emitDwarfRegOpIndirect(*this, Reg, 0, false); + emitDwarfRegOpIndirect(Streamer, Reg, 0, false); else - emitDwarfRegOp(*this, Reg); + emitDwarfRegOp(Streamer, Reg); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 81934e17297..dab3c194c1e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dwarfdebug" +#include "ByteStreamer.h" #include "DwarfDebug.h" #include "DIE.h" #include "DIEHash.h" @@ -2395,6 +2396,65 @@ void DwarfDebug::emitDebugStr() { Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } +void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, + const DotDebugLocEntry &Entry) { + DIVariable DV(Entry.getVariable()); + if (Entry.isInt()) { + DIBasicType BTy(DV.getType()); + if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || + BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { + Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts"); + Streamer.EmitSLEB128(Entry.getInt()); + } else { + Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu"); + Streamer.EmitULEB128(Entry.getInt()); + } + } else if (Entry.isLocation()) { + MachineLocation Loc = Entry.getLoc(); + if (!DV.hasComplexAddress()) + // Regular entry. + Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); + else { + // Complex address entry. + unsigned N = DV.getNumAddrElements(); + unsigned i = 0; + if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { + if (Loc.getOffset()) { + i = 2; + Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); + Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); + Streamer.EmitSLEB128(DV.getAddrElement(1)); + } else { + // If first address element is OpPlus then emit + // DW_OP_breg + Offset instead of DW_OP_reg + Offset. + MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); + Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect()); + i = 2; + } + } else { + Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); + } + + // Emit remaining complex address elements. + for (; i < N; ++i) { + uint64_t Element = DV.getAddrElement(i); + if (Element == DIBuilder::OpPlus) { + Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); + Streamer.EmitULEB128(DV.getAddrElement(++i)); + } else if (Element == DIBuilder::OpDeref) { + if (!Loc.isReg()) + Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + } else + llvm_unreachable("unknown Opcode found in complex address"); + } + } + } + // else ... ignore constant fp. There is not any good way to + // to represent them here in dwarf. + // FIXME: ^ +} + // Emit locations into the debug loc section. void DwarfDebug::emitDebugLoc() { if (DotDebugLocEntries.empty()) @@ -2422,76 +2482,24 @@ void DwarfDebug::emitDebugLoc() { const DotDebugLocEntry &Entry = *I; if (Entry.isMerged()) continue; + if (Entry.isEmpty()) { Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index)); } else { + // Set up the range. Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size); Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size); - DIVariable DV(Entry.getVariable()); Asm->OutStreamer.AddComment("Loc expr size"); MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); Asm->EmitLabelDifference(end, begin, 2); Asm->OutStreamer.EmitLabel(begin); - if (Entry.isInt()) { - DIBasicType BTy(DV.getType()); - if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || - BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { - Asm->OutStreamer.AddComment("DW_OP_consts"); - Asm->EmitInt8(dwarf::DW_OP_consts); - Asm->EmitSLEB128(Entry.getInt()); - } else { - Asm->OutStreamer.AddComment("DW_OP_constu"); - Asm->EmitInt8(dwarf::DW_OP_constu); - Asm->EmitULEB128(Entry.getInt()); - } - } else if (Entry.isLocation()) { - MachineLocation Loc = Entry.getLoc(); - if (!DV.hasComplexAddress()) - // Regular entry. - Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); - else { - // Complex address entry. - unsigned N = DV.getNumAddrElements(); - unsigned i = 0; - if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { - if (Loc.getOffset()) { - i = 2; - Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); - Asm->OutStreamer.AddComment("DW_OP_deref"); - Asm->EmitInt8(dwarf::DW_OP_deref); - Asm->OutStreamer.AddComment("DW_OP_plus_uconst"); - Asm->EmitInt8(dwarf::DW_OP_plus_uconst); - Asm->EmitSLEB128(DV.getAddrElement(1)); - } else { - // If first address element is OpPlus then emit - // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); - Asm->EmitDwarfRegOp(TLoc, DV.isIndirect()); - i = 2; - } - } else { - Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); - } - - // Emit remaining complex address elements. - for (; i < N; ++i) { - uint64_t Element = DV.getAddrElement(i); - if (Element == DIBuilder::OpPlus) { - Asm->EmitInt8(dwarf::DW_OP_plus_uconst); - Asm->EmitULEB128(DV.getAddrElement(++i)); - } else if (Element == DIBuilder::OpDeref) { - if (!Loc.isReg()) - Asm->EmitInt8(dwarf::DW_OP_deref); - } else - llvm_unreachable("unknown Opcode found in complex address"); - } - } - } - // else ... ignore constant fp. There is not any good way to - // to represent them here in dwarf. + // Emit the entry. + APByteStreamer Streamer(*Asm); + emitDebugLocEntry(Streamer, Entry); + // Close the range. Asm->OutStreamer.EmitLabel(end); } } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 1373e96d009..0dadb73562e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -31,6 +31,7 @@ namespace llvm { +class ByteStreamer; class DwarfUnit; class DwarfCompileUnit; class ConstantInt; @@ -587,6 +588,9 @@ class DwarfDebug : public AsmPrinterHandler { /// \brief Emit visible names into a debug str section. void emitDebugStr(); + /// \brief Emit an entry for the debug loc section. + void emitDebugLocEntry(ByteStreamer &Streamer, const DotDebugLocEntry &Entry); + /// \brief Emit visible names into a debug loc section. void emitDebugLoc();