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   DIExpressionCursor(ArrayRef<uint64_t> Expr)
43       : Start(Expr.begin()), End(Expr.end()) {}
44 
45   /// Consume one operation.
46   Optional<DIExpression::ExprOperand> take() {
47     if (Start == End)
48       return None;
49     return *(Start++);
50   }
51 
52   /// Consume N operations.
53   void consume(unsigned N) { std::advance(Start, N); }
54 
55   /// Return the current operation.
56   Optional<DIExpression::ExprOperand> peek() const {
57     if (Start == End)
58       return None;
59     return *(Start);
60   }
61 
62   /// Return the next operation.
63   Optional<DIExpression::ExprOperand> peekNext() const {
64     if (Start == End)
65       return None;
66 
67     auto Next = Start.getNext();
68     if (Next == End)
69       return None;
70 
71     return *Next;
72   }
73   /// Determine whether there are any operations left in this expression.
74   operator bool() const { return Start != End; }
75 };
76 
77 /// Base class containing the logic for constructing DWARF expressions
78 /// independently of whether they are emitted into a DIE or into a .debug_loc
79 /// entry.
80 class DwarfExpression {
81 protected:
82   unsigned DwarfVersion;
83   /// Current Fragment Offset in Bits.
84   uint64_t OffsetInBits = 0;
85 
86   /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
87   unsigned SubRegisterSizeInBits = 0;
88   unsigned SubRegisterOffsetInBits = 0;
89 
90   /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
91   /// to represent a subregister.
92   void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
93     SubRegisterSizeInBits = SizeInBits;
94     SubRegisterOffsetInBits = OffsetInBits;
95   }
96 
97 public:
98   DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {}
99   virtual ~DwarfExpression() {};
100 
101   /// This needs to be called last to commit any pending changes.
102   void finalize();
103 
104   /// Output a dwarf operand and an optional assembler comment.
105   virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0;
106   /// Emit a raw signed value.
107   virtual void EmitSigned(int64_t Value) = 0;
108   /// Emit a raw unsigned value.
109   virtual void EmitUnsigned(uint64_t Value) = 0;
110   /// Return whether the given machine register is the frame register in the
111   /// current function.
112   virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
113 
114   /// Emit a dwarf register operation.
115   void AddReg(int DwarfReg, const char *Comment = nullptr);
116   /// Emit an (double-)indirect dwarf register operation.
117   void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
118 
119   /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
120   /// \param OffsetInBits    This is an optional offset into the location that
121   /// is at the top of the DWARF stack.
122   void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
123 
124   /// Emit a shift-right dwarf expression.
125   void AddShr(unsigned ShiftBy);
126 
127   /// Emit a DW_OP_stack_value, if supported.
128   ///
129   /// The proper way to describe a constant value is DW_OP_constu <const>,
130   /// DW_OP_stack_value.  Unfortunately, DW_OP_stack_value was not available
131   /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
132   /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
133   /// <const> actually describes a value at a constant addess, not a constant
134   /// value.  However, in the past there was no better way to describe a
135   /// constant value, so the producers and consumers started to rely on
136   /// heuristics to disambiguate the value vs. location status of the
137   /// expression.  See PR21176 for more details.
138   void AddStackValue();
139 
140   /// Emit an indirect dwarf register operation for the given machine register.
141   /// \return false if no DWARF register exists for MachineReg.
142   bool AddMachineRegIndirect(const TargetRegisterInfo &TRI, unsigned MachineReg,
143                              int Offset = 0);
144 
145   /// Emit a partial DWARF register operation.
146   ///
147   /// \param MachineReg           The register number.
148   ///
149   /// If size and offset is zero an operation for the entire register is
150   /// emitted: Some targets do not provide a DWARF register number for every
151   /// register.  If this is the case, this function will attempt to emit a DWARF
152   /// register by emitting a fragment of a super-register or by piecing together
153   /// multiple subregisters that alias the register.
154   ///
155   /// \return false if no DWARF register exists for MachineReg.
156   bool AddMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg);
157 
158   /// Emit a signed constant.
159   void AddSignedConstant(int64_t Value);
160   /// Emit an unsigned constant.
161   void AddUnsignedConstant(uint64_t Value);
162   /// Emit an unsigned constant.
163   void AddUnsignedConstant(const APInt &Value);
164 
165   /// Emit a machine register location. As an optimization this may also consume
166   /// the prefix of a DwarfExpression if a more efficient representation for
167   /// combining the register location and the first operation exists.
168   ///
169   /// \param FragmentOffsetInBits     If this is one fragment out of a fragmented
170   ///                                 location, this is the offset of the
171   ///                                 fragment inside the entire variable.
172   /// \return                         false if no DWARF register exists
173   ///                                 for MachineReg.
174   bool AddMachineRegExpression(const TargetRegisterInfo &TRI,
175                                DIExpressionCursor &Expr, unsigned MachineReg,
176                                unsigned FragmentOffsetInBits = 0);
177   /// Emit all remaining operations in the DIExpressionCursor.
178   ///
179   /// \param FragmentOffsetInBits     If this is one fragment out of multiple
180   ///                                 locations, this is the offset of the
181   ///                                 fragment inside the entire variable.
182   void AddExpression(DIExpressionCursor &&Expr,
183                      unsigned FragmentOffsetInBits = 0);
184 
185   /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
186   /// the fragment described by \c Expr.
187   void addFragmentOffset(const DIExpression *Expr);
188 };
189 
190 /// DwarfExpression implementation for .debug_loc entries.
191 class DebugLocDwarfExpression : public DwarfExpression {
192   ByteStreamer &BS;
193 
194 public:
195   DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS)
196       : DwarfExpression(DwarfVersion), BS(BS) {}
197 
198   void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
199   void EmitSigned(int64_t Value) override;
200   void EmitUnsigned(uint64_t Value) override;
201   bool isFrameRegister(const TargetRegisterInfo &TRI,
202                        unsigned MachineReg) override;
203 };
204 
205 /// DwarfExpression implementation for singular DW_AT_location.
206 class DIEDwarfExpression : public DwarfExpression {
207 const AsmPrinter &AP;
208   DwarfUnit &DU;
209   DIELoc &DIE;
210 
211 public:
212   DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE);
213   void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
214   void EmitSigned(int64_t Value) override;
215   void EmitUnsigned(uint64_t Value) override;
216   bool isFrameRegister(const TargetRegisterInfo &TRI,
217                        unsigned MachineReg) override;
218 };
219 }
220 
221 #endif
222