xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h (revision 8bcb0991864975618c09697b1aca10683346d9f0)
10b57cec5SDimitry Andric //===- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains support for writing dwarf compile unit.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
140b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
150b57cec5SDimitry Andric 
16*8bcb0991SDimitry Andric #include "ByteStreamer.h"
170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/None.h"
190b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
220b57cec5SDimitry Andric #include <cassert>
230b57cec5SDimitry Andric #include <cstdint>
240b57cec5SDimitry Andric #include <iterator>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace llvm {
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric class AsmPrinter;
290b57cec5SDimitry Andric class APInt;
300b57cec5SDimitry Andric class DwarfCompileUnit;
310b57cec5SDimitry Andric class DIELoc;
320b57cec5SDimitry Andric class TargetRegisterInfo;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric /// Holds a DIExpression and keeps track of how many operands have been consumed
350b57cec5SDimitry Andric /// so far.
360b57cec5SDimitry Andric class DIExpressionCursor {
370b57cec5SDimitry Andric   DIExpression::expr_op_iterator Start, End;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric public:
400b57cec5SDimitry Andric   DIExpressionCursor(const DIExpression *Expr) {
410b57cec5SDimitry Andric     if (!Expr) {
420b57cec5SDimitry Andric       assert(Start == End);
430b57cec5SDimitry Andric       return;
440b57cec5SDimitry Andric     }
450b57cec5SDimitry Andric     Start = Expr->expr_op_begin();
460b57cec5SDimitry Andric     End = Expr->expr_op_end();
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   DIExpressionCursor(ArrayRef<uint64_t> Expr)
500b57cec5SDimitry Andric       : Start(Expr.begin()), End(Expr.end()) {}
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   DIExpressionCursor(const DIExpressionCursor &) = default;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   /// Consume one operation.
550b57cec5SDimitry Andric   Optional<DIExpression::ExprOperand> take() {
560b57cec5SDimitry Andric     if (Start == End)
570b57cec5SDimitry Andric       return None;
580b57cec5SDimitry Andric     return *(Start++);
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   /// Consume N operations.
620b57cec5SDimitry Andric   void consume(unsigned N) { std::advance(Start, N); }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   /// Return the current operation.
650b57cec5SDimitry Andric   Optional<DIExpression::ExprOperand> peek() const {
660b57cec5SDimitry Andric     if (Start == End)
670b57cec5SDimitry Andric       return None;
680b57cec5SDimitry Andric     return *(Start);
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   /// Return the next operation.
720b57cec5SDimitry Andric   Optional<DIExpression::ExprOperand> peekNext() const {
730b57cec5SDimitry Andric     if (Start == End)
740b57cec5SDimitry Andric       return None;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric     auto Next = Start.getNext();
770b57cec5SDimitry Andric     if (Next == End)
780b57cec5SDimitry Andric       return None;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric     return *Next;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   /// Determine whether there are any operations left in this expression.
840b57cec5SDimitry Andric   operator bool() const { return Start != End; }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   DIExpression::expr_op_iterator begin() const { return Start; }
870b57cec5SDimitry Andric   DIExpression::expr_op_iterator end() const { return End; }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   /// Retrieve the fragment information, if any.
900b57cec5SDimitry Andric   Optional<DIExpression::FragmentInfo> getFragmentInfo() const {
910b57cec5SDimitry Andric     return DIExpression::getFragmentInfo(Start, End);
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric };
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric /// Base class containing the logic for constructing DWARF expressions
960b57cec5SDimitry Andric /// independently of whether they are emitted into a DIE or into a .debug_loc
970b57cec5SDimitry Andric /// entry.
98*8bcb0991SDimitry Andric ///
99*8bcb0991SDimitry Andric /// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the size
100*8bcb0991SDimitry Andric /// of a succeeding DWARF block before the latter is emitted to the output.
101*8bcb0991SDimitry Andric /// To handle such cases, data can conditionally be emitted to a temporary
102*8bcb0991SDimitry Andric /// buffer, which can later on be committed to the main output. The size of the
103*8bcb0991SDimitry Andric /// temporary buffer is queryable, allowing for the size of the data to be
104*8bcb0991SDimitry Andric /// emitted before the data is committed.
1050b57cec5SDimitry Andric class DwarfExpression {
1060b57cec5SDimitry Andric protected:
1070b57cec5SDimitry Andric   /// Holds information about all subregisters comprising a register location.
1080b57cec5SDimitry Andric   struct Register {
1090b57cec5SDimitry Andric     int DwarfRegNo;
1100b57cec5SDimitry Andric     unsigned Size;
1110b57cec5SDimitry Andric     const char *Comment;
1120b57cec5SDimitry Andric   };
1130b57cec5SDimitry Andric 
114*8bcb0991SDimitry Andric   /// Whether we are currently emitting an entry value operation.
115*8bcb0991SDimitry Andric   bool IsEmittingEntryValue = false;
116*8bcb0991SDimitry Andric 
1170b57cec5SDimitry Andric   DwarfCompileUnit &CU;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   /// The register location, if any.
1200b57cec5SDimitry Andric   SmallVector<Register, 2> DwarfRegs;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   /// Current Fragment Offset in Bits.
1230b57cec5SDimitry Andric   uint64_t OffsetInBits = 0;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
1260b57cec5SDimitry Andric   unsigned SubRegisterSizeInBits : 16;
1270b57cec5SDimitry Andric   unsigned SubRegisterOffsetInBits : 16;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   /// The kind of location description being produced.
1300b57cec5SDimitry Andric   enum { Unknown = 0, Register, Memory, Implicit };
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   /// The flags of location description being produced.
133*8bcb0991SDimitry Andric   enum { EntryValue = 1, CallSiteParamValue };
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   unsigned LocationKind : 3;
1360b57cec5SDimitry Andric   unsigned LocationFlags : 2;
1370b57cec5SDimitry Andric   unsigned DwarfVersion : 4;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric public:
1400b57cec5SDimitry Andric   bool isUnknownLocation() const {
1410b57cec5SDimitry Andric     return LocationKind == Unknown;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   bool isMemoryLocation() const {
1450b57cec5SDimitry Andric     return LocationKind == Memory;
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   bool isRegisterLocation() const {
1490b57cec5SDimitry Andric     return LocationKind == Register;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   bool isImplicitLocation() const {
1530b57cec5SDimitry Andric     return LocationKind == Implicit;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   bool isEntryValue() const {
1570b57cec5SDimitry Andric     return LocationFlags & EntryValue;
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric 
160*8bcb0991SDimitry Andric   bool isParameterValue() {
161*8bcb0991SDimitry Andric     return LocationFlags & CallSiteParamValue;
162*8bcb0991SDimitry Andric   }
163*8bcb0991SDimitry Andric 
1640b57cec5SDimitry Andric   Optional<uint8_t> TagOffset;
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric protected:
1670b57cec5SDimitry Andric   /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
1680b57cec5SDimitry Andric   /// to represent a subregister.
1690b57cec5SDimitry Andric   void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
1700b57cec5SDimitry Andric     assert(SizeInBits < 65536 && OffsetInBits < 65536);
1710b57cec5SDimitry Andric     SubRegisterSizeInBits = SizeInBits;
1720b57cec5SDimitry Andric     SubRegisterOffsetInBits = OffsetInBits;
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   /// Add masking operations to stencil out a subregister.
1760b57cec5SDimitry Andric   void maskSubRegister();
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   /// Output a dwarf operand and an optional assembler comment.
1790b57cec5SDimitry Andric   virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   /// Emit a raw signed value.
1820b57cec5SDimitry Andric   virtual void emitSigned(int64_t Value) = 0;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   /// Emit a raw unsigned value.
1850b57cec5SDimitry Andric   virtual void emitUnsigned(uint64_t Value) = 0;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   virtual void emitData1(uint8_t Value) = 0;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   virtual void emitBaseTypeRef(uint64_t Idx) = 0;
1900b57cec5SDimitry Andric 
191*8bcb0991SDimitry Andric   /// Start emitting data to the temporary buffer. The data stored in the
192*8bcb0991SDimitry Andric   /// temporary buffer can be committed to the main output using
193*8bcb0991SDimitry Andric   /// commitTemporaryBuffer().
194*8bcb0991SDimitry Andric   virtual void enableTemporaryBuffer() = 0;
195*8bcb0991SDimitry Andric 
196*8bcb0991SDimitry Andric   /// Disable emission to the temporary buffer. This does not commit data
197*8bcb0991SDimitry Andric   /// in the temporary buffer to the main output.
198*8bcb0991SDimitry Andric   virtual void disableTemporaryBuffer() = 0;
199*8bcb0991SDimitry Andric 
200*8bcb0991SDimitry Andric   /// Return the emitted size, in number of bytes, for the data stored in the
201*8bcb0991SDimitry Andric   /// temporary buffer.
202*8bcb0991SDimitry Andric   virtual unsigned getTemporaryBufferSize() = 0;
203*8bcb0991SDimitry Andric 
204*8bcb0991SDimitry Andric   /// Commit the data stored in the temporary buffer to the main output.
205*8bcb0991SDimitry Andric   virtual void commitTemporaryBuffer() = 0;
206*8bcb0991SDimitry Andric 
2070b57cec5SDimitry Andric   /// Emit a normalized unsigned constant.
2080b57cec5SDimitry Andric   void emitConstu(uint64_t Value);
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   /// Return whether the given machine register is the frame register in the
2110b57cec5SDimitry Andric   /// current function.
2120b57cec5SDimitry Andric   virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
2150b57cec5SDimitry Andric   /// register location description.
2160b57cec5SDimitry Andric   void addReg(int DwarfReg, const char *Comment = nullptr);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   /// Emit a DW_OP_breg operation.
2190b57cec5SDimitry Andric   void addBReg(int DwarfReg, int Offset);
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   /// Emit DW_OP_fbreg <Offset>.
2220b57cec5SDimitry Andric   void addFBReg(int Offset);
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   /// Emit a partial DWARF register operation.
2250b57cec5SDimitry Andric   ///
2260b57cec5SDimitry Andric   /// \param MachineReg           The register number.
2270b57cec5SDimitry Andric   /// \param MaxSize              If the register must be composed from
2280b57cec5SDimitry Andric   ///                             sub-registers this is an upper bound
2290b57cec5SDimitry Andric   ///                             for how many bits the emitted DW_OP_piece
2300b57cec5SDimitry Andric   ///                             may cover.
2310b57cec5SDimitry Andric   ///
2320b57cec5SDimitry Andric   /// If size and offset is zero an operation for the entire register is
2330b57cec5SDimitry Andric   /// emitted: Some targets do not provide a DWARF register number for every
2340b57cec5SDimitry Andric   /// register.  If this is the case, this function will attempt to emit a DWARF
2350b57cec5SDimitry Andric   /// register by emitting a fragment of a super-register or by piecing together
2360b57cec5SDimitry Andric   /// multiple subregisters that alias the register.
2370b57cec5SDimitry Andric   ///
2380b57cec5SDimitry Andric   /// \return false if no DWARF register exists for MachineReg.
2390b57cec5SDimitry Andric   bool addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg,
2400b57cec5SDimitry Andric                      unsigned MaxSize = ~1U);
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
2430b57cec5SDimitry Andric   /// \param OffsetInBits    This is an optional offset into the location that
2440b57cec5SDimitry Andric   /// is at the top of the DWARF stack.
2450b57cec5SDimitry Andric   void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   /// Emit a shift-right dwarf operation.
2480b57cec5SDimitry Andric   void addShr(unsigned ShiftBy);
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   /// Emit a bitwise and dwarf operation.
2510b57cec5SDimitry Andric   void addAnd(unsigned Mask);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   /// Emit a DW_OP_stack_value, if supported.
2540b57cec5SDimitry Andric   ///
2550b57cec5SDimitry Andric   /// The proper way to describe a constant value is DW_OP_constu <const>,
2560b57cec5SDimitry Andric   /// DW_OP_stack_value.  Unfortunately, DW_OP_stack_value was not available
2570b57cec5SDimitry Andric   /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
2580b57cec5SDimitry Andric   /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
2590b57cec5SDimitry Andric   /// <const> actually describes a value at a constant address, not a constant
2600b57cec5SDimitry Andric   /// value.  However, in the past there was no better way to describe a
2610b57cec5SDimitry Andric   /// constant value, so the producers and consumers started to rely on
2620b57cec5SDimitry Andric   /// heuristics to disambiguate the value vs. location status of the
2630b57cec5SDimitry Andric   /// expression.  See PR21176 for more details.
2640b57cec5SDimitry Andric   void addStackValue();
2650b57cec5SDimitry Andric 
266*8bcb0991SDimitry Andric   /// Finalize an entry value by emitting its size operand, and committing the
267*8bcb0991SDimitry Andric   /// DWARF block which has been emitted to the temporary buffer.
268*8bcb0991SDimitry Andric   void finalizeEntryValue();
269*8bcb0991SDimitry Andric 
2700b57cec5SDimitry Andric   ~DwarfExpression() = default;
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric public:
2730b57cec5SDimitry Andric   DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU)
2740b57cec5SDimitry Andric       : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0),
2750b57cec5SDimitry Andric         LocationKind(Unknown), LocationFlags(Unknown),
2760b57cec5SDimitry Andric         DwarfVersion(DwarfVersion) {}
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   /// This needs to be called last to commit any pending changes.
2790b57cec5SDimitry Andric   void finalize();
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   /// Emit a signed constant.
2820b57cec5SDimitry Andric   void addSignedConstant(int64_t Value);
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   /// Emit an unsigned constant.
2850b57cec5SDimitry Andric   void addUnsignedConstant(uint64_t Value);
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   /// Emit an unsigned constant.
2880b57cec5SDimitry Andric   void addUnsignedConstant(const APInt &Value);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   /// Lock this down to become a memory location description.
2910b57cec5SDimitry Andric   void setMemoryLocationKind() {
2920b57cec5SDimitry Andric     assert(isUnknownLocation());
2930b57cec5SDimitry Andric     LocationKind = Memory;
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   /// Lock this down to become an entry value location.
2970b57cec5SDimitry Andric   void setEntryValueFlag() {
2980b57cec5SDimitry Andric     LocationFlags |= EntryValue;
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
301*8bcb0991SDimitry Andric   /// Lock this down to become a call site parameter location.
302*8bcb0991SDimitry Andric   void setCallSiteParamValueFlag() {
303*8bcb0991SDimitry Andric     LocationFlags |= CallSiteParamValue;
304*8bcb0991SDimitry Andric   }
305*8bcb0991SDimitry Andric 
3060b57cec5SDimitry Andric   /// Emit a machine register location. As an optimization this may also consume
3070b57cec5SDimitry Andric   /// the prefix of a DwarfExpression if a more efficient representation for
3080b57cec5SDimitry Andric   /// combining the register location and the first operation exists.
3090b57cec5SDimitry Andric   ///
3100b57cec5SDimitry Andric   /// \param FragmentOffsetInBits     If this is one fragment out of a
3110b57cec5SDimitry Andric   /// fragmented
3120b57cec5SDimitry Andric   ///                                 location, this is the offset of the
3130b57cec5SDimitry Andric   ///                                 fragment inside the entire variable.
3140b57cec5SDimitry Andric   /// \return                         false if no DWARF register exists
3150b57cec5SDimitry Andric   ///                                 for MachineReg.
3160b57cec5SDimitry Andric   bool addMachineRegExpression(const TargetRegisterInfo &TRI,
3170b57cec5SDimitry Andric                                DIExpressionCursor &Expr, unsigned MachineReg,
3180b57cec5SDimitry Andric                                unsigned FragmentOffsetInBits = 0);
3190b57cec5SDimitry Andric 
320*8bcb0991SDimitry Andric   /// Begin emission of an entry value dwarf operation. The entry value's
321*8bcb0991SDimitry Andric   /// first operand is the size of the DWARF block (its second operand),
322*8bcb0991SDimitry Andric   /// which needs to be calculated at time of emission, so we don't emit
323*8bcb0991SDimitry Andric   /// any operands here.
324*8bcb0991SDimitry Andric   void beginEntryValueExpression(DIExpressionCursor &ExprCursor);
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   /// Emit all remaining operations in the DIExpressionCursor.
3270b57cec5SDimitry Andric   ///
3280b57cec5SDimitry Andric   /// \param FragmentOffsetInBits     If this is one fragment out of multiple
3290b57cec5SDimitry Andric   ///                                 locations, this is the offset of the
3300b57cec5SDimitry Andric   ///                                 fragment inside the entire variable.
3310b57cec5SDimitry Andric   void addExpression(DIExpressionCursor &&Expr,
3320b57cec5SDimitry Andric                      unsigned FragmentOffsetInBits = 0);
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
3350b57cec5SDimitry Andric   /// the fragment described by \c Expr.
3360b57cec5SDimitry Andric   void addFragmentOffset(const DIExpression *Expr);
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   void emitLegacySExt(unsigned FromBits);
3390b57cec5SDimitry Andric   void emitLegacyZExt(unsigned FromBits);
3400b57cec5SDimitry Andric };
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries.
3430b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression {
344*8bcb0991SDimitry Andric 
345*8bcb0991SDimitry Andric   struct TempBuffer {
346*8bcb0991SDimitry Andric     SmallString<32> Bytes;
347*8bcb0991SDimitry Andric     std::vector<std::string> Comments;
348*8bcb0991SDimitry Andric     BufferByteStreamer BS;
349*8bcb0991SDimitry Andric 
350*8bcb0991SDimitry Andric     TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {}
351*8bcb0991SDimitry Andric   };
352*8bcb0991SDimitry Andric 
353*8bcb0991SDimitry Andric   std::unique_ptr<TempBuffer> TmpBuf;
354*8bcb0991SDimitry Andric   BufferByteStreamer &OutBS;
355*8bcb0991SDimitry Andric   bool IsBuffering = false;
356*8bcb0991SDimitry Andric 
357*8bcb0991SDimitry Andric   /// Return the byte streamer that currently is being emitted to.
358*8bcb0991SDimitry Andric   ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
3610b57cec5SDimitry Andric   void emitSigned(int64_t Value) override;
3620b57cec5SDimitry Andric   void emitUnsigned(uint64_t Value) override;
3630b57cec5SDimitry Andric   void emitData1(uint8_t Value) override;
3640b57cec5SDimitry Andric   void emitBaseTypeRef(uint64_t Idx) override;
365*8bcb0991SDimitry Andric 
366*8bcb0991SDimitry Andric   void enableTemporaryBuffer() override;
367*8bcb0991SDimitry Andric   void disableTemporaryBuffer() override;
368*8bcb0991SDimitry Andric   unsigned getTemporaryBufferSize() override;
369*8bcb0991SDimitry Andric   void commitTemporaryBuffer() override;
370*8bcb0991SDimitry Andric 
3710b57cec5SDimitry Andric   bool isFrameRegister(const TargetRegisterInfo &TRI,
3720b57cec5SDimitry Andric                        unsigned MachineReg) override;
3730b57cec5SDimitry Andric public:
374*8bcb0991SDimitry Andric   DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS,
375*8bcb0991SDimitry Andric                           DwarfCompileUnit &CU)
376*8bcb0991SDimitry Andric       : DwarfExpression(DwarfVersion, CU), OutBS(BS) {}
3770b57cec5SDimitry Andric };
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location.
3800b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression {
3810b57cec5SDimitry Andric   const AsmPrinter &AP;
382*8bcb0991SDimitry Andric   DIELoc &OutDIE;
383*8bcb0991SDimitry Andric   DIELoc TmpDIE;
384*8bcb0991SDimitry Andric   bool IsBuffering = false;
385*8bcb0991SDimitry Andric 
386*8bcb0991SDimitry Andric   /// Return the DIE that currently is being emitted to.
387*8bcb0991SDimitry Andric   DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; }
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
3900b57cec5SDimitry Andric   void emitSigned(int64_t Value) override;
3910b57cec5SDimitry Andric   void emitUnsigned(uint64_t Value) override;
3920b57cec5SDimitry Andric   void emitData1(uint8_t Value) override;
3930b57cec5SDimitry Andric   void emitBaseTypeRef(uint64_t Idx) override;
394*8bcb0991SDimitry Andric 
395*8bcb0991SDimitry Andric   void enableTemporaryBuffer() override;
396*8bcb0991SDimitry Andric   void disableTemporaryBuffer() override;
397*8bcb0991SDimitry Andric   unsigned getTemporaryBufferSize() override;
398*8bcb0991SDimitry Andric   void commitTemporaryBuffer() override;
399*8bcb0991SDimitry Andric 
4000b57cec5SDimitry Andric   bool isFrameRegister(const TargetRegisterInfo &TRI,
4010b57cec5SDimitry Andric                        unsigned MachineReg) override;
4020b57cec5SDimitry Andric public:
4030b57cec5SDimitry Andric   DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE);
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   DIELoc *finalize() {
4060b57cec5SDimitry Andric     DwarfExpression::finalize();
407*8bcb0991SDimitry Andric     return &OutDIE;
4080b57cec5SDimitry Andric   }
4090b57cec5SDimitry Andric };
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric } // end namespace llvm
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
414