1 //===-- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ---*- C++ -*--===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains support for writing dwarf compile unit. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 15 #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 16 17 #include "llvm/IR/DebugInfo.h" 18 #include "llvm/Support/DataTypes.h" 19 20 namespace llvm { 21 22 class AsmPrinter; 23 class ByteStreamer; 24 class TargetRegisterInfo; 25 class DwarfUnit; 26 class DIELoc; 27 28 /// Holds a DIExpression and keeps track of how many operands have been consumed 29 /// so far. 30 class DIExpressionCursor { 31 DIExpression::expr_op_iterator Start, End; 32 public: 33 DIExpressionCursor(const DIExpression *Expr) { 34 if (!Expr) { 35 assert(Start == End); 36 return; 37 } 38 Start = Expr->expr_op_begin(); 39 End = Expr->expr_op_end(); 40 } 41 42 /// Consume one operation. 43 Optional<DIExpression::ExprOperand> take() { 44 if (Start == End) 45 return None; 46 return *(Start++); 47 } 48 49 /// Consume N operations. 50 void consume(unsigned N) { std::advance(Start, N); } 51 52 /// Return the current operation. 53 Optional<DIExpression::ExprOperand> peek() const { 54 if (Start == End) 55 return None; 56 return *(Start); 57 } 58 59 /// Return the next operation. 60 Optional<DIExpression::ExprOperand> peekNext() const { 61 if (Start == End) 62 return None; 63 64 auto Next = Start.getNext(); 65 if (Next == End) 66 return None; 67 68 return *Next; 69 } 70 /// Determine whether there are any operations left in this expression. 71 operator bool() const { return Start != End; } 72 }; 73 74 /// Base class containing the logic for constructing DWARF expressions 75 /// independently of whether they are emitted into a DIE or into a .debug_loc 76 /// entry. 77 class DwarfExpression { 78 protected: 79 unsigned DwarfVersion; 80 81 public: 82 DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {} 83 virtual ~DwarfExpression() {} 84 85 /// Output a dwarf operand and an optional assembler comment. 86 virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0; 87 /// Emit a raw signed value. 88 virtual void EmitSigned(int64_t Value) = 0; 89 /// Emit a raw unsigned value. 90 virtual void EmitUnsigned(uint64_t Value) = 0; 91 /// Return whether the given machine register is the frame register in the 92 /// current function. 93 virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0; 94 95 /// Emit a dwarf register operation. 96 void AddReg(int DwarfReg, const char *Comment = nullptr); 97 /// Emit an (double-)indirect dwarf register operation. 98 void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false); 99 100 /// Emit a DW_OP_piece operation for a variable fragment. 101 /// \param OffsetInBits This is the offset where the fragment appears 102 /// inside the *source variable*. 103 void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); 104 105 /// Emit a shift-right dwarf expression. 106 void AddShr(unsigned ShiftBy); 107 108 /// Emit a DW_OP_stack_value, if supported. 109 /// 110 /// The proper way to describe a constant value is DW_OP_constu <const>, 111 /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available 112 /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for 113 /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const 114 /// <const> actually describes a value at a constant addess, not a constant 115 /// value. However, in the past there was no better way to describe a 116 /// constant value, so the producers and consumers started to rely on 117 /// heuristics to disambiguate the value vs. location status of the 118 /// expression. See PR21176 for more details. 119 void AddStackValue(); 120 121 /// Emit an indirect dwarf register operation for the given machine register. 122 /// \return false if no DWARF register exists for MachineReg. 123 bool AddMachineRegIndirect(const TargetRegisterInfo &TRI, unsigned MachineReg, 124 int Offset = 0); 125 126 /// Emit a partial DWARF register operation. 127 /// 128 /// \param MachineReg the register, 129 /// \param FragmentSizeInBits size and 130 /// \param FragmentOffsetInBits offset of the fragment in bits, if this is 131 /// a fragment of an aggregate value. 132 /// 133 /// If size and offset is zero an operation for the entire register is 134 /// emitted: Some targets do not provide a DWARF register number for every 135 /// register. If this is the case, this function will attempt to emit a DWARF 136 /// register by emitting a fragment of a super-register or by piecing together 137 /// multiple subregisters that alias the register. 138 /// 139 /// \return false if no DWARF register exists for MachineReg. 140 bool AddMachineRegFragment(const TargetRegisterInfo &TRI, unsigned MachineReg, 141 unsigned FragmentSizeInBits = 0, 142 unsigned FragmentOffsetInBits = 0); 143 144 /// Emit a signed constant. 145 void AddSignedConstant(int64_t Value); 146 /// Emit an unsigned constant. 147 void AddUnsignedConstant(uint64_t Value); 148 /// Emit an unsigned constant. 149 void AddUnsignedConstant(const APInt &Value); 150 151 /// Emit a machine register location. As an optimization this may also consume 152 /// the prefix of a DwarfExpression if a more efficient representation for 153 /// combining the register location and the first operation exists. 154 /// 155 /// \param FragmentOffsetInBits If this is one fragment out of a fragmented 156 /// location, this is the offset of the 157 /// fragment inside the entire variable. 158 /// \return false if no DWARF register exists 159 /// for MachineReg. 160 bool AddMachineRegExpression(const TargetRegisterInfo &TRI, 161 DIExpressionCursor &Expr, unsigned MachineReg, 162 unsigned FragmentOffsetInBits = 0); 163 /// Emit all remaining operations in the DIExpressionCursor. 164 /// 165 /// \param FragmentOffsetInBits If this is one fragment out of multiple 166 /// locations, this is the offset of the 167 /// fragment inside the entire variable. 168 void AddExpression(DIExpressionCursor &&Expr, 169 unsigned FragmentOffsetInBits = 0); 170 }; 171 172 /// DwarfExpression implementation for .debug_loc entries. 173 class DebugLocDwarfExpression : public DwarfExpression { 174 ByteStreamer &BS; 175 176 public: 177 DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS) 178 : DwarfExpression(DwarfVersion), BS(BS) {} 179 180 void EmitOp(uint8_t Op, const char *Comment = nullptr) override; 181 void EmitSigned(int64_t Value) override; 182 void EmitUnsigned(uint64_t Value) override; 183 bool isFrameRegister(const TargetRegisterInfo &TRI, 184 unsigned MachineReg) override; 185 }; 186 187 /// DwarfExpression implementation for singular DW_AT_location. 188 class DIEDwarfExpression : public DwarfExpression { 189 const AsmPrinter &AP; 190 DwarfUnit &DU; 191 DIELoc &DIE; 192 193 public: 194 DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE); 195 void EmitOp(uint8_t Op, const char *Comment = nullptr) override; 196 void EmitSigned(int64_t Value) override; 197 void EmitUnsigned(uint64_t Value) override; 198 bool isFrameRegister(const TargetRegisterInfo &TRI, 199 unsigned MachineReg) override; 200 }; 201 } 202 203 #endif 204