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; 335ffd83dbSDimitry 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; 1115ffd83dbSDimitry Andric unsigned SubRegSize; 1120b57cec5SDimitry Andric const char *Comment; 1135ffd83dbSDimitry Andric 1145ffd83dbSDimitry Andric /// Create a full register, no extra DW_OP_piece operators necessary. 1155ffd83dbSDimitry Andric static Register createRegister(int RegNo, const char *Comment) { 1165ffd83dbSDimitry Andric return {RegNo, 0, Comment}; 1175ffd83dbSDimitry Andric } 1185ffd83dbSDimitry Andric 1195ffd83dbSDimitry Andric /// Create a subregister that needs a DW_OP_piece operator with SizeInBits. 1205ffd83dbSDimitry Andric static Register createSubRegister(int RegNo, unsigned SizeInBits, 1215ffd83dbSDimitry Andric const char *Comment) { 1225ffd83dbSDimitry Andric return {RegNo, SizeInBits, Comment}; 1235ffd83dbSDimitry Andric } 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry 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 1465ffd83dbSDimitry Andric /// Additional location flags which may be combined with any location kind. 1475ffd83dbSDimitry Andric /// Currently, entry values are not supported for the Memory location kind. 1485ffd83dbSDimitry Andric enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 }; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric unsigned LocationKind : 3; 151fe6060f1SDimitry Andric unsigned SavedLocationKind : 3; 1525ffd83dbSDimitry Andric unsigned LocationFlags : 3; 1530b57cec5SDimitry Andric unsigned DwarfVersion : 4; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric public: 1565ffd83dbSDimitry Andric /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe. 1575ffd83dbSDimitry Andric void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr); 1580b57cec5SDimitry Andric 1595ffd83dbSDimitry Andric bool isUnknownLocation() const { return LocationKind == Unknown; } 1600b57cec5SDimitry Andric 1615ffd83dbSDimitry Andric bool isMemoryLocation() const { return LocationKind == Memory; } 1620b57cec5SDimitry Andric 1635ffd83dbSDimitry Andric bool isRegisterLocation() const { return LocationKind == Register; } 1640b57cec5SDimitry Andric 1655ffd83dbSDimitry Andric bool isImplicitLocation() const { return LocationKind == Implicit; } 1660b57cec5SDimitry Andric 1675ffd83dbSDimitry Andric bool isEntryValue() const { return LocationFlags & EntryValue; } 1685ffd83dbSDimitry Andric 1695ffd83dbSDimitry Andric bool isIndirect() const { return LocationFlags & Indirect; } 1705ffd83dbSDimitry Andric 1715ffd83dbSDimitry Andric bool isParameterValue() { return LocationFlags & CallSiteParamValue; } 1728bcb0991SDimitry Andric 1730b57cec5SDimitry Andric Optional<uint8_t> TagOffset; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric protected: 1760b57cec5SDimitry Andric /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed 1770b57cec5SDimitry Andric /// to represent a subregister. 1780b57cec5SDimitry Andric void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { 1790b57cec5SDimitry Andric assert(SizeInBits < 65536 && OffsetInBits < 65536); 1800b57cec5SDimitry Andric SubRegisterSizeInBits = SizeInBits; 1810b57cec5SDimitry Andric SubRegisterOffsetInBits = OffsetInBits; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric /// Add masking operations to stencil out a subregister. 1850b57cec5SDimitry Andric void maskSubRegister(); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric /// Output a dwarf operand and an optional assembler comment. 1880b57cec5SDimitry Andric virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric /// Emit a raw signed value. 1910b57cec5SDimitry Andric virtual void emitSigned(int64_t Value) = 0; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric /// Emit a raw unsigned value. 1940b57cec5SDimitry Andric virtual void emitUnsigned(uint64_t Value) = 0; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric virtual void emitData1(uint8_t Value) = 0; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric virtual void emitBaseTypeRef(uint64_t Idx) = 0; 1990b57cec5SDimitry Andric 2008bcb0991SDimitry Andric /// Start emitting data to the temporary buffer. The data stored in the 2018bcb0991SDimitry Andric /// temporary buffer can be committed to the main output using 2028bcb0991SDimitry Andric /// commitTemporaryBuffer(). 2038bcb0991SDimitry Andric virtual void enableTemporaryBuffer() = 0; 2048bcb0991SDimitry Andric 2058bcb0991SDimitry Andric /// Disable emission to the temporary buffer. This does not commit data 2068bcb0991SDimitry Andric /// in the temporary buffer to the main output. 2078bcb0991SDimitry Andric virtual void disableTemporaryBuffer() = 0; 2088bcb0991SDimitry Andric 2098bcb0991SDimitry Andric /// Return the emitted size, in number of bytes, for the data stored in the 2108bcb0991SDimitry Andric /// temporary buffer. 2118bcb0991SDimitry Andric virtual unsigned getTemporaryBufferSize() = 0; 2128bcb0991SDimitry Andric 2138bcb0991SDimitry Andric /// Commit the data stored in the temporary buffer to the main output. 2148bcb0991SDimitry Andric virtual void commitTemporaryBuffer() = 0; 2158bcb0991SDimitry Andric 2160b57cec5SDimitry Andric /// Emit a normalized unsigned constant. 2170b57cec5SDimitry Andric void emitConstu(uint64_t Value); 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric /// Return whether the given machine register is the frame register in the 2200b57cec5SDimitry Andric /// current function. 2215ffd83dbSDimitry Andric virtual bool isFrameRegister(const TargetRegisterInfo &TRI, 222e8d8bef9SDimitry Andric llvm::Register MachineReg) = 0; 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF 2250b57cec5SDimitry Andric /// register location description. 2260b57cec5SDimitry Andric void addReg(int DwarfReg, const char *Comment = nullptr); 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric /// Emit a DW_OP_breg operation. 2290b57cec5SDimitry Andric void addBReg(int DwarfReg, int Offset); 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric /// Emit DW_OP_fbreg <Offset>. 2320b57cec5SDimitry Andric void addFBReg(int Offset); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric /// Emit a partial DWARF register operation. 2350b57cec5SDimitry Andric /// 2360b57cec5SDimitry Andric /// \param MachineReg The register number. 2370b57cec5SDimitry Andric /// \param MaxSize If the register must be composed from 2380b57cec5SDimitry Andric /// sub-registers this is an upper bound 2390b57cec5SDimitry Andric /// for how many bits the emitted DW_OP_piece 2400b57cec5SDimitry Andric /// may cover. 2410b57cec5SDimitry Andric /// 2420b57cec5SDimitry Andric /// If size and offset is zero an operation for the entire register is 2430b57cec5SDimitry Andric /// emitted: Some targets do not provide a DWARF register number for every 2440b57cec5SDimitry Andric /// register. If this is the case, this function will attempt to emit a DWARF 2450b57cec5SDimitry Andric /// register by emitting a fragment of a super-register or by piecing together 2460b57cec5SDimitry Andric /// multiple subregisters that alias the register. 2470b57cec5SDimitry Andric /// 2480b57cec5SDimitry Andric /// \return false if no DWARF register exists for MachineReg. 249e8d8bef9SDimitry Andric bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register MachineReg, 2500b57cec5SDimitry Andric unsigned MaxSize = ~1U); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. 2530b57cec5SDimitry Andric /// \param OffsetInBits This is an optional offset into the location that 2540b57cec5SDimitry Andric /// is at the top of the DWARF stack. 2550b57cec5SDimitry Andric void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric /// Emit a shift-right dwarf operation. 2580b57cec5SDimitry Andric void addShr(unsigned ShiftBy); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric /// Emit a bitwise and dwarf operation. 2610b57cec5SDimitry Andric void addAnd(unsigned Mask); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric /// Emit a DW_OP_stack_value, if supported. 2640b57cec5SDimitry Andric /// 2650b57cec5SDimitry Andric /// The proper way to describe a constant value is DW_OP_constu <const>, 2660b57cec5SDimitry Andric /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available 2670b57cec5SDimitry Andric /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for 2680b57cec5SDimitry Andric /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const 2690b57cec5SDimitry Andric /// <const> actually describes a value at a constant address, not a constant 2700b57cec5SDimitry Andric /// value. However, in the past there was no better way to describe a 2710b57cec5SDimitry Andric /// constant value, so the producers and consumers started to rely on 2720b57cec5SDimitry Andric /// heuristics to disambiguate the value vs. location status of the 2730b57cec5SDimitry Andric /// expression. See PR21176 for more details. 2740b57cec5SDimitry Andric void addStackValue(); 2750b57cec5SDimitry Andric 2768bcb0991SDimitry Andric /// Finalize an entry value by emitting its size operand, and committing the 2778bcb0991SDimitry Andric /// DWARF block which has been emitted to the temporary buffer. 2788bcb0991SDimitry Andric void finalizeEntryValue(); 2798bcb0991SDimitry Andric 2805ffd83dbSDimitry Andric /// Cancel the emission of an entry value. 2815ffd83dbSDimitry Andric void cancelEntryValue(); 2825ffd83dbSDimitry Andric 2830b57cec5SDimitry Andric ~DwarfExpression() = default; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric public: 2860b57cec5SDimitry Andric DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) 2870b57cec5SDimitry Andric : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), 288fe6060f1SDimitry Andric LocationKind(Unknown), SavedLocationKind(Unknown), 289fe6060f1SDimitry Andric LocationFlags(Unknown), DwarfVersion(DwarfVersion) {} 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric /// This needs to be called last to commit any pending changes. 2920b57cec5SDimitry Andric void finalize(); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric /// Emit a signed constant. 2950b57cec5SDimitry Andric void addSignedConstant(int64_t Value); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric /// Emit an unsigned constant. 2980b57cec5SDimitry Andric void addUnsignedConstant(uint64_t Value); 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric /// Emit an unsigned constant. 3010b57cec5SDimitry Andric void addUnsignedConstant(const APInt &Value); 3020b57cec5SDimitry Andric 303e8d8bef9SDimitry Andric /// Emit an floating point constant. 304e8d8bef9SDimitry Andric void addConstantFP(const APFloat &Value, const AsmPrinter &AP); 305e8d8bef9SDimitry Andric 3060b57cec5SDimitry Andric /// Lock this down to become a memory location description. 3070b57cec5SDimitry Andric void setMemoryLocationKind() { 3080b57cec5SDimitry Andric assert(isUnknownLocation()); 3090b57cec5SDimitry Andric LocationKind = Memory; 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric /// Lock this down to become an entry value location. 3135ffd83dbSDimitry Andric void setEntryValueFlags(const MachineLocation &Loc); 3140b57cec5SDimitry Andric 3158bcb0991SDimitry Andric /// Lock this down to become a call site parameter location. 3165ffd83dbSDimitry Andric void setCallSiteParamValueFlag() { LocationFlags |= CallSiteParamValue; } 3178bcb0991SDimitry Andric 3180b57cec5SDimitry Andric /// Emit a machine register location. As an optimization this may also consume 3190b57cec5SDimitry Andric /// the prefix of a DwarfExpression if a more efficient representation for 3200b57cec5SDimitry Andric /// combining the register location and the first operation exists. 3210b57cec5SDimitry Andric /// 3220b57cec5SDimitry Andric /// \param FragmentOffsetInBits If this is one fragment out of a 3230b57cec5SDimitry Andric /// fragmented 3240b57cec5SDimitry Andric /// location, this is the offset of the 3250b57cec5SDimitry Andric /// fragment inside the entire variable. 3260b57cec5SDimitry Andric /// \return false if no DWARF register exists 3270b57cec5SDimitry Andric /// for MachineReg. 3280b57cec5SDimitry Andric bool addMachineRegExpression(const TargetRegisterInfo &TRI, 329e8d8bef9SDimitry Andric DIExpressionCursor &Expr, 330e8d8bef9SDimitry Andric llvm::Register MachineReg, 3310b57cec5SDimitry Andric unsigned FragmentOffsetInBits = 0); 3320b57cec5SDimitry Andric 3338bcb0991SDimitry Andric /// Begin emission of an entry value dwarf operation. The entry value's 3348bcb0991SDimitry Andric /// first operand is the size of the DWARF block (its second operand), 3358bcb0991SDimitry Andric /// which needs to be calculated at time of emission, so we don't emit 3368bcb0991SDimitry Andric /// any operands here. 3378bcb0991SDimitry Andric void beginEntryValueExpression(DIExpressionCursor &ExprCursor); 3380b57cec5SDimitry Andric 3395ffd83dbSDimitry Andric /// Return the index of a base type with the given properties and 3405ffd83dbSDimitry Andric /// create one if necessary. 3415ffd83dbSDimitry Andric unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding); 3425ffd83dbSDimitry Andric 343*9738bc28SDimitry Andric /// Emit all remaining operations in the DIExpressionCursor. The 344*9738bc28SDimitry Andric /// cursor must not contain any DW_OP_LLVM_arg operations. 345*9738bc28SDimitry Andric void addExpression(DIExpressionCursor &&Expr); 346*9738bc28SDimitry Andric 3470b57cec5SDimitry Andric /// Emit all remaining operations in the DIExpressionCursor. 348*9738bc28SDimitry Andric /// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg). 349*9738bc28SDimitry Andric // 350*9738bc28SDimitry Andric /// \return false if any call to (\p InsertArg) returns false. 351*9738bc28SDimitry Andric bool addExpression( 352*9738bc28SDimitry Andric DIExpressionCursor &&Expr, 353fe6060f1SDimitry Andric llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg); 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to 3560b57cec5SDimitry Andric /// the fragment described by \c Expr. 3570b57cec5SDimitry Andric void addFragmentOffset(const DIExpression *Expr); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric void emitLegacySExt(unsigned FromBits); 3600b57cec5SDimitry Andric void emitLegacyZExt(unsigned FromBits); 361480093f4SDimitry Andric 362480093f4SDimitry Andric /// Emit location information expressed via WebAssembly location + offset 363480093f4SDimitry Andric /// The Index is an identifier for locals, globals or operand stack. 3645ffd83dbSDimitry Andric void addWasmLocation(unsigned Index, uint64_t Offset); 3650b57cec5SDimitry Andric }; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries. 3680b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression { 3698bcb0991SDimitry Andric 3708bcb0991SDimitry Andric struct TempBuffer { 3718bcb0991SDimitry Andric SmallString<32> Bytes; 3728bcb0991SDimitry Andric std::vector<std::string> Comments; 3738bcb0991SDimitry Andric BufferByteStreamer BS; 3748bcb0991SDimitry Andric 3758bcb0991SDimitry Andric TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {} 3768bcb0991SDimitry Andric }; 3778bcb0991SDimitry Andric 3788bcb0991SDimitry Andric std::unique_ptr<TempBuffer> TmpBuf; 3798bcb0991SDimitry Andric BufferByteStreamer &OutBS; 3808bcb0991SDimitry Andric bool IsBuffering = false; 3818bcb0991SDimitry Andric 3828bcb0991SDimitry Andric /// Return the byte streamer that currently is being emitted to. 3838bcb0991SDimitry Andric ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 3860b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 3870b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 3880b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 3890b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 3908bcb0991SDimitry Andric 3918bcb0991SDimitry Andric void enableTemporaryBuffer() override; 3928bcb0991SDimitry Andric void disableTemporaryBuffer() override; 3938bcb0991SDimitry Andric unsigned getTemporaryBufferSize() override; 3948bcb0991SDimitry Andric void commitTemporaryBuffer() override; 3958bcb0991SDimitry Andric 3960b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 397e8d8bef9SDimitry Andric llvm::Register MachineReg) override; 3985ffd83dbSDimitry Andric 3990b57cec5SDimitry Andric public: 4008bcb0991SDimitry Andric DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, 4018bcb0991SDimitry Andric DwarfCompileUnit &CU) 4028bcb0991SDimitry Andric : DwarfExpression(DwarfVersion, CU), OutBS(BS) {} 4030b57cec5SDimitry Andric }; 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location. 4060b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression { 4070b57cec5SDimitry Andric const AsmPrinter &AP; 4088bcb0991SDimitry Andric DIELoc &OutDIE; 4098bcb0991SDimitry Andric DIELoc TmpDIE; 4108bcb0991SDimitry Andric bool IsBuffering = false; 4118bcb0991SDimitry Andric 4128bcb0991SDimitry Andric /// Return the DIE that currently is being emitted to. 4138bcb0991SDimitry Andric DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 4160b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 4170b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 4180b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 4190b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 4208bcb0991SDimitry Andric 4218bcb0991SDimitry Andric void enableTemporaryBuffer() override; 4228bcb0991SDimitry Andric void disableTemporaryBuffer() override; 4238bcb0991SDimitry Andric unsigned getTemporaryBufferSize() override; 4248bcb0991SDimitry Andric void commitTemporaryBuffer() override; 4258bcb0991SDimitry Andric 4260b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 427e8d8bef9SDimitry Andric llvm::Register MachineReg) override; 4285ffd83dbSDimitry Andric 4290b57cec5SDimitry Andric public: 4300b57cec5SDimitry Andric DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric DIELoc *finalize() { 4330b57cec5SDimitry Andric DwarfExpression::finalize(); 4348bcb0991SDimitry Andric return &OutDIE; 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric }; 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric } // end namespace llvm 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 441