diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h')
-rw-r--r-- | contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h | 165 |
1 files changed, 124 insertions, 41 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 5fff28d..fd90fa0 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -25,17 +25,86 @@ class TargetRegisterInfo; class DwarfUnit; class DIELoc; +/// Holds a DIExpression and keeps track of how many operands have been consumed +/// so far. +class DIExpressionCursor { + DIExpression::expr_op_iterator Start, End; +public: + DIExpressionCursor(const DIExpression *Expr) { + if (!Expr) { + assert(Start == End); + return; + } + Start = Expr->expr_op_begin(); + End = Expr->expr_op_end(); + } + + DIExpressionCursor(ArrayRef<uint64_t> Expr) + : Start(Expr.begin()), End(Expr.end()) {} + + /// Consume one operation. + Optional<DIExpression::ExprOperand> take() { + if (Start == End) + return None; + return *(Start++); + } + + /// Consume N operations. + void consume(unsigned N) { std::advance(Start, N); } + + /// Return the current operation. + Optional<DIExpression::ExprOperand> peek() const { + if (Start == End) + return None; + return *(Start); + } + + /// Return the next operation. + Optional<DIExpression::ExprOperand> peekNext() const { + if (Start == End) + return None; + + auto Next = Start.getNext(); + if (Next == End) + return None; + + return *Next; + } + /// Determine whether there are any operations left in this expression. + operator bool() const { return Start != End; } + + /// Retrieve the fragment information, if any. + Optional<DIExpression::FragmentInfo> getFragmentInfo() const { + return DIExpression::getFragmentInfo(Start, End); + } +}; + /// Base class containing the logic for constructing DWARF expressions /// independently of whether they are emitted into a DIE or into a .debug_loc /// entry. class DwarfExpression { protected: - // Various convenience accessors that extract things out of AsmPrinter. unsigned DwarfVersion; + /// Current Fragment Offset in Bits. + uint64_t OffsetInBits = 0; + + /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. + unsigned SubRegisterSizeInBits = 0; + unsigned SubRegisterOffsetInBits = 0; + + /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed + /// to represent a subregister. + void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { + SubRegisterSizeInBits = SizeInBits; + SubRegisterOffsetInBits = OffsetInBits; + } public: DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {} - virtual ~DwarfExpression() {} + virtual ~DwarfExpression() {}; + + /// This needs to be called last to commit any pending changes. + void finalize(); /// Output a dwarf operand and an optional assembler comment. virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0; @@ -52,24 +121,25 @@ public: /// Emit an (double-)indirect dwarf register operation. void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false); - /// Emit a dwarf register operation for describing - /// - a small value occupying only part of a register or - /// - a register representing only part of a value. + /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. + /// \param OffsetInBits This is an optional offset into the location that + /// is at the top of the DWARF stack. void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); + /// Emit a shift-right dwarf expression. void AddShr(unsigned ShiftBy); + /// Emit a DW_OP_stack_value, if supported. /// - /// The proper way to describe a constant value is - /// DW_OP_constu <const>, DW_OP_stack_value. - /// Unfortunately, DW_OP_stack_value was not available until DWARF-4, - /// so we will continue to generate DW_OP_constu <const> for DWARF-2 - /// and DWARF-3. Technically, this is incorrect since DW_OP_const <const> - /// actually describes a value at a constant addess, not a constant value. - /// However, in the past there was no better way to describe a constant - /// value, so the producers and consumers started to rely on heuristics - /// to disambiguate the value vs. location status of the expression. - /// See PR21176 for more details. + /// The proper way to describe a constant value is DW_OP_constu <const>, + /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available + /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for + /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const + /// <const> actually describes a value at a constant addess, not a constant + /// value. However, in the past there was no better way to describe a + /// constant value, so the producers and consumers started to rely on + /// heuristics to disambiguate the value vs. location status of the + /// expression. See PR21176 for more details. void AddStackValue(); /// Emit an indirect dwarf register operation for the given machine register. @@ -77,23 +147,23 @@ public: bool AddMachineRegIndirect(const TargetRegisterInfo &TRI, unsigned MachineReg, int Offset = 0); - /// \brief Emit a partial DWARF register operation. - /// \param MachineReg the register - /// \param PieceSizeInBits size and - /// \param PieceOffsetInBits offset of the piece in bits, if this is one - /// piece of an aggregate value. + /// Emit a partial DWARF register operation. + /// + /// \param MachineReg The register number. + /// \param MaxSize If the register must be composed from + /// sub-registers this is an upper bound + /// for how many bits the emitted DW_OP_piece + /// may cover. /// - /// If size and offset is zero an operation for the entire - /// register is emitted: Some targets do not provide a DWARF - /// register number for every register. If this is the case, this - /// function will attempt to emit a DWARF register by emitting a - /// piece of a super-register or by piecing together multiple - /// subregisters that alias the register. + /// If size and offset is zero an operation for the entire register is + /// emitted: Some targets do not provide a DWARF register number for every + /// register. If this is the case, this function will attempt to emit a DWARF + /// register by emitting a fragment of a super-register or by piecing together + /// multiple subregisters that alias the register. /// /// \return false if no DWARF register exists for MachineReg. - bool AddMachineRegPiece(const TargetRegisterInfo &TRI, unsigned MachineReg, - unsigned PieceSizeInBits = 0, - unsigned PieceOffsetInBits = 0); + bool AddMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg, + unsigned MaxSize = ~1U); /// Emit a signed constant. void AddSignedConstant(int64_t Value); @@ -102,20 +172,29 @@ public: /// Emit an unsigned constant. void AddUnsignedConstant(const APInt &Value); - /// \brief Emit an entire expression on top of a machine register location. + /// Emit a machine register location. As an optimization this may also consume + /// the prefix of a DwarfExpression if a more efficient representation for + /// combining the register location and the first operation exists. /// - /// \param PieceOffsetInBits If this is one piece out of a fragmented - /// location, this is the offset of the piece inside the entire variable. - /// \return false if no DWARF register exists for MachineReg. + /// \param FragmentOffsetInBits If this is one fragment out of a fragmented + /// location, this is the offset of the + /// fragment inside the entire variable. + /// \return false if no DWARF register exists + /// for MachineReg. bool AddMachineRegExpression(const TargetRegisterInfo &TRI, - const DIExpression *Expr, unsigned MachineReg, - unsigned PieceOffsetInBits = 0); - /// Emit a the operations remaining the DIExpressionIterator I. - /// \param PieceOffsetInBits If this is one piece out of a fragmented - /// location, this is the offset of the piece inside the entire variable. - void AddExpression(DIExpression::expr_op_iterator I, - DIExpression::expr_op_iterator E, - unsigned PieceOffsetInBits = 0); + DIExpressionCursor &Expr, unsigned MachineReg, + unsigned FragmentOffsetInBits = 0); + /// Emit all remaining operations in the DIExpressionCursor. + /// + /// \param FragmentOffsetInBits If this is one fragment out of multiple + /// locations, this is the offset of the + /// fragment inside the entire variable. + void AddExpression(DIExpressionCursor &&Expr, + unsigned FragmentOffsetInBits = 0); + + /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to + /// the fragment described by \c Expr. + void addFragmentOffset(const DIExpression *Expr); }; /// DwarfExpression implementation for .debug_loc entries. @@ -146,6 +225,10 @@ public: void EmitUnsigned(uint64_t Value) override; bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) override; + DIELoc *finalize() { + DwarfExpression::finalize(); + return &DIE; + } }; } |