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/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; 33*5ffd83dbSDimitry Andric class MachineLocation; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric /// Holds a DIExpression and keeps track of how many operands have been consumed 360b57cec5SDimitry Andric /// so far. 370b57cec5SDimitry Andric class DIExpressionCursor { 380b57cec5SDimitry Andric DIExpression::expr_op_iterator Start, End; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric public: 410b57cec5SDimitry Andric DIExpressionCursor(const DIExpression *Expr) { 420b57cec5SDimitry Andric if (!Expr) { 430b57cec5SDimitry Andric assert(Start == End); 440b57cec5SDimitry Andric return; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric Start = Expr->expr_op_begin(); 470b57cec5SDimitry Andric End = Expr->expr_op_end(); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric DIExpressionCursor(ArrayRef<uint64_t> Expr) 510b57cec5SDimitry Andric : Start(Expr.begin()), End(Expr.end()) {} 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric DIExpressionCursor(const DIExpressionCursor &) = default; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// Consume one operation. 560b57cec5SDimitry Andric Optional<DIExpression::ExprOperand> take() { 570b57cec5SDimitry Andric if (Start == End) 580b57cec5SDimitry Andric return None; 590b57cec5SDimitry Andric return *(Start++); 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Consume N operations. 630b57cec5SDimitry Andric void consume(unsigned N) { std::advance(Start, N); } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric /// Return the current operation. 660b57cec5SDimitry Andric Optional<DIExpression::ExprOperand> peek() const { 670b57cec5SDimitry Andric if (Start == End) 680b57cec5SDimitry Andric return None; 690b57cec5SDimitry Andric return *(Start); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric /// Return the next operation. 730b57cec5SDimitry Andric Optional<DIExpression::ExprOperand> peekNext() const { 740b57cec5SDimitry Andric if (Start == End) 750b57cec5SDimitry Andric return None; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric auto Next = Start.getNext(); 780b57cec5SDimitry Andric if (Next == End) 790b57cec5SDimitry Andric return None; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric return *Next; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /// Determine whether there are any operations left in this expression. 850b57cec5SDimitry Andric operator bool() const { return Start != End; } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric DIExpression::expr_op_iterator begin() const { return Start; } 880b57cec5SDimitry Andric DIExpression::expr_op_iterator end() const { return End; } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// Retrieve the fragment information, if any. 910b57cec5SDimitry Andric Optional<DIExpression::FragmentInfo> getFragmentInfo() const { 920b57cec5SDimitry Andric return DIExpression::getFragmentInfo(Start, End); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric }; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric /// Base class containing the logic for constructing DWARF expressions 970b57cec5SDimitry Andric /// independently of whether they are emitted into a DIE or into a .debug_loc 980b57cec5SDimitry Andric /// entry. 998bcb0991SDimitry Andric /// 1008bcb0991SDimitry Andric /// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the size 1018bcb0991SDimitry Andric /// of a succeeding DWARF block before the latter is emitted to the output. 1028bcb0991SDimitry Andric /// To handle such cases, data can conditionally be emitted to a temporary 1038bcb0991SDimitry Andric /// buffer, which can later on be committed to the main output. The size of the 1048bcb0991SDimitry Andric /// temporary buffer is queryable, allowing for the size of the data to be 1058bcb0991SDimitry Andric /// emitted before the data is committed. 1060b57cec5SDimitry Andric class DwarfExpression { 1070b57cec5SDimitry Andric protected: 1080b57cec5SDimitry Andric /// Holds information about all subregisters comprising a register location. 1090b57cec5SDimitry Andric struct Register { 1100b57cec5SDimitry Andric int DwarfRegNo; 111*5ffd83dbSDimitry Andric unsigned SubRegSize; 1120b57cec5SDimitry Andric const char *Comment; 113*5ffd83dbSDimitry Andric 114*5ffd83dbSDimitry Andric /// Create a full register, no extra DW_OP_piece operators necessary. 115*5ffd83dbSDimitry Andric static Register createRegister(int RegNo, const char *Comment) { 116*5ffd83dbSDimitry Andric return {RegNo, 0, Comment}; 117*5ffd83dbSDimitry Andric } 118*5ffd83dbSDimitry Andric 119*5ffd83dbSDimitry Andric /// Create a subregister that needs a DW_OP_piece operator with SizeInBits. 120*5ffd83dbSDimitry Andric static Register createSubRegister(int RegNo, unsigned SizeInBits, 121*5ffd83dbSDimitry Andric const char *Comment) { 122*5ffd83dbSDimitry Andric return {RegNo, SizeInBits, Comment}; 123*5ffd83dbSDimitry Andric } 124*5ffd83dbSDimitry Andric 125*5ffd83dbSDimitry Andric bool isSubRegister() const { return SubRegSize; } 1260b57cec5SDimitry Andric }; 1270b57cec5SDimitry Andric 1288bcb0991SDimitry Andric /// Whether we are currently emitting an entry value operation. 1298bcb0991SDimitry Andric bool IsEmittingEntryValue = false; 1308bcb0991SDimitry Andric 1310b57cec5SDimitry Andric DwarfCompileUnit &CU; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric /// The register location, if any. 1340b57cec5SDimitry Andric SmallVector<Register, 2> DwarfRegs; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// Current Fragment Offset in Bits. 1370b57cec5SDimitry Andric uint64_t OffsetInBits = 0; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. 1400b57cec5SDimitry Andric unsigned SubRegisterSizeInBits : 16; 1410b57cec5SDimitry Andric unsigned SubRegisterOffsetInBits : 16; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// The kind of location description being produced. 1440b57cec5SDimitry Andric enum { Unknown = 0, Register, Memory, Implicit }; 1450b57cec5SDimitry Andric 146*5ffd83dbSDimitry Andric /// Additional location flags which may be combined with any location kind. 147*5ffd83dbSDimitry Andric /// Currently, entry values are not supported for the Memory location kind. 148*5ffd83dbSDimitry Andric enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 }; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric unsigned LocationKind : 3; 151*5ffd83dbSDimitry Andric unsigned LocationFlags : 3; 1520b57cec5SDimitry Andric unsigned DwarfVersion : 4; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric public: 155*5ffd83dbSDimitry Andric /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe. 156*5ffd83dbSDimitry Andric void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr); 1570b57cec5SDimitry Andric 158*5ffd83dbSDimitry Andric bool isUnknownLocation() const { return LocationKind == Unknown; } 1590b57cec5SDimitry Andric 160*5ffd83dbSDimitry Andric bool isMemoryLocation() const { return LocationKind == Memory; } 1610b57cec5SDimitry Andric 162*5ffd83dbSDimitry Andric bool isRegisterLocation() const { return LocationKind == Register; } 1630b57cec5SDimitry Andric 164*5ffd83dbSDimitry Andric bool isImplicitLocation() const { return LocationKind == Implicit; } 1650b57cec5SDimitry Andric 166*5ffd83dbSDimitry Andric bool isEntryValue() const { return LocationFlags & EntryValue; } 167*5ffd83dbSDimitry Andric 168*5ffd83dbSDimitry Andric bool isIndirect() const { return LocationFlags & Indirect; } 169*5ffd83dbSDimitry Andric 170*5ffd83dbSDimitry Andric bool isParameterValue() { return LocationFlags & CallSiteParamValue; } 1718bcb0991SDimitry Andric 1720b57cec5SDimitry Andric Optional<uint8_t> TagOffset; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric protected: 1750b57cec5SDimitry Andric /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed 1760b57cec5SDimitry Andric /// to represent a subregister. 1770b57cec5SDimitry Andric void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { 1780b57cec5SDimitry Andric assert(SizeInBits < 65536 && OffsetInBits < 65536); 1790b57cec5SDimitry Andric SubRegisterSizeInBits = SizeInBits; 1800b57cec5SDimitry Andric SubRegisterOffsetInBits = OffsetInBits; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// Add masking operations to stencil out a subregister. 1840b57cec5SDimitry Andric void maskSubRegister(); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric /// Output a dwarf operand and an optional assembler comment. 1870b57cec5SDimitry Andric virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric /// Emit a raw signed value. 1900b57cec5SDimitry Andric virtual void emitSigned(int64_t Value) = 0; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric /// Emit a raw unsigned value. 1930b57cec5SDimitry Andric virtual void emitUnsigned(uint64_t Value) = 0; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric virtual void emitData1(uint8_t Value) = 0; 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric virtual void emitBaseTypeRef(uint64_t Idx) = 0; 1980b57cec5SDimitry Andric 1998bcb0991SDimitry Andric /// Start emitting data to the temporary buffer. The data stored in the 2008bcb0991SDimitry Andric /// temporary buffer can be committed to the main output using 2018bcb0991SDimitry Andric /// commitTemporaryBuffer(). 2028bcb0991SDimitry Andric virtual void enableTemporaryBuffer() = 0; 2038bcb0991SDimitry Andric 2048bcb0991SDimitry Andric /// Disable emission to the temporary buffer. This does not commit data 2058bcb0991SDimitry Andric /// in the temporary buffer to the main output. 2068bcb0991SDimitry Andric virtual void disableTemporaryBuffer() = 0; 2078bcb0991SDimitry Andric 2088bcb0991SDimitry Andric /// Return the emitted size, in number of bytes, for the data stored in the 2098bcb0991SDimitry Andric /// temporary buffer. 2108bcb0991SDimitry Andric virtual unsigned getTemporaryBufferSize() = 0; 2118bcb0991SDimitry Andric 2128bcb0991SDimitry Andric /// Commit the data stored in the temporary buffer to the main output. 2138bcb0991SDimitry Andric virtual void commitTemporaryBuffer() = 0; 2148bcb0991SDimitry Andric 2150b57cec5SDimitry Andric /// Emit a normalized unsigned constant. 2160b57cec5SDimitry Andric void emitConstu(uint64_t Value); 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric /// Return whether the given machine register is the frame register in the 2190b57cec5SDimitry Andric /// current function. 220*5ffd83dbSDimitry Andric virtual bool isFrameRegister(const TargetRegisterInfo &TRI, 221*5ffd83dbSDimitry Andric unsigned MachineReg) = 0; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF 2240b57cec5SDimitry Andric /// register location description. 2250b57cec5SDimitry Andric void addReg(int DwarfReg, const char *Comment = nullptr); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric /// Emit a DW_OP_breg operation. 2280b57cec5SDimitry Andric void addBReg(int DwarfReg, int Offset); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric /// Emit DW_OP_fbreg <Offset>. 2310b57cec5SDimitry Andric void addFBReg(int Offset); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric /// Emit a partial DWARF register operation. 2340b57cec5SDimitry Andric /// 2350b57cec5SDimitry Andric /// \param MachineReg The register number. 2360b57cec5SDimitry Andric /// \param MaxSize If the register must be composed from 2370b57cec5SDimitry Andric /// sub-registers this is an upper bound 2380b57cec5SDimitry Andric /// for how many bits the emitted DW_OP_piece 2390b57cec5SDimitry Andric /// may cover. 2400b57cec5SDimitry Andric /// 2410b57cec5SDimitry Andric /// If size and offset is zero an operation for the entire register is 2420b57cec5SDimitry Andric /// emitted: Some targets do not provide a DWARF register number for every 2430b57cec5SDimitry Andric /// register. If this is the case, this function will attempt to emit a DWARF 2440b57cec5SDimitry Andric /// register by emitting a fragment of a super-register or by piecing together 2450b57cec5SDimitry Andric /// multiple subregisters that alias the register. 2460b57cec5SDimitry Andric /// 2470b57cec5SDimitry Andric /// \return false if no DWARF register exists for MachineReg. 2480b57cec5SDimitry Andric bool addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg, 2490b57cec5SDimitry Andric unsigned MaxSize = ~1U); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. 2520b57cec5SDimitry Andric /// \param OffsetInBits This is an optional offset into the location that 2530b57cec5SDimitry Andric /// is at the top of the DWARF stack. 2540b57cec5SDimitry Andric void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric /// Emit a shift-right dwarf operation. 2570b57cec5SDimitry Andric void addShr(unsigned ShiftBy); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric /// Emit a bitwise and dwarf operation. 2600b57cec5SDimitry Andric void addAnd(unsigned Mask); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric /// Emit a DW_OP_stack_value, if supported. 2630b57cec5SDimitry Andric /// 2640b57cec5SDimitry Andric /// The proper way to describe a constant value is DW_OP_constu <const>, 2650b57cec5SDimitry Andric /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available 2660b57cec5SDimitry Andric /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for 2670b57cec5SDimitry Andric /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const 2680b57cec5SDimitry Andric /// <const> actually describes a value at a constant address, not a constant 2690b57cec5SDimitry Andric /// value. However, in the past there was no better way to describe a 2700b57cec5SDimitry Andric /// constant value, so the producers and consumers started to rely on 2710b57cec5SDimitry Andric /// heuristics to disambiguate the value vs. location status of the 2720b57cec5SDimitry Andric /// expression. See PR21176 for more details. 2730b57cec5SDimitry Andric void addStackValue(); 2740b57cec5SDimitry Andric 2758bcb0991SDimitry Andric /// Finalize an entry value by emitting its size operand, and committing the 2768bcb0991SDimitry Andric /// DWARF block which has been emitted to the temporary buffer. 2778bcb0991SDimitry Andric void finalizeEntryValue(); 2788bcb0991SDimitry Andric 279*5ffd83dbSDimitry Andric /// Cancel the emission of an entry value. 280*5ffd83dbSDimitry Andric void cancelEntryValue(); 281*5ffd83dbSDimitry Andric 2820b57cec5SDimitry Andric ~DwarfExpression() = default; 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric public: 2850b57cec5SDimitry Andric DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) 2860b57cec5SDimitry Andric : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), 2870b57cec5SDimitry Andric LocationKind(Unknown), LocationFlags(Unknown), 2880b57cec5SDimitry Andric DwarfVersion(DwarfVersion) {} 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric /// This needs to be called last to commit any pending changes. 2910b57cec5SDimitry Andric void finalize(); 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric /// Emit a signed constant. 2940b57cec5SDimitry Andric void addSignedConstant(int64_t Value); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric /// Emit an unsigned constant. 2970b57cec5SDimitry Andric void addUnsignedConstant(uint64_t Value); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric /// Emit an unsigned constant. 3000b57cec5SDimitry Andric void addUnsignedConstant(const APInt &Value); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric /// Lock this down to become a memory location description. 3030b57cec5SDimitry Andric void setMemoryLocationKind() { 3040b57cec5SDimitry Andric assert(isUnknownLocation()); 3050b57cec5SDimitry Andric LocationKind = Memory; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric /// Lock this down to become an entry value location. 309*5ffd83dbSDimitry Andric void setEntryValueFlags(const MachineLocation &Loc); 3100b57cec5SDimitry Andric 3118bcb0991SDimitry Andric /// Lock this down to become a call site parameter location. 312*5ffd83dbSDimitry Andric void setCallSiteParamValueFlag() { LocationFlags |= CallSiteParamValue; } 3138bcb0991SDimitry Andric 3140b57cec5SDimitry Andric /// Emit a machine register location. As an optimization this may also consume 3150b57cec5SDimitry Andric /// the prefix of a DwarfExpression if a more efficient representation for 3160b57cec5SDimitry Andric /// combining the register location and the first operation exists. 3170b57cec5SDimitry Andric /// 3180b57cec5SDimitry Andric /// \param FragmentOffsetInBits If this is one fragment out of a 3190b57cec5SDimitry Andric /// fragmented 3200b57cec5SDimitry Andric /// location, this is the offset of the 3210b57cec5SDimitry Andric /// fragment inside the entire variable. 3220b57cec5SDimitry Andric /// \return false if no DWARF register exists 3230b57cec5SDimitry Andric /// for MachineReg. 3240b57cec5SDimitry Andric bool addMachineRegExpression(const TargetRegisterInfo &TRI, 3250b57cec5SDimitry Andric DIExpressionCursor &Expr, unsigned MachineReg, 3260b57cec5SDimitry Andric unsigned FragmentOffsetInBits = 0); 3270b57cec5SDimitry Andric 3288bcb0991SDimitry Andric /// Begin emission of an entry value dwarf operation. The entry value's 3298bcb0991SDimitry Andric /// first operand is the size of the DWARF block (its second operand), 3308bcb0991SDimitry Andric /// which needs to be calculated at time of emission, so we don't emit 3318bcb0991SDimitry Andric /// any operands here. 3328bcb0991SDimitry Andric void beginEntryValueExpression(DIExpressionCursor &ExprCursor); 3330b57cec5SDimitry Andric 334*5ffd83dbSDimitry Andric /// Return the index of a base type with the given properties and 335*5ffd83dbSDimitry Andric /// create one if necessary. 336*5ffd83dbSDimitry Andric unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding); 337*5ffd83dbSDimitry Andric 3380b57cec5SDimitry Andric /// Emit all remaining operations in the DIExpressionCursor. 3390b57cec5SDimitry Andric /// 3400b57cec5SDimitry Andric /// \param FragmentOffsetInBits If this is one fragment out of multiple 3410b57cec5SDimitry Andric /// locations, this is the offset of the 3420b57cec5SDimitry Andric /// fragment inside the entire variable. 3430b57cec5SDimitry Andric void addExpression(DIExpressionCursor &&Expr, 3440b57cec5SDimitry Andric unsigned FragmentOffsetInBits = 0); 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to 3470b57cec5SDimitry Andric /// the fragment described by \c Expr. 3480b57cec5SDimitry Andric void addFragmentOffset(const DIExpression *Expr); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric void emitLegacySExt(unsigned FromBits); 3510b57cec5SDimitry Andric void emitLegacyZExt(unsigned FromBits); 352480093f4SDimitry Andric 353480093f4SDimitry Andric /// Emit location information expressed via WebAssembly location + offset 354480093f4SDimitry Andric /// The Index is an identifier for locals, globals or operand stack. 355*5ffd83dbSDimitry Andric void addWasmLocation(unsigned Index, uint64_t Offset); 3560b57cec5SDimitry Andric }; 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries. 3590b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression { 3608bcb0991SDimitry Andric 3618bcb0991SDimitry Andric struct TempBuffer { 3628bcb0991SDimitry Andric SmallString<32> Bytes; 3638bcb0991SDimitry Andric std::vector<std::string> Comments; 3648bcb0991SDimitry Andric BufferByteStreamer BS; 3658bcb0991SDimitry Andric 3668bcb0991SDimitry Andric TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {} 3678bcb0991SDimitry Andric }; 3688bcb0991SDimitry Andric 3698bcb0991SDimitry Andric std::unique_ptr<TempBuffer> TmpBuf; 3708bcb0991SDimitry Andric BufferByteStreamer &OutBS; 3718bcb0991SDimitry Andric bool IsBuffering = false; 3728bcb0991SDimitry Andric 3738bcb0991SDimitry Andric /// Return the byte streamer that currently is being emitted to. 3748bcb0991SDimitry Andric ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 3770b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 3780b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 3790b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 3800b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 3818bcb0991SDimitry Andric 3828bcb0991SDimitry Andric void enableTemporaryBuffer() override; 3838bcb0991SDimitry Andric void disableTemporaryBuffer() override; 3848bcb0991SDimitry Andric unsigned getTemporaryBufferSize() override; 3858bcb0991SDimitry Andric void commitTemporaryBuffer() override; 3868bcb0991SDimitry Andric 3870b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 3880b57cec5SDimitry Andric unsigned MachineReg) override; 389*5ffd83dbSDimitry Andric 3900b57cec5SDimitry Andric public: 3918bcb0991SDimitry Andric DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, 3928bcb0991SDimitry Andric DwarfCompileUnit &CU) 3938bcb0991SDimitry Andric : DwarfExpression(DwarfVersion, CU), OutBS(BS) {} 3940b57cec5SDimitry Andric }; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location. 3970b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression { 3980b57cec5SDimitry Andric const AsmPrinter &AP; 3998bcb0991SDimitry Andric DIELoc &OutDIE; 4008bcb0991SDimitry Andric DIELoc TmpDIE; 4018bcb0991SDimitry Andric bool IsBuffering = false; 4028bcb0991SDimitry Andric 4038bcb0991SDimitry Andric /// Return the DIE that currently is being emitted to. 4048bcb0991SDimitry Andric DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 4070b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 4080b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 4090b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 4100b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 4118bcb0991SDimitry Andric 4128bcb0991SDimitry Andric void enableTemporaryBuffer() override; 4138bcb0991SDimitry Andric void disableTemporaryBuffer() override; 4148bcb0991SDimitry Andric unsigned getTemporaryBufferSize() override; 4158bcb0991SDimitry Andric void commitTemporaryBuffer() override; 4168bcb0991SDimitry Andric 4170b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 4180b57cec5SDimitry Andric unsigned MachineReg) override; 419*5ffd83dbSDimitry Andric 4200b57cec5SDimitry Andric public: 4210b57cec5SDimitry Andric DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric DIELoc *finalize() { 4240b57cec5SDimitry Andric DwarfExpression::finalize(); 4258bcb0991SDimitry Andric return &OutDIE; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric }; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric } // end namespace llvm 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 432