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> 23bdd1243dSDimitry 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 /// 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: DIExpressionCursor(const DIExpression * Expr)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 DIExpressionCursor(ArrayRef<uint64_t> Expr)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. take()55bdd1243dSDimitry Andric std::optional<DIExpression::ExprOperand> take() { 560b57cec5SDimitry Andric if (Start == End) 57bdd1243dSDimitry Andric return std::nullopt; 580b57cec5SDimitry Andric return *(Start++); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// Consume N operations. consume(unsigned N)620b57cec5SDimitry Andric void consume(unsigned N) { std::advance(Start, N); } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric /// Return the current operation. peek()65bdd1243dSDimitry Andric std::optional<DIExpression::ExprOperand> peek() const { 660b57cec5SDimitry Andric if (Start == End) 67bdd1243dSDimitry Andric return std::nullopt; 680b57cec5SDimitry Andric return *(Start); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// Return the next operation. peekNext()72bdd1243dSDimitry Andric std::optional<DIExpression::ExprOperand> peekNext() const { 730b57cec5SDimitry Andric if (Start == End) 74bdd1243dSDimitry Andric return std::nullopt; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric auto Next = Start.getNext(); 770b57cec5SDimitry Andric if (Next == End) 78bdd1243dSDimitry Andric return std::nullopt; 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 begin()860b57cec5SDimitry Andric DIExpression::expr_op_iterator begin() const { return Start; } end()870b57cec5SDimitry Andric DIExpression::expr_op_iterator end() const { return End; } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric /// Retrieve the fragment information, if any. getFragmentInfo()90bdd1243dSDimitry Andric std::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. 988bcb0991SDimitry Andric /// 998bcb0991SDimitry Andric /// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the size 1008bcb0991SDimitry Andric /// of a succeeding DWARF block before the latter is emitted to the output. 1018bcb0991SDimitry Andric /// To handle such cases, data can conditionally be emitted to a temporary 1028bcb0991SDimitry Andric /// buffer, which can later on be committed to the main output. The size of the 1038bcb0991SDimitry Andric /// temporary buffer is queryable, allowing for the size of the data to be 1048bcb0991SDimitry 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; 1105ffd83dbSDimitry Andric unsigned SubRegSize; 1110b57cec5SDimitry Andric const char *Comment; 1125ffd83dbSDimitry Andric 1135ffd83dbSDimitry Andric /// Create a full register, no extra DW_OP_piece operators necessary. createRegisterRegister1145ffd83dbSDimitry Andric static Register createRegister(int RegNo, const char *Comment) { 1155ffd83dbSDimitry Andric return {RegNo, 0, Comment}; 1165ffd83dbSDimitry Andric } 1175ffd83dbSDimitry Andric 1185ffd83dbSDimitry Andric /// Create a subregister that needs a DW_OP_piece operator with SizeInBits. createSubRegisterRegister1195ffd83dbSDimitry Andric static Register createSubRegister(int RegNo, unsigned SizeInBits, 1205ffd83dbSDimitry Andric const char *Comment) { 1215ffd83dbSDimitry Andric return {RegNo, SizeInBits, Comment}; 1225ffd83dbSDimitry Andric } 1235ffd83dbSDimitry Andric isSubRegisterRegister1245ffd83dbSDimitry Andric bool isSubRegister() const { return SubRegSize; } 1250b57cec5SDimitry Andric }; 1260b57cec5SDimitry Andric 1278bcb0991SDimitry Andric /// Whether we are currently emitting an entry value operation. 1288bcb0991SDimitry Andric bool IsEmittingEntryValue = false; 1298bcb0991SDimitry Andric 1300b57cec5SDimitry Andric DwarfCompileUnit &CU; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// The register location, if any. 1330b57cec5SDimitry Andric SmallVector<Register, 2> DwarfRegs; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric /// Current Fragment Offset in Bits. 1360b57cec5SDimitry Andric uint64_t OffsetInBits = 0; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. 1390b57cec5SDimitry Andric unsigned SubRegisterSizeInBits : 16; 1400b57cec5SDimitry Andric unsigned SubRegisterOffsetInBits : 16; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// The kind of location description being produced. 1430b57cec5SDimitry Andric enum { Unknown = 0, Register, Memory, Implicit }; 1440b57cec5SDimitry Andric 1455ffd83dbSDimitry Andric /// Additional location flags which may be combined with any location kind. 1465ffd83dbSDimitry Andric /// Currently, entry values are not supported for the Memory location kind. 1475ffd83dbSDimitry Andric enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 }; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric unsigned LocationKind : 3; 150fe6060f1SDimitry Andric unsigned SavedLocationKind : 3; 1515ffd83dbSDimitry Andric unsigned LocationFlags : 3; 1520b57cec5SDimitry Andric unsigned DwarfVersion : 4; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric public: 1555ffd83dbSDimitry Andric /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe. 1565ffd83dbSDimitry Andric void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr); 1570b57cec5SDimitry Andric isUnknownLocation()1585ffd83dbSDimitry Andric bool isUnknownLocation() const { return LocationKind == Unknown; } 1590b57cec5SDimitry Andric isMemoryLocation()1605ffd83dbSDimitry Andric bool isMemoryLocation() const { return LocationKind == Memory; } 1610b57cec5SDimitry Andric isRegisterLocation()1625ffd83dbSDimitry Andric bool isRegisterLocation() const { return LocationKind == Register; } 1630b57cec5SDimitry Andric isImplicitLocation()1645ffd83dbSDimitry Andric bool isImplicitLocation() const { return LocationKind == Implicit; } 1650b57cec5SDimitry Andric isEntryValue()1665ffd83dbSDimitry Andric bool isEntryValue() const { return LocationFlags & EntryValue; } 1675ffd83dbSDimitry Andric isIndirect()1685ffd83dbSDimitry Andric bool isIndirect() const { return LocationFlags & Indirect; } 1695ffd83dbSDimitry Andric isParameterValue()1705ffd83dbSDimitry Andric bool isParameterValue() { return LocationFlags & CallSiteParamValue; } 1718bcb0991SDimitry Andric 172bdd1243dSDimitry Andric std::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. setSubRegisterPiece(unsigned SizeInBits,unsigned OffsetInBits)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. 2205ffd83dbSDimitry Andric virtual bool isFrameRegister(const TargetRegisterInfo &TRI, 221e8d8bef9SDimitry Andric llvm::Register 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. 248e8d8bef9SDimitry Andric bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register 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 2795ffd83dbSDimitry Andric /// Cancel the emission of an entry value. 2805ffd83dbSDimitry Andric void cancelEntryValue(); 2815ffd83dbSDimitry Andric 2820b57cec5SDimitry Andric ~DwarfExpression() = default; 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric public: DwarfExpression(unsigned DwarfVersion,DwarfCompileUnit & CU)2850b57cec5SDimitry Andric DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) 2860b57cec5SDimitry Andric : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), 287fe6060f1SDimitry Andric LocationKind(Unknown), SavedLocationKind(Unknown), 288fe6060f1SDimitry Andric LocationFlags(Unknown), 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 302e8d8bef9SDimitry Andric /// Emit an floating point constant. 303e8d8bef9SDimitry Andric void addConstantFP(const APFloat &Value, const AsmPrinter &AP); 304e8d8bef9SDimitry Andric 3050b57cec5SDimitry Andric /// Lock this down to become a memory location description. setMemoryLocationKind()3060b57cec5SDimitry Andric void setMemoryLocationKind() { 3070b57cec5SDimitry Andric assert(isUnknownLocation()); 3080b57cec5SDimitry Andric LocationKind = Memory; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric /// Lock this down to become an entry value location. 3125ffd83dbSDimitry Andric void setEntryValueFlags(const MachineLocation &Loc); 3130b57cec5SDimitry Andric 3148bcb0991SDimitry Andric /// Lock this down to become a call site parameter location. setCallSiteParamValueFlag()3155ffd83dbSDimitry Andric void setCallSiteParamValueFlag() { LocationFlags |= CallSiteParamValue; } 3168bcb0991SDimitry Andric 3170b57cec5SDimitry Andric /// Emit a machine register location. As an optimization this may also consume 3180b57cec5SDimitry Andric /// the prefix of a DwarfExpression if a more efficient representation for 3190b57cec5SDimitry Andric /// combining the register location and the first operation exists. 3200b57cec5SDimitry Andric /// 3210b57cec5SDimitry Andric /// \param FragmentOffsetInBits If this is one fragment out of a 3220b57cec5SDimitry Andric /// fragmented 3230b57cec5SDimitry Andric /// location, this is the offset of the 3240b57cec5SDimitry Andric /// fragment inside the entire variable. 3250b57cec5SDimitry Andric /// \return false if no DWARF register exists 3260b57cec5SDimitry Andric /// for MachineReg. 3270b57cec5SDimitry Andric bool addMachineRegExpression(const TargetRegisterInfo &TRI, 328e8d8bef9SDimitry Andric DIExpressionCursor &Expr, 329e8d8bef9SDimitry Andric llvm::Register MachineReg, 3300b57cec5SDimitry Andric unsigned FragmentOffsetInBits = 0); 3310b57cec5SDimitry Andric 3328bcb0991SDimitry Andric /// Begin emission of an entry value dwarf operation. The entry value's 3338bcb0991SDimitry Andric /// first operand is the size of the DWARF block (its second operand), 3348bcb0991SDimitry Andric /// which needs to be calculated at time of emission, so we don't emit 3358bcb0991SDimitry Andric /// any operands here. 3368bcb0991SDimitry Andric void beginEntryValueExpression(DIExpressionCursor &ExprCursor); 3370b57cec5SDimitry Andric 3385ffd83dbSDimitry Andric /// Return the index of a base type with the given properties and 3395ffd83dbSDimitry Andric /// create one if necessary. 3405ffd83dbSDimitry Andric unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding); 3415ffd83dbSDimitry Andric 3429738bc28SDimitry Andric /// Emit all remaining operations in the DIExpressionCursor. The 3439738bc28SDimitry Andric /// cursor must not contain any DW_OP_LLVM_arg operations. 3449738bc28SDimitry Andric void addExpression(DIExpressionCursor &&Expr); 3459738bc28SDimitry Andric 3460b57cec5SDimitry Andric /// Emit all remaining operations in the DIExpressionCursor. 3479738bc28SDimitry Andric /// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg). 3489738bc28SDimitry Andric // 3499738bc28SDimitry Andric /// \return false if any call to (\p InsertArg) returns false. 3509738bc28SDimitry Andric bool addExpression( 3519738bc28SDimitry Andric DIExpressionCursor &&Expr, 352fe6060f1SDimitry Andric llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to 3550b57cec5SDimitry Andric /// the fragment described by \c Expr. 3560b57cec5SDimitry Andric void addFragmentOffset(const DIExpression *Expr); 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric void emitLegacySExt(unsigned FromBits); 3590b57cec5SDimitry Andric void emitLegacyZExt(unsigned FromBits); 360480093f4SDimitry Andric 361480093f4SDimitry Andric /// Emit location information expressed via WebAssembly location + offset 362480093f4SDimitry Andric /// The Index is an identifier for locals, globals or operand stack. 3635ffd83dbSDimitry Andric void addWasmLocation(unsigned Index, uint64_t Offset); 3640b57cec5SDimitry Andric }; 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries. 3670b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression { 3688bcb0991SDimitry Andric 3698bcb0991SDimitry Andric struct TempBuffer { 3708bcb0991SDimitry Andric SmallString<32> Bytes; 3718bcb0991SDimitry Andric std::vector<std::string> Comments; 3728bcb0991SDimitry Andric BufferByteStreamer BS; 3738bcb0991SDimitry Andric TempBufferTempBuffer3748bcb0991SDimitry Andric TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {} 3758bcb0991SDimitry Andric }; 3768bcb0991SDimitry Andric 3778bcb0991SDimitry Andric std::unique_ptr<TempBuffer> TmpBuf; 3788bcb0991SDimitry Andric BufferByteStreamer &OutBS; 3798bcb0991SDimitry Andric bool IsBuffering = false; 3808bcb0991SDimitry Andric 3818bcb0991SDimitry Andric /// Return the byte streamer that currently is being emitted to. getActiveStreamer()3828bcb0991SDimitry Andric ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 3850b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 3860b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 3870b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 3880b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 3898bcb0991SDimitry Andric 3908bcb0991SDimitry Andric void enableTemporaryBuffer() override; 3918bcb0991SDimitry Andric void disableTemporaryBuffer() override; 3928bcb0991SDimitry Andric unsigned getTemporaryBufferSize() override; 3938bcb0991SDimitry Andric void commitTemporaryBuffer() override; 3948bcb0991SDimitry Andric 3950b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 396e8d8bef9SDimitry Andric llvm::Register MachineReg) override; 3975ffd83dbSDimitry Andric 3980b57cec5SDimitry Andric public: DebugLocDwarfExpression(unsigned DwarfVersion,BufferByteStreamer & BS,DwarfCompileUnit & CU)3998bcb0991SDimitry Andric DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, 4008bcb0991SDimitry Andric DwarfCompileUnit &CU) 4018bcb0991SDimitry Andric : DwarfExpression(DwarfVersion, CU), OutBS(BS) {} 4020b57cec5SDimitry Andric }; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location. 4050b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression { 4060b57cec5SDimitry Andric const AsmPrinter &AP; 4078bcb0991SDimitry Andric DIELoc &OutDIE; 4088bcb0991SDimitry Andric DIELoc TmpDIE; 4098bcb0991SDimitry Andric bool IsBuffering = false; 4108bcb0991SDimitry Andric 4118bcb0991SDimitry Andric /// Return the DIE that currently is being emitted to. getActiveDIE()4128bcb0991SDimitry Andric DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 4150b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 4160b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 4170b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 4180b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 4198bcb0991SDimitry Andric 4208bcb0991SDimitry Andric void enableTemporaryBuffer() override; 4218bcb0991SDimitry Andric void disableTemporaryBuffer() override; 4228bcb0991SDimitry Andric unsigned getTemporaryBufferSize() override; 4238bcb0991SDimitry Andric void commitTemporaryBuffer() override; 4248bcb0991SDimitry Andric 4250b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 426e8d8bef9SDimitry Andric llvm::Register MachineReg) override; 4275ffd83dbSDimitry Andric 4280b57cec5SDimitry Andric public: 4290b57cec5SDimitry Andric DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); 4300b57cec5SDimitry Andric finalize()4310b57cec5SDimitry Andric DIELoc *finalize() { 4320b57cec5SDimitry Andric DwarfExpression::finalize(); 4338bcb0991SDimitry Andric return &OutDIE; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric }; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric } // end namespace llvm 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 440