/// EmitDwarfRegOp - Emit dwarf register operation. void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, const MachineLocation &MLoc, bool Indirect) const { const TargetRegisterInfo *TRI = TM.getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); if (Reg < 0) { // We assume that pointers are always in an addressable register. if (Indirect || MLoc.isIndirect()) { // FIXME: We have no reasonable way of handling errors in here. The // caller might be in the middle of a dwarf expression. We should // probably assert that Reg >= 0 once debug info generation is more // mature. 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(Streamer, *this, MLoc); } if (MLoc.isIndirect()) emitDwarfRegOpIndirect(Streamer, Reg, MLoc.getOffset(), Indirect); else if (Indirect) emitDwarfRegOpIndirect(Streamer, Reg, 0, false); else emitDwarfRegOp(Streamer, Reg); }
/// EmitDwarfRegOp - Emit dwarf register operation. void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, const MachineLocation &MLoc) const { DebugLocDwarfExpression Expr(*MF->getSubtarget().getRegisterInfo(), getDwarfDebug()->getDwarfVersion(), Streamer); const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo(); int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false); if (Reg < 0) { // We assume that pointers are always in an addressable register. if (MLoc.isIndirect()) // FIXME: We have no reasonable way of handling errors in here. The // caller might be in the middle of a dwarf expression. We should // probably assert that Reg >= 0 once debug info generation is more // mature. return Expr.EmitOp(dwarf::DW_OP_nop, "nop (could not find a dwarf register number)"); // Attempt to find a valid super- or sub-register. if (!Expr.AddMachineRegPiece(MLoc.getReg())) Expr.EmitOp(dwarf::DW_OP_nop, "nop (could not find a dwarf register number)"); return; } if (MLoc.isIndirect()) Expr.AddRegIndirect(Reg, MLoc.getOffset()); else Expr.AddReg(Reg); }
/// Add an address attribute to a die based on the location provided. void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location) { DIELoc *Loc = new (DIEValueAllocator) DIELoc; DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); if (Location.isIndirect()) DwarfExpr.setMemoryLocationKind(); DIExpressionCursor Cursor({}); const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) return; DwarfExpr.addExpression(std::move(Cursor)); // Now attach the location information to the DIE. addBlock(Die, Attribute, DwarfExpr.finalize()); }
/// Some targets do not provide a DWARF register number for every /// 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(ByteStreamer &Streamer, const AsmPrinter &AP, const MachineLocation &MLoc) { assert(!MLoc.isIndirect()); const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); // Walk up the super-register chain until we find a valid number. // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0. for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) { Reg = TRI->getDwarfRegNum(*SR, false); if (Reg >= 0) { unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg()); unsigned Size = TRI->getSubRegIdxSize(Idx); unsigned Offset = TRI->getSubRegIdxOffset(Idx); AP.OutStreamer.AddComment("super-register"); emitDwarfRegOp(Streamer, Reg); emitDwarfOpPiece(Streamer, Size, Offset); return; } } // Otherwise, attempt to find a covering set of sub-register numbers. // For example, Q0 on ARM is a composition of D0+D1. // // Keep track of the current position so we can emit the more // efficient DW_OP_piece. unsigned CurPos = 0; // The size of the register in bits, assuming 8 bits per byte. unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize() * 8; // Keep track of the bits in the register we already emitted, so we // can avoid emitting redundant aliasing subregs. SmallBitVector Coverage(RegSize, false); for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) { unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR); unsigned Size = TRI->getSubRegIdxSize(Idx); unsigned Offset = TRI->getSubRegIdxOffset(Idx); Reg = TRI->getDwarfRegNum(*SR, false); // Intersection between the bits we already emitted and the bits // covered by this subregister. SmallBitVector Intersection(RegSize, false); Intersection.set(Offset, Offset + Size); Intersection ^= Coverage; // If this sub-register has a DWARF number and we haven't covered // its range, emit a DWARF piece for it. if (Reg >= 0 && Intersection.any()) { AP.OutStreamer.AddComment("sub-register"); emitDwarfRegOp(Streamer, Reg); emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset); CurPos = Offset + Size; // Mark it as emitted. Coverage.set(Offset, Offset + Size); } } if (CurPos == 0) { // FIXME: We have no reasonable way of handling errors in here. Streamer.EmitInt8(dwarf::DW_OP_nop, "nop (could not find a dwarf register number)"); } }