1*0b57cec5SDimitry Andric //===- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains support for writing dwarf compile unit. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 14*0b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/None.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 20*0b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 21*0b57cec5SDimitry Andric #include <cassert> 22*0b57cec5SDimitry Andric #include <cstdint> 23*0b57cec5SDimitry Andric #include <iterator> 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric namespace llvm { 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric class AsmPrinter; 28*0b57cec5SDimitry Andric class APInt; 29*0b57cec5SDimitry Andric class ByteStreamer; 30*0b57cec5SDimitry Andric class DwarfCompileUnit; 31*0b57cec5SDimitry Andric class DIELoc; 32*0b57cec5SDimitry Andric class TargetRegisterInfo; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric /// Holds a DIExpression and keeps track of how many operands have been consumed 35*0b57cec5SDimitry Andric /// so far. 36*0b57cec5SDimitry Andric class DIExpressionCursor { 37*0b57cec5SDimitry Andric DIExpression::expr_op_iterator Start, End; 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric public: 40*0b57cec5SDimitry Andric DIExpressionCursor(const DIExpression *Expr) { 41*0b57cec5SDimitry Andric if (!Expr) { 42*0b57cec5SDimitry Andric assert(Start == End); 43*0b57cec5SDimitry Andric return; 44*0b57cec5SDimitry Andric } 45*0b57cec5SDimitry Andric Start = Expr->expr_op_begin(); 46*0b57cec5SDimitry Andric End = Expr->expr_op_end(); 47*0b57cec5SDimitry Andric } 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric DIExpressionCursor(ArrayRef<uint64_t> Expr) 50*0b57cec5SDimitry Andric : Start(Expr.begin()), End(Expr.end()) {} 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric DIExpressionCursor(const DIExpressionCursor &) = default; 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric /// Consume one operation. 55*0b57cec5SDimitry Andric Optional<DIExpression::ExprOperand> take() { 56*0b57cec5SDimitry Andric if (Start == End) 57*0b57cec5SDimitry Andric return None; 58*0b57cec5SDimitry Andric return *(Start++); 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric /// Consume N operations. 62*0b57cec5SDimitry Andric void consume(unsigned N) { std::advance(Start, N); } 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric /// Return the current operation. 65*0b57cec5SDimitry Andric Optional<DIExpression::ExprOperand> peek() const { 66*0b57cec5SDimitry Andric if (Start == End) 67*0b57cec5SDimitry Andric return None; 68*0b57cec5SDimitry Andric return *(Start); 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric /// Return the next operation. 72*0b57cec5SDimitry Andric Optional<DIExpression::ExprOperand> peekNext() const { 73*0b57cec5SDimitry Andric if (Start == End) 74*0b57cec5SDimitry Andric return None; 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric auto Next = Start.getNext(); 77*0b57cec5SDimitry Andric if (Next == End) 78*0b57cec5SDimitry Andric return None; 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric return *Next; 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric /// Determine whether there are any operations left in this expression. 84*0b57cec5SDimitry Andric operator bool() const { return Start != End; } 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric DIExpression::expr_op_iterator begin() const { return Start; } 87*0b57cec5SDimitry Andric DIExpression::expr_op_iterator end() const { return End; } 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric /// Retrieve the fragment information, if any. 90*0b57cec5SDimitry Andric Optional<DIExpression::FragmentInfo> getFragmentInfo() const { 91*0b57cec5SDimitry Andric return DIExpression::getFragmentInfo(Start, End); 92*0b57cec5SDimitry Andric } 93*0b57cec5SDimitry Andric }; 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric /// Base class containing the logic for constructing DWARF expressions 96*0b57cec5SDimitry Andric /// independently of whether they are emitted into a DIE or into a .debug_loc 97*0b57cec5SDimitry Andric /// entry. 98*0b57cec5SDimitry Andric class DwarfExpression { 99*0b57cec5SDimitry Andric protected: 100*0b57cec5SDimitry Andric /// Holds information about all subregisters comprising a register location. 101*0b57cec5SDimitry Andric struct Register { 102*0b57cec5SDimitry Andric int DwarfRegNo; 103*0b57cec5SDimitry Andric unsigned Size; 104*0b57cec5SDimitry Andric const char *Comment; 105*0b57cec5SDimitry Andric }; 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric DwarfCompileUnit &CU; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric /// The register location, if any. 110*0b57cec5SDimitry Andric SmallVector<Register, 2> DwarfRegs; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric /// Current Fragment Offset in Bits. 113*0b57cec5SDimitry Andric uint64_t OffsetInBits = 0; 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. 116*0b57cec5SDimitry Andric unsigned SubRegisterSizeInBits : 16; 117*0b57cec5SDimitry Andric unsigned SubRegisterOffsetInBits : 16; 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric /// The kind of location description being produced. 120*0b57cec5SDimitry Andric enum { Unknown = 0, Register, Memory, Implicit }; 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric /// The flags of location description being produced. 123*0b57cec5SDimitry Andric enum { EntryValue = 1 }; 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric unsigned LocationKind : 3; 126*0b57cec5SDimitry Andric unsigned LocationFlags : 2; 127*0b57cec5SDimitry Andric unsigned DwarfVersion : 4; 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric public: 130*0b57cec5SDimitry Andric bool isUnknownLocation() const { 131*0b57cec5SDimitry Andric return LocationKind == Unknown; 132*0b57cec5SDimitry Andric } 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric bool isMemoryLocation() const { 135*0b57cec5SDimitry Andric return LocationKind == Memory; 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric bool isRegisterLocation() const { 139*0b57cec5SDimitry Andric return LocationKind == Register; 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric bool isImplicitLocation() const { 143*0b57cec5SDimitry Andric return LocationKind == Implicit; 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric bool isEntryValue() const { 147*0b57cec5SDimitry Andric return LocationFlags & EntryValue; 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric Optional<uint8_t> TagOffset; 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric protected: 153*0b57cec5SDimitry Andric /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed 154*0b57cec5SDimitry Andric /// to represent a subregister. 155*0b57cec5SDimitry Andric void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { 156*0b57cec5SDimitry Andric assert(SizeInBits < 65536 && OffsetInBits < 65536); 157*0b57cec5SDimitry Andric SubRegisterSizeInBits = SizeInBits; 158*0b57cec5SDimitry Andric SubRegisterOffsetInBits = OffsetInBits; 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric /// Add masking operations to stencil out a subregister. 162*0b57cec5SDimitry Andric void maskSubRegister(); 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric /// Output a dwarf operand and an optional assembler comment. 165*0b57cec5SDimitry Andric virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0; 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric /// Emit a raw signed value. 168*0b57cec5SDimitry Andric virtual void emitSigned(int64_t Value) = 0; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric /// Emit a raw unsigned value. 171*0b57cec5SDimitry Andric virtual void emitUnsigned(uint64_t Value) = 0; 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric virtual void emitData1(uint8_t Value) = 0; 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric virtual void emitBaseTypeRef(uint64_t Idx) = 0; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric /// Emit a normalized unsigned constant. 178*0b57cec5SDimitry Andric void emitConstu(uint64_t Value); 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric /// Return whether the given machine register is the frame register in the 181*0b57cec5SDimitry Andric /// current function. 182*0b57cec5SDimitry Andric virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0; 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF 185*0b57cec5SDimitry Andric /// register location description. 186*0b57cec5SDimitry Andric void addReg(int DwarfReg, const char *Comment = nullptr); 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andric /// Emit a DW_OP_breg operation. 189*0b57cec5SDimitry Andric void addBReg(int DwarfReg, int Offset); 190*0b57cec5SDimitry Andric 191*0b57cec5SDimitry Andric /// Emit DW_OP_fbreg <Offset>. 192*0b57cec5SDimitry Andric void addFBReg(int Offset); 193*0b57cec5SDimitry Andric 194*0b57cec5SDimitry Andric /// Emit a partial DWARF register operation. 195*0b57cec5SDimitry Andric /// 196*0b57cec5SDimitry Andric /// \param MachineReg The register number. 197*0b57cec5SDimitry Andric /// \param MaxSize If the register must be composed from 198*0b57cec5SDimitry Andric /// sub-registers this is an upper bound 199*0b57cec5SDimitry Andric /// for how many bits the emitted DW_OP_piece 200*0b57cec5SDimitry Andric /// may cover. 201*0b57cec5SDimitry Andric /// 202*0b57cec5SDimitry Andric /// If size and offset is zero an operation for the entire register is 203*0b57cec5SDimitry Andric /// emitted: Some targets do not provide a DWARF register number for every 204*0b57cec5SDimitry Andric /// register. If this is the case, this function will attempt to emit a DWARF 205*0b57cec5SDimitry Andric /// register by emitting a fragment of a super-register or by piecing together 206*0b57cec5SDimitry Andric /// multiple subregisters that alias the register. 207*0b57cec5SDimitry Andric /// 208*0b57cec5SDimitry Andric /// \return false if no DWARF register exists for MachineReg. 209*0b57cec5SDimitry Andric bool addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg, 210*0b57cec5SDimitry Andric unsigned MaxSize = ~1U); 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. 213*0b57cec5SDimitry Andric /// \param OffsetInBits This is an optional offset into the location that 214*0b57cec5SDimitry Andric /// is at the top of the DWARF stack. 215*0b57cec5SDimitry Andric void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric /// Emit a shift-right dwarf operation. 218*0b57cec5SDimitry Andric void addShr(unsigned ShiftBy); 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric /// Emit a bitwise and dwarf operation. 221*0b57cec5SDimitry Andric void addAnd(unsigned Mask); 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric /// Emit a DW_OP_stack_value, if supported. 224*0b57cec5SDimitry Andric /// 225*0b57cec5SDimitry Andric /// The proper way to describe a constant value is DW_OP_constu <const>, 226*0b57cec5SDimitry Andric /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available 227*0b57cec5SDimitry Andric /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for 228*0b57cec5SDimitry Andric /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const 229*0b57cec5SDimitry Andric /// <const> actually describes a value at a constant address, not a constant 230*0b57cec5SDimitry Andric /// value. However, in the past there was no better way to describe a 231*0b57cec5SDimitry Andric /// constant value, so the producers and consumers started to rely on 232*0b57cec5SDimitry Andric /// heuristics to disambiguate the value vs. location status of the 233*0b57cec5SDimitry Andric /// expression. See PR21176 for more details. 234*0b57cec5SDimitry Andric void addStackValue(); 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric ~DwarfExpression() = default; 237*0b57cec5SDimitry Andric 238*0b57cec5SDimitry Andric public: 239*0b57cec5SDimitry Andric DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) 240*0b57cec5SDimitry Andric : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), 241*0b57cec5SDimitry Andric LocationKind(Unknown), LocationFlags(Unknown), 242*0b57cec5SDimitry Andric DwarfVersion(DwarfVersion) {} 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric /// This needs to be called last to commit any pending changes. 245*0b57cec5SDimitry Andric void finalize(); 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric /// Emit a signed constant. 248*0b57cec5SDimitry Andric void addSignedConstant(int64_t Value); 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric /// Emit an unsigned constant. 251*0b57cec5SDimitry Andric void addUnsignedConstant(uint64_t Value); 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric /// Emit an unsigned constant. 254*0b57cec5SDimitry Andric void addUnsignedConstant(const APInt &Value); 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric /// Lock this down to become a memory location description. 257*0b57cec5SDimitry Andric void setMemoryLocationKind() { 258*0b57cec5SDimitry Andric assert(isUnknownLocation()); 259*0b57cec5SDimitry Andric LocationKind = Memory; 260*0b57cec5SDimitry Andric } 261*0b57cec5SDimitry Andric 262*0b57cec5SDimitry Andric /// Lock this down to become an entry value location. 263*0b57cec5SDimitry Andric void setEntryValueFlag() { 264*0b57cec5SDimitry Andric LocationFlags |= EntryValue; 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric 267*0b57cec5SDimitry Andric /// Emit a machine register location. As an optimization this may also consume 268*0b57cec5SDimitry Andric /// the prefix of a DwarfExpression if a more efficient representation for 269*0b57cec5SDimitry Andric /// combining the register location and the first operation exists. 270*0b57cec5SDimitry Andric /// 271*0b57cec5SDimitry Andric /// \param FragmentOffsetInBits If this is one fragment out of a 272*0b57cec5SDimitry Andric /// fragmented 273*0b57cec5SDimitry Andric /// location, this is the offset of the 274*0b57cec5SDimitry Andric /// fragment inside the entire variable. 275*0b57cec5SDimitry Andric /// \return false if no DWARF register exists 276*0b57cec5SDimitry Andric /// for MachineReg. 277*0b57cec5SDimitry Andric bool addMachineRegExpression(const TargetRegisterInfo &TRI, 278*0b57cec5SDimitry Andric DIExpressionCursor &Expr, unsigned MachineReg, 279*0b57cec5SDimitry Andric unsigned FragmentOffsetInBits = 0); 280*0b57cec5SDimitry Andric 281*0b57cec5SDimitry Andric /// Emit entry value dwarf operation. 282*0b57cec5SDimitry Andric void addEntryValueExpression(DIExpressionCursor &ExprCursor); 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric /// Emit all remaining operations in the DIExpressionCursor. 285*0b57cec5SDimitry Andric /// 286*0b57cec5SDimitry Andric /// \param FragmentOffsetInBits If this is one fragment out of multiple 287*0b57cec5SDimitry Andric /// locations, this is the offset of the 288*0b57cec5SDimitry Andric /// fragment inside the entire variable. 289*0b57cec5SDimitry Andric void addExpression(DIExpressionCursor &&Expr, 290*0b57cec5SDimitry Andric unsigned FragmentOffsetInBits = 0); 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to 293*0b57cec5SDimitry Andric /// the fragment described by \c Expr. 294*0b57cec5SDimitry Andric void addFragmentOffset(const DIExpression *Expr); 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric void emitLegacySExt(unsigned FromBits); 297*0b57cec5SDimitry Andric void emitLegacyZExt(unsigned FromBits); 298*0b57cec5SDimitry Andric }; 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric /// DwarfExpression implementation for .debug_loc entries. 301*0b57cec5SDimitry Andric class DebugLocDwarfExpression final : public DwarfExpression { 302*0b57cec5SDimitry Andric ByteStreamer &BS; 303*0b57cec5SDimitry Andric 304*0b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 305*0b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 306*0b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 307*0b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 308*0b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 309*0b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 310*0b57cec5SDimitry Andric unsigned MachineReg) override; 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric public: 313*0b57cec5SDimitry Andric DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS, DwarfCompileUnit &CU) 314*0b57cec5SDimitry Andric : DwarfExpression(DwarfVersion, CU), BS(BS) {} 315*0b57cec5SDimitry Andric }; 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric /// DwarfExpression implementation for singular DW_AT_location. 318*0b57cec5SDimitry Andric class DIEDwarfExpression final : public DwarfExpression { 319*0b57cec5SDimitry Andric const AsmPrinter &AP; 320*0b57cec5SDimitry Andric DIELoc &DIE; 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric void emitOp(uint8_t Op, const char *Comment = nullptr) override; 323*0b57cec5SDimitry Andric void emitSigned(int64_t Value) override; 324*0b57cec5SDimitry Andric void emitUnsigned(uint64_t Value) override; 325*0b57cec5SDimitry Andric void emitData1(uint8_t Value) override; 326*0b57cec5SDimitry Andric void emitBaseTypeRef(uint64_t Idx) override; 327*0b57cec5SDimitry Andric bool isFrameRegister(const TargetRegisterInfo &TRI, 328*0b57cec5SDimitry Andric unsigned MachineReg) override; 329*0b57cec5SDimitry Andric public: 330*0b57cec5SDimitry Andric DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); 331*0b57cec5SDimitry Andric 332*0b57cec5SDimitry Andric DIELoc *finalize() { 333*0b57cec5SDimitry Andric DwarfExpression::finalize(); 334*0b57cec5SDimitry Andric return &DIE; 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric }; 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric } // end namespace llvm 339*0b57cec5SDimitry Andric 340*0b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 341