xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
168bcb0991SDimitry Andric #include "ByteStreamer.h"
170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
200b57cec5SDimitry Andric #include <cassert>
210b57cec5SDimitry Andric #include <cstdint>
220b57cec5SDimitry Andric #include <iterator>
23*bdd1243dSDimitry Andric #include <optional>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace llvm {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric class AsmPrinter;
280b57cec5SDimitry Andric class APInt;
290b57cec5SDimitry Andric class DwarfCompileUnit;
300b57cec5SDimitry Andric class DIELoc;
310b57cec5SDimitry Andric class TargetRegisterInfo;
325ffd83dbSDimitry Andric class MachineLocation;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric /// Base class containing the logic for constructing DWARF expressions
350b57cec5SDimitry Andric /// independently of whether they are emitted into a DIE or into a .debug_loc
360b57cec5SDimitry Andric /// entry.
378bcb0991SDimitry Andric ///
388bcb0991SDimitry Andric /// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the size
398bcb0991SDimitry Andric /// of a succeeding DWARF block before the latter is emitted to the output.
408bcb0991SDimitry Andric /// To handle such cases, data can conditionally be emitted to a temporary
418bcb0991SDimitry Andric /// buffer, which can later on be committed to the main output. The size of the
428bcb0991SDimitry Andric /// temporary buffer is queryable, allowing for the size of the data to be
438bcb0991SDimitry Andric /// emitted before the data is committed.
440b57cec5SDimitry Andric class DwarfExpression {
450b57cec5SDimitry Andric protected:
460b57cec5SDimitry Andric   /// Holds information about all subregisters comprising a register location.
470b57cec5SDimitry Andric   struct Register {
480b57cec5SDimitry Andric     int DwarfRegNo;
495ffd83dbSDimitry Andric     unsigned SubRegSize;
500b57cec5SDimitry Andric     const char *Comment;
515ffd83dbSDimitry Andric 
525ffd83dbSDimitry Andric     /// Create a full register, no extra DW_OP_piece operators necessary.
createRegisterRegister535ffd83dbSDimitry Andric     static Register createRegister(int RegNo, const char *Comment) {
545ffd83dbSDimitry Andric       return {RegNo, 0, Comment};
555ffd83dbSDimitry Andric     }
565ffd83dbSDimitry Andric 
575ffd83dbSDimitry Andric     /// Create a subregister that needs a DW_OP_piece operator with SizeInBits.
createSubRegisterRegister585ffd83dbSDimitry Andric     static Register createSubRegister(int RegNo, unsigned SizeInBits,
595ffd83dbSDimitry Andric                                       const char *Comment) {
605ffd83dbSDimitry Andric       return {RegNo, SizeInBits, Comment};
615ffd83dbSDimitry Andric     }
625ffd83dbSDimitry Andric 
isSubRegisterRegister635ffd83dbSDimitry Andric     bool isSubRegister() const { return SubRegSize; }
640b57cec5SDimitry Andric   };
650b57cec5SDimitry Andric 
668bcb0991SDimitry Andric   /// Whether we are currently emitting an entry value operation.
678bcb0991SDimitry Andric   bool IsEmittingEntryValue = false;
688bcb0991SDimitry Andric 
690b57cec5SDimitry Andric   DwarfCompileUnit &CU;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   /// The register location, if any.
720b57cec5SDimitry Andric   SmallVector<Register, 2> DwarfRegs;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   /// Current Fragment Offset in Bits.
750b57cec5SDimitry Andric   uint64_t OffsetInBits = 0;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
780b57cec5SDimitry Andric   unsigned SubRegisterSizeInBits : 16;
790b57cec5SDimitry Andric   unsigned SubRegisterOffsetInBits : 16;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   /// The kind of location description being produced.
820b57cec5SDimitry Andric   enum { Unknown = 0, Register, Memory, Implicit };
830b57cec5SDimitry Andric 
845ffd83dbSDimitry Andric   /// Additional location flags which may be combined with any location kind.
855ffd83dbSDimitry Andric   /// Currently, entry values are not supported for the Memory location kind.
865ffd83dbSDimitry Andric   enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 };
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   unsigned LocationKind : 3;
89fe6060f1SDimitry Andric   unsigned SavedLocationKind : 3;
905ffd83dbSDimitry Andric   unsigned LocationFlags : 3;
910b57cec5SDimitry Andric   unsigned DwarfVersion : 4;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric public:
945ffd83dbSDimitry Andric   /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe.
955ffd83dbSDimitry Andric   void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr);
960b57cec5SDimitry Andric 
isUnknownLocation()975ffd83dbSDimitry Andric   bool isUnknownLocation() const { return LocationKind == Unknown; }
980b57cec5SDimitry Andric 
isMemoryLocation()995ffd83dbSDimitry Andric   bool isMemoryLocation() const { return LocationKind == Memory; }
1000b57cec5SDimitry Andric 
isRegisterLocation()1015ffd83dbSDimitry Andric   bool isRegisterLocation() const { return LocationKind == Register; }
1020b57cec5SDimitry Andric 
isImplicitLocation()1035ffd83dbSDimitry Andric   bool isImplicitLocation() const { return LocationKind == Implicit; }
1040b57cec5SDimitry Andric 
isEntryValue()1055ffd83dbSDimitry Andric   bool isEntryValue() const { return LocationFlags & EntryValue; }
1065ffd83dbSDimitry Andric 
isIndirect()1075ffd83dbSDimitry Andric   bool isIndirect() const { return LocationFlags & Indirect; }
1085ffd83dbSDimitry Andric 
isParameterValue()1095ffd83dbSDimitry Andric   bool isParameterValue() { return LocationFlags & CallSiteParamValue; }
1108bcb0991SDimitry Andric 
111*bdd1243dSDimitry Andric   std::optional<uint8_t> TagOffset;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric protected:
1140b57cec5SDimitry Andric   /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
1150b57cec5SDimitry Andric   /// to represent a subregister.
setSubRegisterPiece(unsigned SizeInBits,unsigned OffsetInBits)1160b57cec5SDimitry Andric   void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
1170b57cec5SDimitry Andric     assert(SizeInBits < 65536 && OffsetInBits < 65536);
1180b57cec5SDimitry Andric     SubRegisterSizeInBits = SizeInBits;
1190b57cec5SDimitry Andric     SubRegisterOffsetInBits = OffsetInBits;
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   /// Add masking operations to stencil out a subregister.
1230b57cec5SDimitry Andric   void maskSubRegister();
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   /// Output a dwarf operand and an optional assembler comment.
1260b57cec5SDimitry Andric   virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   /// Emit a raw signed value.
1290b57cec5SDimitry Andric   virtual void emitSigned(int64_t Value) = 0;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   /// Emit a raw unsigned value.
1320b57cec5SDimitry Andric   virtual void emitUnsigned(uint64_t Value) = 0;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   virtual void emitData1(uint8_t Value) = 0;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   virtual void emitBaseTypeRef(uint64_t Idx) = 0;
1370b57cec5SDimitry Andric 
1388bcb0991SDimitry Andric   /// Start emitting data to the temporary buffer. The data stored in the
1398bcb0991SDimitry Andric   /// temporary buffer can be committed to the main output using
1408bcb0991SDimitry Andric   /// commitTemporaryBuffer().
1418bcb0991SDimitry Andric   virtual void enableTemporaryBuffer() = 0;
1428bcb0991SDimitry Andric 
1438bcb0991SDimitry Andric   /// Disable emission to the temporary buffer. This does not commit data
1448bcb0991SDimitry Andric   /// in the temporary buffer to the main output.
1458bcb0991SDimitry Andric   virtual void disableTemporaryBuffer() = 0;
1468bcb0991SDimitry Andric 
1478bcb0991SDimitry Andric   /// Return the emitted size, in number of bytes, for the data stored in the
1488bcb0991SDimitry Andric   /// temporary buffer.
1498bcb0991SDimitry Andric   virtual unsigned getTemporaryBufferSize() = 0;
1508bcb0991SDimitry Andric 
1518bcb0991SDimitry Andric   /// Commit the data stored in the temporary buffer to the main output.
1528bcb0991SDimitry Andric   virtual void commitTemporaryBuffer() = 0;
1538bcb0991SDimitry Andric 
1540b57cec5SDimitry Andric   /// Emit a normalized unsigned constant.
1550b57cec5SDimitry Andric   void emitConstu(uint64_t Value);
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   /// Return whether the given machine register is the frame register in the
1580b57cec5SDimitry Andric   /// current function.
1595ffd83dbSDimitry Andric   virtual bool isFrameRegister(const TargetRegisterInfo &TRI,
160e8d8bef9SDimitry Andric                                llvm::Register MachineReg) = 0;
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
1630b57cec5SDimitry Andric   /// register location description.
1640b57cec5SDimitry Andric   void addReg(int DwarfReg, const char *Comment = nullptr);
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   /// Emit a DW_OP_breg operation.
1670b57cec5SDimitry Andric   void addBReg(int DwarfReg, int Offset);
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   /// Emit DW_OP_fbreg <Offset>.
1700b57cec5SDimitry Andric   void addFBReg(int Offset);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   /// Emit a partial DWARF register operation.
1730b57cec5SDimitry Andric   ///
1740b57cec5SDimitry Andric   /// \param MachineReg           The register number.
1750b57cec5SDimitry Andric   /// \param MaxSize              If the register must be composed from
1760b57cec5SDimitry Andric   ///                             sub-registers this is an upper bound
1770b57cec5SDimitry Andric   ///                             for how many bits the emitted DW_OP_piece
1780b57cec5SDimitry Andric   ///                             may cover.
1790b57cec5SDimitry Andric   ///
1800b57cec5SDimitry Andric   /// If size and offset is zero an operation for the entire register is
1810b57cec5SDimitry Andric   /// emitted: Some targets do not provide a DWARF register number for every
1820b57cec5SDimitry Andric   /// register.  If this is the case, this function will attempt to emit a DWARF
1830b57cec5SDimitry Andric   /// register by emitting a fragment of a super-register or by piecing together
1840b57cec5SDimitry Andric   /// multiple subregisters that alias the register.
1850b57cec5SDimitry Andric   ///
1860b57cec5SDimitry Andric   /// \return false if no DWARF register exists for MachineReg.
187e8d8bef9SDimitry Andric   bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register MachineReg,
1880b57cec5SDimitry Andric                      unsigned MaxSize = ~1U);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
1910b57cec5SDimitry Andric   /// \param OffsetInBits    This is an optional offset into the location that
1920b57cec5SDimitry Andric   /// is at the top of the DWARF stack.
1930b57cec5SDimitry Andric   void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   /// Emit a shift-right dwarf operation.
1960b57cec5SDimitry Andric   void addShr(unsigned ShiftBy);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   /// Emit a bitwise and dwarf operation.
1990b57cec5SDimitry Andric   void addAnd(unsigned Mask);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   /// Emit a DW_OP_stack_value, if supported.
2020b57cec5SDimitry Andric   ///
2030b57cec5SDimitry Andric   /// The proper way to describe a constant value is DW_OP_constu <const>,
2040b57cec5SDimitry Andric   /// DW_OP_stack_value.  Unfortunately, DW_OP_stack_value was not available
2050b57cec5SDimitry Andric   /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
2060b57cec5SDimitry Andric   /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
2070b57cec5SDimitry Andric   /// <const> actually describes a value at a constant address, not a constant
2080b57cec5SDimitry Andric   /// value.  However, in the past there was no better way to describe a
2090b57cec5SDimitry Andric   /// constant value, so the producers and consumers started to rely on
2100b57cec5SDimitry Andric   /// heuristics to disambiguate the value vs. location status of the
2110b57cec5SDimitry Andric   /// expression.  See PR21176 for more details.
2120b57cec5SDimitry Andric   void addStackValue();
2130b57cec5SDimitry Andric 
2148bcb0991SDimitry Andric   /// Finalize an entry value by emitting its size operand, and committing the
2158bcb0991SDimitry Andric   /// DWARF block which has been emitted to the temporary buffer.
2168bcb0991SDimitry Andric   void finalizeEntryValue();
2178bcb0991SDimitry Andric 
2185ffd83dbSDimitry Andric   /// Cancel the emission of an entry value.
2195ffd83dbSDimitry Andric   void cancelEntryValue();
2205ffd83dbSDimitry Andric 
2210b57cec5SDimitry Andric   ~DwarfExpression() = default;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric public:
DwarfExpression(unsigned DwarfVersion,DwarfCompileUnit & CU)2240b57cec5SDimitry Andric   DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU)
2250b57cec5SDimitry Andric       : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0),
226fe6060f1SDimitry Andric         LocationKind(Unknown), SavedLocationKind(Unknown),
227fe6060f1SDimitry Andric         LocationFlags(Unknown), DwarfVersion(DwarfVersion) {}
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   /// This needs to be called last to commit any pending changes.
2300b57cec5SDimitry Andric   void finalize();
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   /// Emit a signed constant.
2330b57cec5SDimitry Andric   void addSignedConstant(int64_t Value);
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   /// Emit an unsigned constant.
2360b57cec5SDimitry Andric   void addUnsignedConstant(uint64_t Value);
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   /// Emit an unsigned constant.
2390b57cec5SDimitry Andric   void addUnsignedConstant(const APInt &Value);
2400b57cec5SDimitry Andric 
241e8d8bef9SDimitry Andric   /// Emit an floating point constant.
242e8d8bef9SDimitry Andric   void addConstantFP(const APFloat &Value, const AsmPrinter &AP);
243e8d8bef9SDimitry Andric 
2440b57cec5SDimitry Andric   /// Lock this down to become a memory location description.
setMemoryLocationKind()2450b57cec5SDimitry Andric   void setMemoryLocationKind() {
2460b57cec5SDimitry Andric     assert(isUnknownLocation());
2470b57cec5SDimitry Andric     LocationKind = Memory;
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   /// Lock this down to become an entry value location.
2515ffd83dbSDimitry Andric   void setEntryValueFlags(const MachineLocation &Loc);
2520b57cec5SDimitry Andric 
2538bcb0991SDimitry Andric   /// Lock this down to become a call site parameter location.
setCallSiteParamValueFlag()2545ffd83dbSDimitry Andric   void setCallSiteParamValueFlag() { LocationFlags |= CallSiteParamValue; }
2558bcb0991SDimitry Andric 
2560b57cec5SDimitry Andric   /// Emit a machine register location. As an optimization this may also consume
2570b57cec5SDimitry Andric   /// the prefix of a DwarfExpression if a more efficient representation for
2580b57cec5SDimitry Andric   /// combining the register location and the first operation exists.
2590b57cec5SDimitry Andric   ///
2600b57cec5SDimitry Andric   /// \param FragmentOffsetInBits     If this is one fragment out of a
2610b57cec5SDimitry Andric   /// fragmented
2620b57cec5SDimitry Andric   ///                                 location, this is the offset of the
2630b57cec5SDimitry Andric   ///                                 fragment inside the entire variable.
2640b57cec5SDimitry Andric   /// \return                         false if no DWARF register exists
2650b57cec5SDimitry Andric   ///                                 for MachineReg.
2660b57cec5SDimitry Andric   bool addMachineRegExpression(const TargetRegisterInfo &TRI,
267e8d8bef9SDimitry Andric                                DIExpressionCursor &Expr,
268e8d8bef9SDimitry Andric                                llvm::Register MachineReg,
2690b57cec5SDimitry Andric                                unsigned FragmentOffsetInBits = 0);
2700b57cec5SDimitry Andric 
2718bcb0991SDimitry Andric   /// Begin emission of an entry value dwarf operation. The entry value's
2728bcb0991SDimitry Andric   /// first operand is the size of the DWARF block (its second operand),
2738bcb0991SDimitry Andric   /// which needs to be calculated at time of emission, so we don't emit
2748bcb0991SDimitry Andric   /// any operands here.
2758bcb0991SDimitry Andric   void beginEntryValueExpression(DIExpressionCursor &ExprCursor);
2760b57cec5SDimitry Andric 
2775ffd83dbSDimitry Andric   /// Return the index of a base type with the given properties and
2785ffd83dbSDimitry Andric   /// create one if necessary.
2795ffd83dbSDimitry Andric   unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding);
2805ffd83dbSDimitry Andric 
2819738bc28SDimitry Andric   /// Emit all remaining operations in the DIExpressionCursor. The
2829738bc28SDimitry Andric   /// cursor must not contain any DW_OP_LLVM_arg operations.
2839738bc28SDimitry Andric   void addExpression(DIExpressionCursor &&Expr);
2849738bc28SDimitry Andric 
2850b57cec5SDimitry Andric   /// Emit all remaining operations in the DIExpressionCursor.
2869738bc28SDimitry Andric   /// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg).
2879738bc28SDimitry Andric   //
2889738bc28SDimitry Andric   /// \return false if any call to (\p InsertArg) returns false.
2899738bc28SDimitry Andric   bool addExpression(
2909738bc28SDimitry Andric       DIExpressionCursor &&Expr,
291fe6060f1SDimitry Andric       llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg);
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
2940b57cec5SDimitry Andric   /// the fragment described by \c Expr.
2950b57cec5SDimitry Andric   void addFragmentOffset(const DIExpression *Expr);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   void emitLegacySExt(unsigned FromBits);
2980b57cec5SDimitry Andric   void emitLegacyZExt(unsigned FromBits);
299480093f4SDimitry Andric 
300480093f4SDimitry Andric   /// Emit location information expressed via WebAssembly location + offset
301480093f4SDimitry Andric   /// The Index is an identifier for locals, globals or operand stack.
3025ffd83dbSDimitry Andric   void addWasmLocation(unsigned Index, uint64_t Offset);
3030b57cec5SDimitry Andric };
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries.
3060b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression {
3078bcb0991SDimitry Andric 
3088bcb0991SDimitry Andric   struct TempBuffer {
3098bcb0991SDimitry Andric     SmallString<32> Bytes;
3108bcb0991SDimitry Andric     std::vector<std::string> Comments;
3118bcb0991SDimitry Andric     BufferByteStreamer BS;
3128bcb0991SDimitry Andric 
TempBufferTempBuffer3138bcb0991SDimitry Andric     TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {}
3148bcb0991SDimitry Andric   };
3158bcb0991SDimitry Andric 
3168bcb0991SDimitry Andric   std::unique_ptr<TempBuffer> TmpBuf;
3178bcb0991SDimitry Andric   BufferByteStreamer &OutBS;
3188bcb0991SDimitry Andric   bool IsBuffering = false;
3198bcb0991SDimitry Andric 
3208bcb0991SDimitry Andric   /// Return the byte streamer that currently is being emitted to.
getActiveStreamer()3218bcb0991SDimitry Andric   ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
3240b57cec5SDimitry Andric   void emitSigned(int64_t Value) override;
3250b57cec5SDimitry Andric   void emitUnsigned(uint64_t Value) override;
3260b57cec5SDimitry Andric   void emitData1(uint8_t Value) override;
3270b57cec5SDimitry Andric   void emitBaseTypeRef(uint64_t Idx) override;
3288bcb0991SDimitry Andric 
3298bcb0991SDimitry Andric   void enableTemporaryBuffer() override;
3308bcb0991SDimitry Andric   void disableTemporaryBuffer() override;
3318bcb0991SDimitry Andric   unsigned getTemporaryBufferSize() override;
3328bcb0991SDimitry Andric   void commitTemporaryBuffer() override;
3338bcb0991SDimitry Andric 
3340b57cec5SDimitry Andric   bool isFrameRegister(const TargetRegisterInfo &TRI,
335e8d8bef9SDimitry Andric                        llvm::Register MachineReg) override;
3365ffd83dbSDimitry Andric 
3370b57cec5SDimitry Andric public:
DebugLocDwarfExpression(unsigned DwarfVersion,BufferByteStreamer & BS,DwarfCompileUnit & CU)3388bcb0991SDimitry Andric   DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS,
3398bcb0991SDimitry Andric                           DwarfCompileUnit &CU)
3408bcb0991SDimitry Andric       : DwarfExpression(DwarfVersion, CU), OutBS(BS) {}
3410b57cec5SDimitry Andric };
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location.
3440b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression {
3450b57cec5SDimitry Andric   const AsmPrinter &AP;
3468bcb0991SDimitry Andric   DIELoc &OutDIE;
3478bcb0991SDimitry Andric   DIELoc TmpDIE;
3488bcb0991SDimitry Andric   bool IsBuffering = false;
3498bcb0991SDimitry Andric 
3508bcb0991SDimitry Andric   /// Return the DIE that currently is being emitted to.
getActiveDIE()3518bcb0991SDimitry Andric   DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   void emitOp(uint8_t Op, const char *Comment = nullptr) override;
3540b57cec5SDimitry Andric   void emitSigned(int64_t Value) override;
3550b57cec5SDimitry Andric   void emitUnsigned(uint64_t Value) override;
3560b57cec5SDimitry Andric   void emitData1(uint8_t Value) override;
3570b57cec5SDimitry Andric   void emitBaseTypeRef(uint64_t Idx) override;
3588bcb0991SDimitry Andric 
3598bcb0991SDimitry Andric   void enableTemporaryBuffer() override;
3608bcb0991SDimitry Andric   void disableTemporaryBuffer() override;
3618bcb0991SDimitry Andric   unsigned getTemporaryBufferSize() override;
3628bcb0991SDimitry Andric   void commitTemporaryBuffer() override;
3638bcb0991SDimitry Andric 
3640b57cec5SDimitry Andric   bool isFrameRegister(const TargetRegisterInfo &TRI,
365e8d8bef9SDimitry Andric                        llvm::Register MachineReg) override;
3665ffd83dbSDimitry Andric 
3670b57cec5SDimitry Andric public:
3680b57cec5SDimitry Andric   DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE);
3690b57cec5SDimitry Andric 
finalize()3700b57cec5SDimitry Andric   DIELoc *finalize() {
3710b57cec5SDimitry Andric     DwarfExpression::finalize();
3728bcb0991SDimitry Andric     return &OutDIE;
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric };
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric } // end namespace llvm
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
379