diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp')
-rw-r--r-- | contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp | 170 |
1 files changed, 92 insertions, 78 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 7dbc6cb..61b2c7e6 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -46,7 +46,9 @@ void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) { } void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) { - assert(SizeInBits > 0 && "piece has size zero"); + if (!SizeInBits) + return; + const unsigned SizeOfByte = 8; if (OffsetInBits > 0 || SizeInBits % SizeOfByte) { EmitOp(dwarf::DW_OP_bit_piece); @@ -57,6 +59,7 @@ void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) { unsigned ByteSize = SizeInBits / SizeOfByte; EmitUnsigned(ByteSize); } + this->OffsetInBits += SizeInBits; } void DwarfExpression::AddShr(unsigned ShiftBy) { @@ -82,10 +85,8 @@ bool DwarfExpression::AddMachineRegIndirect(const TargetRegisterInfo &TRI, return true; } -bool DwarfExpression::AddMachineRegPiece(const TargetRegisterInfo &TRI, - unsigned MachineReg, - unsigned PieceSizeInBits, - unsigned PieceOffsetInBits) { +bool DwarfExpression::AddMachineReg(const TargetRegisterInfo &TRI, + unsigned MachineReg, unsigned MaxSize) { if (!TRI.isPhysicalRegister(MachineReg)) return false; @@ -94,13 +95,11 @@ bool DwarfExpression::AddMachineRegPiece(const TargetRegisterInfo &TRI, // If this is a valid register number, emit it. if (Reg >= 0) { AddReg(Reg); - if (PieceSizeInBits) - AddOpPiece(PieceSizeInBits, PieceOffsetInBits); return true; } // 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 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) { @@ -108,27 +107,15 @@ bool DwarfExpression::AddMachineRegPiece(const TargetRegisterInfo &TRI, unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); AddReg(Reg, "super-register"); - if (PieceOffsetInBits == RegOffset) { - AddOpPiece(Size, RegOffset); - } else { - // If this is part of a variable in a sub-register at a - // non-zero offset, we need to manually shift the value into - // place, since the DW_OP_piece describes the part of the - // variable, not the position of the subregister. - if (RegOffset) - AddShr(RegOffset); - AddOpPiece(Size, PieceOffsetInBits); - } + // 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. - // - // Keep track of the current position so we can emit the more - // efficient DW_OP_piece. - unsigned CurPos = PieceOffsetInBits; + 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 @@ -150,7 +137,12 @@ bool DwarfExpression::AddMachineRegPiece(const TargetRegisterInfo &TRI, // its range, emit a DWARF piece for it. if (Reg >= 0 && Intersection.any()) { AddReg(Reg, "sub-register"); - AddOpPiece(Size, Offset == CurPos ? 0 : Offset); + if (Offset >= MaxSize) + break; + // Emit a piece for the any gap in the coverage. + if (Offset > CurPos) + AddOpPiece(Offset - CurPos); + AddOpPiece(std::min<unsigned>(Size, MaxSize - Offset)); CurPos = Offset + Size; // Mark it as emitted. @@ -158,7 +150,7 @@ bool DwarfExpression::AddMachineRegPiece(const TargetRegisterInfo &TRI, } } - return CurPos > PieceOffsetInBits; + return CurPos; } void DwarfExpression::AddStackValue() { @@ -194,92 +186,114 @@ void DwarfExpression::AddUnsignedConstant(const APInt &Value) { } } -static unsigned getOffsetOrZero(unsigned OffsetInBits, - unsigned PieceOffsetInBits) { - if (OffsetInBits == PieceOffsetInBits) - return 0; - assert(OffsetInBits >= PieceOffsetInBits && "overlapping pieces"); - return OffsetInBits; -} - bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI, - const DIExpression *Expr, + DIExpressionCursor &ExprCursor, unsigned MachineReg, - unsigned PieceOffsetInBits) { - auto I = Expr->expr_op_begin(); - auto E = Expr->expr_op_end(); - if (I == E) - return AddMachineRegPiece(TRI, MachineReg); + unsigned FragmentOffsetInBits) { + if (!ExprCursor) + return AddMachineReg(TRI, MachineReg); // Pattern-match combinations for which more efficient representations exist // first. bool ValidReg = false; - switch (I->getOp()) { - case dwarf::DW_OP_bit_piece: { - unsigned OffsetInBits = I->getArg(0); - unsigned SizeInBits = I->getArg(1); - // Piece always comes at the end of the expression. - return AddMachineRegPiece(TRI, MachineReg, SizeInBits, - getOffsetOrZero(OffsetInBits, PieceOffsetInBits)); + 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 = I.getNext(); - if (N != E && N->getOp() == dwarf::DW_OP_deref) { - unsigned Offset = I->getArg(0); + auto N = ExprCursor.peekNext(); + if (N && N->getOp() == dwarf::DW_OP_deref) { + unsigned Offset = Op->getArg(0); ValidReg = AddMachineRegIndirect( - TRI, MachineReg, I->getOp() == dwarf::DW_OP_plus ? Offset : -Offset); - std::advance(I, 2); - break; + TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset); + ExprCursor.consume(2); } else - ValidReg = AddMachineRegPiece(TRI, MachineReg); - } - case dwarf::DW_OP_deref: { - // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg]. - ValidReg = AddMachineRegIndirect(TRI, MachineReg); - ++I; - break; + ValidReg = AddMachineReg(TRI, MachineReg); + break; } - default: - llvm_unreachable("unsupported operand"); + case dwarf::DW_OP_deref: + // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg]. + ValidReg = AddMachineRegIndirect(TRI, MachineReg); + ExprCursor.take(); + break; } - if (!ValidReg) - return false; - - // Emit remaining elements of the expression. - AddExpression(I, E, PieceOffsetInBits); - return true; + return ValidReg; } -void DwarfExpression::AddExpression(DIExpression::expr_op_iterator I, - DIExpression::expr_op_iterator E, - unsigned PieceOffsetInBits) { - for (; I != E; ++I) { - switch (I->getOp()) { - case dwarf::DW_OP_bit_piece: { - unsigned OffsetInBits = I->getArg(0); - unsigned SizeInBits = I->getArg(1); - AddOpPiece(SizeInBits, getOffsetOrZero(OffsetInBits, PieceOffsetInBits)); +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<unsigned>(SizeInBits, SubRegisterSizeInBits); + + AddOpPiece(SizeInBits, SubRegisterOffsetInBits); + setSubRegisterPiece(0, 0); break; } case dwarf::DW_OP_plus: EmitOp(dwarf::DW_OP_plus_uconst); - EmitUnsigned(I->getArg(0)); + EmitUnsigned(Op->getArg(0)); break; case dwarf::DW_OP_minus: // There is no OP_minus_uconst. EmitOp(dwarf::DW_OP_constu); - EmitUnsigned(I->getArg(0)); + 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; +} |