xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains support for writing dwarf compile unit.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
14*0b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/None.h"
18*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
20*0b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
21*0b57cec5SDimitry Andric #include <cassert>
22*0b57cec5SDimitry Andric #include <cstdint>
23*0b57cec5SDimitry Andric #include <iterator>
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric namespace llvm {
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric class AsmPrinter;
28*0b57cec5SDimitry Andric class APInt;
29*0b57cec5SDimitry Andric class ByteStreamer;
30*0b57cec5SDimitry Andric class DwarfCompileUnit;
31*0b57cec5SDimitry Andric class DIELoc;
32*0b57cec5SDimitry Andric class TargetRegisterInfo;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric /// Holds a DIExpression and keeps track of how many operands have been consumed
35*0b57cec5SDimitry Andric /// so far.
36*0b57cec5SDimitry Andric class DIExpressionCursor {
37*0b57cec5SDimitry Andric   DIExpression::expr_op_iterator Start, End;
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric public:
40*0b57cec5SDimitry Andric   DIExpressionCursor(const DIExpression *Expr) {
41*0b57cec5SDimitry Andric     if (!Expr) {
42*0b57cec5SDimitry Andric       assert(Start == End);
43*0b57cec5SDimitry Andric       return;
44*0b57cec5SDimitry Andric     }
45*0b57cec5SDimitry Andric     Start = Expr->expr_op_begin();
46*0b57cec5SDimitry Andric     End = Expr->expr_op_end();
47*0b57cec5SDimitry Andric   }
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric   DIExpressionCursor(ArrayRef<uint64_t> Expr)
50*0b57cec5SDimitry Andric       : Start(Expr.begin()), End(Expr.end()) {}
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric   DIExpressionCursor(const DIExpressionCursor &) = default;
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   /// Consume one operation.
55*0b57cec5SDimitry Andric   Optional<DIExpression::ExprOperand> take() {
56*0b57cec5SDimitry Andric     if (Start == End)
57*0b57cec5SDimitry Andric       return None;
58*0b57cec5SDimitry Andric     return *(Start++);
59*0b57cec5SDimitry Andric   }
60*0b57cec5SDimitry Andric 
61*0b57cec5SDimitry Andric   /// Consume N operations.
62*0b57cec5SDimitry Andric   void consume(unsigned N) { std::advance(Start, N); }
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric   /// Return the current operation.
65*0b57cec5SDimitry Andric   Optional<DIExpression::ExprOperand> peek() const {
66*0b57cec5SDimitry Andric     if (Start == End)
67*0b57cec5SDimitry Andric       return None;
68*0b57cec5SDimitry Andric     return *(Start);
69*0b57cec5SDimitry Andric   }
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric   /// Return the next operation.
72*0b57cec5SDimitry Andric   Optional<DIExpression::ExprOperand> peekNext() const {
73*0b57cec5SDimitry Andric     if (Start == End)
74*0b57cec5SDimitry Andric       return None;
75*0b57cec5SDimitry Andric 
76*0b57cec5SDimitry Andric     auto Next = Start.getNext();
77*0b57cec5SDimitry Andric     if (Next == End)
78*0b57cec5SDimitry Andric       return None;
79*0b57cec5SDimitry Andric 
80*0b57cec5SDimitry Andric     return *Next;
81*0b57cec5SDimitry Andric   }
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric   /// Determine whether there are any operations left in this expression.
84*0b57cec5SDimitry Andric   operator bool() const { return Start != End; }
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric   DIExpression::expr_op_iterator begin() const { return Start; }
87*0b57cec5SDimitry Andric   DIExpression::expr_op_iterator end() const { return End; }
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric   /// Retrieve the fragment information, if any.
90*0b57cec5SDimitry Andric   Optional<DIExpression::FragmentInfo> getFragmentInfo() const {
91*0b57cec5SDimitry Andric     return DIExpression::getFragmentInfo(Start, End);
92*0b57cec5SDimitry Andric   }
93*0b57cec5SDimitry Andric };
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric /// Base class containing the logic for constructing DWARF expressions
96*0b57cec5SDimitry Andric /// independently of whether they are emitted into a DIE or into a .debug_loc
97*0b57cec5SDimitry Andric /// entry.
98*0b57cec5SDimitry Andric class DwarfExpression {
99*0b57cec5SDimitry Andric protected:
100*0b57cec5SDimitry Andric   /// Holds information about all subregisters comprising a register location.
101*0b57cec5SDimitry Andric   struct Register {
102*0b57cec5SDimitry Andric     int DwarfRegNo;
103*0b57cec5SDimitry Andric     unsigned Size;
104*0b57cec5SDimitry Andric     const char *Comment;
105*0b57cec5SDimitry Andric   };
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   DwarfCompileUnit &CU;
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric   /// The register location, if any.
110*0b57cec5SDimitry Andric   SmallVector<Register, 2> DwarfRegs;
111*0b57cec5SDimitry Andric 
112*0b57cec5SDimitry Andric   /// Current Fragment Offset in Bits.
113*0b57cec5SDimitry Andric   uint64_t OffsetInBits = 0;
114*0b57cec5SDimitry Andric 
115*0b57cec5SDimitry Andric   /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
116*0b57cec5SDimitry Andric   unsigned SubRegisterSizeInBits : 16;
117*0b57cec5SDimitry Andric   unsigned SubRegisterOffsetInBits : 16;
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric   /// The kind of location description being produced.
120*0b57cec5SDimitry Andric   enum { Unknown = 0, Register, Memory, Implicit };
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric   /// The flags of location description being produced.
123*0b57cec5SDimitry Andric   enum { EntryValue = 1 };
124*0b57cec5SDimitry Andric 
125*0b57cec5SDimitry Andric   unsigned LocationKind : 3;
126*0b57cec5SDimitry Andric   unsigned LocationFlags : 2;
127*0b57cec5SDimitry Andric   unsigned DwarfVersion : 4;
128*0b57cec5SDimitry Andric 
129*0b57cec5SDimitry Andric public:
130*0b57cec5SDimitry Andric   bool isUnknownLocation() const {
131*0b57cec5SDimitry Andric     return LocationKind == Unknown;
132*0b57cec5SDimitry Andric   }
133*0b57cec5SDimitry Andric 
134*0b57cec5SDimitry Andric   bool isMemoryLocation() const {
135*0b57cec5SDimitry Andric     return LocationKind == Memory;
136*0b57cec5SDimitry Andric   }
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric   bool isRegisterLocation() const {
139*0b57cec5SDimitry Andric     return LocationKind == Register;
140*0b57cec5SDimitry Andric   }
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric   bool isImplicitLocation() const {
143*0b57cec5SDimitry Andric     return LocationKind == Implicit;
144*0b57cec5SDimitry Andric   }
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric   bool isEntryValue() const {
147*0b57cec5SDimitry Andric     return LocationFlags & EntryValue;
148*0b57cec5SDimitry Andric   }
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric   Optional<uint8_t> TagOffset;
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric protected:
153*0b57cec5SDimitry Andric   /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
154*0b57cec5SDimitry Andric   /// to represent a subregister.
155*0b57cec5SDimitry Andric   void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
156*0b57cec5SDimitry Andric     assert(SizeInBits < 65536 && OffsetInBits < 65536);
157*0b57cec5SDimitry Andric     SubRegisterSizeInBits = SizeInBits;
158*0b57cec5SDimitry Andric     SubRegisterOffsetInBits = OffsetInBits;
159*0b57cec5SDimitry Andric   }
160*0b57cec5SDimitry Andric 
161*0b57cec5SDimitry Andric   /// Add masking operations to stencil out a subregister.
162*0b57cec5SDimitry Andric   void maskSubRegister();
163*0b57cec5SDimitry Andric 
164*0b57cec5SDimitry Andric   /// Output a dwarf operand and an optional assembler comment.
165*0b57cec5SDimitry Andric   virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0;
166*0b57cec5SDimitry Andric 
167*0b57cec5SDimitry Andric   /// Emit a raw signed value.
168*0b57cec5SDimitry Andric   virtual void emitSigned(int64_t Value) = 0;
169*0b57cec5SDimitry Andric 
170*0b57cec5SDimitry Andric   /// Emit a raw unsigned value.
171*0b57cec5SDimitry Andric   virtual void emitUnsigned(uint64_t Value) = 0;
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric   virtual void emitData1(uint8_t Value) = 0;
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric   virtual void emitBaseTypeRef(uint64_t Idx) = 0;
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric   /// Emit a normalized unsigned constant.
178*0b57cec5SDimitry Andric   void emitConstu(uint64_t Value);
179*0b57cec5SDimitry Andric 
180*0b57cec5SDimitry Andric   /// Return whether the given machine register is the frame register in the
181*0b57cec5SDimitry Andric   /// current function.
182*0b57cec5SDimitry Andric   virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric   /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
185*0b57cec5SDimitry Andric   /// register location description.
186*0b57cec5SDimitry Andric   void addReg(int DwarfReg, const char *Comment = nullptr);
187*0b57cec5SDimitry Andric 
188*0b57cec5SDimitry Andric   /// Emit a DW_OP_breg operation.
189*0b57cec5SDimitry Andric   void addBReg(int DwarfReg, int Offset);
190*0b57cec5SDimitry Andric 
191*0b57cec5SDimitry Andric   /// Emit DW_OP_fbreg <Offset>.
192*0b57cec5SDimitry Andric   void addFBReg(int Offset);
193*0b57cec5SDimitry Andric 
194*0b57cec5SDimitry Andric   /// Emit a partial DWARF register operation.
195*0b57cec5SDimitry Andric   ///
196*0b57cec5SDimitry Andric   /// \param MachineReg           The register number.
197*0b57cec5SDimitry Andric   /// \param MaxSize              If the register must be composed from
198*0b57cec5SDimitry Andric   ///                             sub-registers this is an upper bound
199*0b57cec5SDimitry Andric   ///                             for how many bits the emitted DW_OP_piece
200*0b57cec5SDimitry Andric   ///                             may cover.
201*0b57cec5SDimitry Andric   ///
202*0b57cec5SDimitry Andric   /// If size and offset is zero an operation for the entire register is
203*0b57cec5SDimitry Andric   /// emitted: Some targets do not provide a DWARF register number for every
204*0b57cec5SDimitry Andric   /// register.  If this is the case, this function will attempt to emit a DWARF
205*0b57cec5SDimitry Andric   /// register by emitting a fragment of a super-register or by piecing together
206*0b57cec5SDimitry Andric   /// multiple subregisters that alias the register.
207*0b57cec5SDimitry Andric   ///
208*0b57cec5SDimitry Andric   /// \return false if no DWARF register exists for MachineReg.
209*0b57cec5SDimitry Andric   bool addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg,
210*0b57cec5SDimitry Andric                      unsigned MaxSize = ~1U);
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric   /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
213*0b57cec5SDimitry Andric   /// \param OffsetInBits    This is an optional offset into the location that
214*0b57cec5SDimitry Andric   /// is at the top of the DWARF stack.
215*0b57cec5SDimitry Andric   void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
216*0b57cec5SDimitry Andric 
217*0b57cec5SDimitry Andric   /// Emit a shift-right dwarf operation.
218*0b57cec5SDimitry Andric   void addShr(unsigned ShiftBy);
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric   /// Emit a bitwise and dwarf operation.
221*0b57cec5SDimitry Andric   void addAnd(unsigned Mask);
222*0b57cec5SDimitry Andric 
223*0b57cec5SDimitry Andric   /// Emit a DW_OP_stack_value, if supported.
224*0b57cec5SDimitry Andric   ///
225*0b57cec5SDimitry Andric   /// The proper way to describe a constant value is DW_OP_constu <const>,
226*0b57cec5SDimitry Andric   /// DW_OP_stack_value.  Unfortunately, DW_OP_stack_value was not available
227*0b57cec5SDimitry Andric   /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
228*0b57cec5SDimitry Andric   /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
229*0b57cec5SDimitry Andric   /// <const> actually describes a value at a constant address, not a constant
230*0b57cec5SDimitry Andric   /// value.  However, in the past there was no better way to describe a
231*0b57cec5SDimitry Andric   /// constant value, so the producers and consumers started to rely on
232*0b57cec5SDimitry Andric   /// heuristics to disambiguate the value vs. location status of the
233*0b57cec5SDimitry Andric   /// expression.  See PR21176 for more details.
234*0b57cec5SDimitry Andric   void addStackValue();
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric   ~DwarfExpression() = default;
237*0b57cec5SDimitry Andric 
238*0b57cec5SDimitry Andric public:
239*0b57cec5SDimitry Andric   DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU)
240*0b57cec5SDimitry Andric       : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0),
241*0b57cec5SDimitry Andric         LocationKind(Unknown), LocationFlags(Unknown),
242*0b57cec5SDimitry Andric         DwarfVersion(DwarfVersion) {}
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric   /// This needs to be called last to commit any pending changes.
245*0b57cec5SDimitry Andric   void finalize();
246*0b57cec5SDimitry Andric 
247*0b57cec5SDimitry Andric   /// Emit a signed constant.
248*0b57cec5SDimitry Andric   void addSignedConstant(int64_t Value);
249*0b57cec5SDimitry Andric 
250*0b57cec5SDimitry Andric   /// Emit an unsigned constant.
251*0b57cec5SDimitry Andric   void addUnsignedConstant(uint64_t Value);
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric   /// Emit an unsigned constant.
254*0b57cec5SDimitry Andric   void addUnsignedConstant(const APInt &Value);
255*0b57cec5SDimitry Andric 
256*0b57cec5SDimitry Andric   /// Lock this down to become a memory location description.
257*0b57cec5SDimitry Andric   void setMemoryLocationKind() {
258*0b57cec5SDimitry Andric     assert(isUnknownLocation());
259*0b57cec5SDimitry Andric     LocationKind = Memory;
260*0b57cec5SDimitry Andric   }
261*0b57cec5SDimitry Andric 
262*0b57cec5SDimitry Andric   /// Lock this down to become an entry value location.
263*0b57cec5SDimitry Andric   void setEntryValueFlag() {
264*0b57cec5SDimitry Andric     LocationFlags |= EntryValue;
265*0b57cec5SDimitry Andric   }
266*0b57cec5SDimitry Andric 
267*0b57cec5SDimitry Andric   /// Emit a machine register location. As an optimization this may also consume
268*0b57cec5SDimitry Andric   /// the prefix of a DwarfExpression if a more efficient representation for
269*0b57cec5SDimitry Andric   /// combining the register location and the first operation exists.
270*0b57cec5SDimitry Andric   ///
271*0b57cec5SDimitry Andric   /// \param FragmentOffsetInBits     If this is one fragment out of a
272*0b57cec5SDimitry Andric   /// fragmented
273*0b57cec5SDimitry Andric   ///                                 location, this is the offset of the
274*0b57cec5SDimitry Andric   ///                                 fragment inside the entire variable.
275*0b57cec5SDimitry Andric   /// \return                         false if no DWARF register exists
276*0b57cec5SDimitry Andric   ///                                 for MachineReg.
277*0b57cec5SDimitry Andric   bool addMachineRegExpression(const TargetRegisterInfo &TRI,
278*0b57cec5SDimitry Andric                                DIExpressionCursor &Expr, unsigned MachineReg,
279*0b57cec5SDimitry Andric                                unsigned FragmentOffsetInBits = 0);
280*0b57cec5SDimitry Andric 
281*0b57cec5SDimitry Andric   /// Emit entry value dwarf operation.
282*0b57cec5SDimitry Andric   void addEntryValueExpression(DIExpressionCursor &ExprCursor);
283*0b57cec5SDimitry Andric 
284*0b57cec5SDimitry Andric   /// Emit all remaining operations in the DIExpressionCursor.
285*0b57cec5SDimitry Andric   ///
286*0b57cec5SDimitry Andric   /// \param FragmentOffsetInBits     If this is one fragment out of multiple
287*0b57cec5SDimitry Andric   ///                                 locations, this is the offset of the
288*0b57cec5SDimitry Andric   ///                                 fragment inside the entire variable.
289*0b57cec5SDimitry Andric   void addExpression(DIExpressionCursor &&Expr,
290*0b57cec5SDimitry Andric                      unsigned FragmentOffsetInBits = 0);
291*0b57cec5SDimitry Andric 
292*0b57cec5SDimitry Andric   /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
293*0b57cec5SDimitry Andric   /// the fragment described by \c Expr.
294*0b57cec5SDimitry Andric   void addFragmentOffset(const DIExpression *Expr);
295*0b57cec5SDimitry Andric 
296*0b57cec5SDimitry Andric   void emitLegacySExt(unsigned FromBits);
297*0b57cec5SDimitry Andric   void emitLegacyZExt(unsigned FromBits);
298*0b57cec5SDimitry Andric };
299*0b57cec5SDimitry Andric 
300*0b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries.
301*0b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression {
302*0b57cec5SDimitry Andric   ByteStreamer &BS;
303*0b57cec5SDimitry Andric 
304*0b57cec5SDimitry Andric   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
305*0b57cec5SDimitry Andric   void emitSigned(int64_t Value) override;
306*0b57cec5SDimitry Andric   void emitUnsigned(uint64_t Value) override;
307*0b57cec5SDimitry Andric   void emitData1(uint8_t Value) override;
308*0b57cec5SDimitry Andric   void emitBaseTypeRef(uint64_t Idx) override;
309*0b57cec5SDimitry Andric   bool isFrameRegister(const TargetRegisterInfo &TRI,
310*0b57cec5SDimitry Andric                        unsigned MachineReg) override;
311*0b57cec5SDimitry Andric 
312*0b57cec5SDimitry Andric public:
313*0b57cec5SDimitry Andric   DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS, DwarfCompileUnit &CU)
314*0b57cec5SDimitry Andric       : DwarfExpression(DwarfVersion, CU), BS(BS) {}
315*0b57cec5SDimitry Andric };
316*0b57cec5SDimitry Andric 
317*0b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location.
318*0b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression {
319*0b57cec5SDimitry Andric const AsmPrinter &AP;
320*0b57cec5SDimitry Andric   DIELoc &DIE;
321*0b57cec5SDimitry Andric 
322*0b57cec5SDimitry Andric   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
323*0b57cec5SDimitry Andric   void emitSigned(int64_t Value) override;
324*0b57cec5SDimitry Andric   void emitUnsigned(uint64_t Value) override;
325*0b57cec5SDimitry Andric   void emitData1(uint8_t Value) override;
326*0b57cec5SDimitry Andric   void emitBaseTypeRef(uint64_t Idx) override;
327*0b57cec5SDimitry Andric   bool isFrameRegister(const TargetRegisterInfo &TRI,
328*0b57cec5SDimitry Andric                        unsigned MachineReg) override;
329*0b57cec5SDimitry Andric public:
330*0b57cec5SDimitry Andric   DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE);
331*0b57cec5SDimitry Andric 
332*0b57cec5SDimitry Andric   DIELoc *finalize() {
333*0b57cec5SDimitry Andric     DwarfExpression::finalize();
334*0b57cec5SDimitry Andric     return &DIE;
335*0b57cec5SDimitry Andric   }
336*0b57cec5SDimitry Andric };
337*0b57cec5SDimitry Andric 
338*0b57cec5SDimitry Andric } // end namespace llvm
339*0b57cec5SDimitry Andric 
340*0b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
341