]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r305575, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / CodeGen / AsmPrinter / DwarfExpression.h
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   DIExpressionCursor(const DIExpressionCursor &C)
46       : Start(C.Start), End(C.End) {}
47
48   /// Consume one operation.
49   Optional<DIExpression::ExprOperand> take() {
50     if (Start == End)
51       return None;
52     return *(Start++);
53   }
54
55   /// Consume N operations.
56   void consume(unsigned N) { std::advance(Start, N); }
57
58   /// Return the current operation.
59   Optional<DIExpression::ExprOperand> peek() const {
60     if (Start == End)
61       return None;
62     return *(Start);
63   }
64
65   /// Return the next operation.
66   Optional<DIExpression::ExprOperand> peekNext() const {
67     if (Start == End)
68       return None;
69
70     auto Next = Start.getNext();
71     if (Next == End)
72       return None;
73
74     return *Next;
75   }
76   /// Determine whether there are any operations left in this expression.
77   operator bool() const { return Start != End; }
78   DIExpression::expr_op_iterator begin() const { return Start; }
79   DIExpression::expr_op_iterator end() const { return End; }
80
81   /// Retrieve the fragment information, if any.
82   Optional<DIExpression::FragmentInfo> getFragmentInfo() const {
83     return DIExpression::getFragmentInfo(Start, End);
84   }
85 };
86
87 /// Base class containing the logic for constructing DWARF expressions
88 /// independently of whether they are emitted into a DIE or into a .debug_loc
89 /// entry.
90 class DwarfExpression {
91 protected:
92   /// Holds information about all subregisters comprising a register location.
93   struct Register {
94     int DwarfRegNo;
95     unsigned Size;
96     const char *Comment;
97   };
98
99   /// The register location, if any.
100   SmallVector<Register, 2> DwarfRegs;
101
102   /// Current Fragment Offset in Bits.
103   uint64_t OffsetInBits = 0;
104   unsigned DwarfVersion;
105
106   /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. 
107   unsigned SubRegisterSizeInBits = 0;
108   unsigned SubRegisterOffsetInBits = 0;
109
110   /// The kind of location description being produced.
111   enum { Unknown = 0, Register, Memory, Implicit } LocationKind = Unknown;
112
113   /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
114   /// to represent a subregister.
115   void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
116     SubRegisterSizeInBits = SizeInBits;
117     SubRegisterOffsetInBits = OffsetInBits;
118   }
119
120   /// Add masking operations to stencil out a subregister.
121   void maskSubRegister();
122
123   /// Output a dwarf operand and an optional assembler comment.
124   virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0;
125   /// Emit a raw signed value.
126   virtual void emitSigned(int64_t Value) = 0;
127   /// Emit a raw unsigned value.
128   virtual void emitUnsigned(uint64_t Value) = 0;
129   /// Return whether the given machine register is the frame register in the
130   /// current function.
131   virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
132
133   /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
134   /// register location description.
135   void addReg(int DwarfReg, const char *Comment = nullptr);
136   /// Emit a DW_OP_breg operation.
137   void addBReg(int DwarfReg, int Offset);
138   /// Emit DW_OP_fbreg <Offset>.
139   void addFBReg(int Offset);
140
141   /// Emit a partial DWARF register operation.
142   ///
143   /// \param MachineReg           The register number.
144   /// \param MaxSize              If the register must be composed from
145   ///                             sub-registers this is an upper bound
146   ///                             for how many bits the emitted DW_OP_piece
147   ///                             may cover.
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                      unsigned MaxSize = ~1U);
158
159
160   /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
161   /// \param OffsetInBits    This is an optional offset into the location that
162   /// is at the top of the DWARF stack.
163   void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
164
165   /// Emit a shift-right dwarf operation.
166   void addShr(unsigned ShiftBy);
167   /// Emit a bitwise and dwarf operation.
168   void addAnd(unsigned Mask);
169
170   /// Emit a DW_OP_stack_value, if supported.
171   ///
172   /// The proper way to describe a constant value is DW_OP_constu <const>,
173   /// DW_OP_stack_value.  Unfortunately, DW_OP_stack_value was not available
174   /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
175   /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
176   /// <const> actually describes a value at a constant addess, not a constant
177   /// value.  However, in the past there was no better way to describe a
178   /// constant value, so the producers and consumers started to rely on
179   /// heuristics to disambiguate the value vs. location status of the
180   /// expression.  See PR21176 for more details.
181   void addStackValue();
182
183   ~DwarfExpression() = default;
184 public:
185   DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {}
186
187   /// This needs to be called last to commit any pending changes.
188   void finalize();
189
190   /// Emit a signed constant.
191   void addSignedConstant(int64_t Value);
192   /// Emit an unsigned constant.
193   void addUnsignedConstant(uint64_t Value);
194   /// Emit an unsigned constant.
195   void addUnsignedConstant(const APInt &Value);
196
197   /// Lock this down to become a memory location description.
198   void setMemoryLocationKind() {
199     assert(LocationKind == Unknown);
200     LocationKind = Memory;
201   }
202
203   /// Emit a machine register location. As an optimization this may also consume
204   /// the prefix of a DwarfExpression if a more efficient representation for
205   /// combining the register location and the first operation exists.
206   ///
207   /// \param FragmentOffsetInBits     If this is one fragment out of a
208   /// fragmented
209   ///                                 location, this is the offset of the
210   ///                                 fragment inside the entire variable.
211   /// \return                         false if no DWARF register exists
212   ///                                 for MachineReg.
213   bool addMachineRegExpression(const TargetRegisterInfo &TRI,
214                                DIExpressionCursor &Expr, unsigned MachineReg,
215                                unsigned FragmentOffsetInBits = 0);
216   /// Emit all remaining operations in the DIExpressionCursor.
217   ///
218   /// \param FragmentOffsetInBits     If this is one fragment out of multiple
219   ///                                 locations, this is the offset of the
220   ///                                 fragment inside the entire variable.
221   void addExpression(DIExpressionCursor &&Expr,
222                      unsigned FragmentOffsetInBits = 0);
223
224   /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
225   /// the fragment described by \c Expr.
226   void addFragmentOffset(const DIExpression *Expr);
227 };
228
229 /// DwarfExpression implementation for .debug_loc entries.
230 class DebugLocDwarfExpression final : public DwarfExpression {
231   ByteStreamer &BS;
232
233   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
234   void emitSigned(int64_t Value) override;
235   void emitUnsigned(uint64_t Value) override;
236   bool isFrameRegister(const TargetRegisterInfo &TRI,
237                        unsigned MachineReg) override;
238 public:
239   DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS)
240       : DwarfExpression(DwarfVersion), BS(BS) {}
241 };
242
243 /// DwarfExpression implementation for singular DW_AT_location.
244 class DIEDwarfExpression final : public DwarfExpression {
245 const AsmPrinter &AP;
246   DwarfUnit &DU;
247   DIELoc &DIE;
248
249   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
250   void emitSigned(int64_t Value) override;
251   void emitUnsigned(uint64_t Value) override;
252   bool isFrameRegister(const TargetRegisterInfo &TRI,
253                        unsigned MachineReg) override;
254 public:
255   DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE);
256   DIELoc *finalize() {
257     DwarfExpression::finalize();
258     return &DIE;
259   }
260 };
261 }
262
263 #endif