//===-- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework ----------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains support for writing dwarf debug info into asm files. // //===----------------------------------------------------------------------===// #include "DwarfExpression.h" #include "DwarfDebug.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Support/Dwarf.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; void DwarfExpression::AddReg(int DwarfReg, const char *Comment) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); if (DwarfReg < 32) { EmitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment); } else { EmitOp(dwarf::DW_OP_regx, Comment); EmitUnsigned(DwarfReg); } } void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); if (DwarfReg < 32) { EmitOp(dwarf::DW_OP_breg0 + DwarfReg); } else { EmitOp(dwarf::DW_OP_bregx); EmitUnsigned(DwarfReg); } EmitSigned(Offset); if (Deref) EmitOp(dwarf::DW_OP_deref); } void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) { if (!SizeInBits) return; const unsigned SizeOfByte = 8; if (OffsetInBits > 0 || SizeInBits % SizeOfByte) { EmitOp(dwarf::DW_OP_bit_piece); EmitUnsigned(SizeInBits); EmitUnsigned(OffsetInBits); } else { EmitOp(dwarf::DW_OP_piece); unsigned ByteSize = SizeInBits / SizeOfByte; EmitUnsigned(ByteSize); } this->OffsetInBits += SizeInBits; } void DwarfExpression::AddShr(unsigned ShiftBy) { EmitOp(dwarf::DW_OP_constu); EmitUnsigned(ShiftBy); EmitOp(dwarf::DW_OP_shr); } bool DwarfExpression::AddMachineRegIndirect(const TargetRegisterInfo &TRI, unsigned MachineReg, int Offset) { if (isFrameRegister(TRI, MachineReg)) { // If variable offset is based in frame register then use fbreg. EmitOp(dwarf::DW_OP_fbreg); EmitSigned(Offset); return true; } int DwarfReg = TRI.getDwarfRegNum(MachineReg, false); if (DwarfReg < 0) return false; AddRegIndirect(DwarfReg, Offset); return true; } bool DwarfExpression::AddMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg, unsigned MaxSize) { if (!TRI.isPhysicalRegister(MachineReg)) return false; int Reg = TRI.getDwarfRegNum(MachineReg, false); // If this is a valid register number, emit it. if (Reg >= 0) { AddReg(Reg); return true; } // Walk up the super-register chain until we find a valid number. // For example, EAX on x86_64 is a 32-bit fragment of RAX with offset 0. for (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) { Reg = TRI.getDwarfRegNum(*SR, false); if (Reg >= 0) { unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg); unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); AddReg(Reg, "super-register"); // Use a DW_OP_bit_piece to describe the sub-register. setSubRegisterPiece(Size, RegOffset); return true; } } // Otherwise, attempt to find a covering set of sub-register numbers. // For example, Q0 on ARM is a composition of D0+D1. unsigned CurPos = 0; // The size of the register in bits, assuming 8 bits per byte. unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->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(MachineReg, &TRI); SR.isValid(); ++SR) { unsigned Idx = TRI.getSubRegIndex(MachineReg, *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()) { AddReg(Reg, "sub-register"); if (Offset >= MaxSize) break; // Emit a piece for the any gap in the coverage. if (Offset > CurPos) AddOpPiece(Offset - CurPos); AddOpPiece(std::min(Size, MaxSize - Offset)); CurPos = Offset + Size; // Mark it as emitted. Coverage.set(Offset, Offset + Size); } } return CurPos; } void DwarfExpression::AddStackValue() { if (DwarfVersion >= 4) EmitOp(dwarf::DW_OP_stack_value); } void DwarfExpression::AddSignedConstant(int64_t Value) { EmitOp(dwarf::DW_OP_consts); EmitSigned(Value); AddStackValue(); } void DwarfExpression::AddUnsignedConstant(uint64_t Value) { EmitOp(dwarf::DW_OP_constu); EmitUnsigned(Value); AddStackValue(); } void DwarfExpression::AddUnsignedConstant(const APInt &Value) { unsigned Size = Value.getBitWidth(); const uint64_t *Data = Value.getRawData(); // Chop it up into 64-bit pieces, because that's the maximum that // AddUnsignedConstant takes. unsigned Offset = 0; while (Offset < Size) { AddUnsignedConstant(*Data++); if (Offset == 0 && Size <= 64) break; AddOpPiece(std::min(Size-Offset, 64u), Offset); Offset += 64; } } bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI, DIExpressionCursor &ExprCursor, unsigned MachineReg, unsigned FragmentOffsetInBits) { if (!ExprCursor) return AddMachineReg(TRI, MachineReg); // Pattern-match combinations for which more efficient representations exist // first. bool ValidReg = false; auto Op = ExprCursor.peek(); switch (Op->getOp()) { default: { auto Fragment = ExprCursor.getFragmentInfo(); ValidReg = AddMachineReg(TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U); break; } case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: { // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset]. // [DW_OP_reg,Offset,DW_OP_minus,DW_OP_deref] --> [DW_OP_breg,-Offset]. auto N = ExprCursor.peekNext(); if (N && N->getOp() == dwarf::DW_OP_deref) { unsigned Offset = Op->getArg(0); ValidReg = AddMachineRegIndirect( TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset); ExprCursor.consume(2); } else ValidReg = AddMachineReg(TRI, MachineReg); break; } case dwarf::DW_OP_deref: // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg]. ValidReg = AddMachineRegIndirect(TRI, MachineReg); ExprCursor.take(); break; } return ValidReg; } void DwarfExpression::AddExpression(DIExpressionCursor &&ExprCursor, unsigned FragmentOffsetInBits) { while (ExprCursor) { auto Op = ExprCursor.take(); switch (Op->getOp()) { case dwarf::DW_OP_LLVM_fragment: { unsigned SizeInBits = Op->getArg(1); unsigned FragmentOffset = Op->getArg(0); // The fragment offset must have already been adjusted by emitting an // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base // location. assert(OffsetInBits >= FragmentOffset && "fragment offset not added?"); // If \a AddMachineReg already emitted DW_OP_piece operations to represent // a super-register by splicing together sub-registers, subtract the size // of the pieces that was already emitted. SizeInBits -= OffsetInBits - FragmentOffset; // If \a AddMachineReg requested a DW_OP_bit_piece to stencil out a // sub-register that is smaller than the current fragment's size, use it. if (SubRegisterSizeInBits) SizeInBits = std::min(SizeInBits, SubRegisterSizeInBits); AddOpPiece(SizeInBits, SubRegisterOffsetInBits); setSubRegisterPiece(0, 0); break; } case dwarf::DW_OP_plus: EmitOp(dwarf::DW_OP_plus_uconst); EmitUnsigned(Op->getArg(0)); break; case dwarf::DW_OP_minus: // There is no OP_minus_uconst. EmitOp(dwarf::DW_OP_constu); EmitUnsigned(Op->getArg(0)); EmitOp(dwarf::DW_OP_minus); break; case dwarf::DW_OP_deref: EmitOp(dwarf::DW_OP_deref); break; case dwarf::DW_OP_constu: EmitOp(dwarf::DW_OP_constu); EmitUnsigned(Op->getArg(0)); break; case dwarf::DW_OP_stack_value: AddStackValue(); break; default: llvm_unreachable("unhandled opcode found in expression"); } } } void DwarfExpression::finalize() { if (SubRegisterSizeInBits) AddOpPiece(SubRegisterSizeInBits, SubRegisterOffsetInBits); } void DwarfExpression::addFragmentOffset(const DIExpression *Expr) { if (!Expr || !Expr->isFragment()) return; uint64_t FragmentOffset = Expr->getFragmentInfo()->OffsetInBits; assert(FragmentOffset >= OffsetInBits && "overlapping or duplicate fragments"); if (FragmentOffset > OffsetInBits) AddOpPiece(FragmentOffset - OffsetInBits); OffsetInBits = FragmentOffset; }