1 //===- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains support for writing dwarf compile unit. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 14 #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 15 16 #include "ByteStreamer.h" 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/IR/DebugInfoMetadata.h" 20 #include <cassert> 21 #include <cstdint> 22 #include <iterator> 23 #include <optional> 24 25 namespace llvm { 26 27 class AsmPrinter; 28 class APInt; 29 class DwarfCompileUnit; 30 class DIELoc; 31 class TargetRegisterInfo; 32 class MachineLocation; 33 34 /// Base class containing the logic for constructing DWARF expressions 35 /// independently of whether they are emitted into a DIE or into a .debug_loc 36 /// entry. 37 /// 38 /// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the size 39 /// of a succeeding DWARF block before the latter is emitted to the output. 40 /// To handle such cases, data can conditionally be emitted to a temporary 41 /// buffer, which can later on be committed to the main output. The size of the 42 /// temporary buffer is queryable, allowing for the size of the data to be 43 /// emitted before the data is committed. 44 class DwarfExpression { 45 protected: 46 /// Holds information about all subregisters comprising a register location. 47 struct Register { 48 int DwarfRegNo; 49 unsigned SubRegSize; 50 const char *Comment; 51 52 /// Create a full register, no extra DW_OP_piece operators necessary. createRegisterRegister53 static Register createRegister(int RegNo, const char *Comment) { 54 return {RegNo, 0, Comment}; 55 } 56 57 /// Create a subregister that needs a DW_OP_piece operator with SizeInBits. createSubRegisterRegister58 static Register createSubRegister(int RegNo, unsigned SizeInBits, 59 const char *Comment) { 60 return {RegNo, SizeInBits, Comment}; 61 } 62 isSubRegisterRegister63 bool isSubRegister() const { return SubRegSize; } 64 }; 65 66 /// Whether we are currently emitting an entry value operation. 67 bool IsEmittingEntryValue = false; 68 69 DwarfCompileUnit &CU; 70 71 /// The register location, if any. 72 SmallVector<Register, 2> DwarfRegs; 73 74 /// Current Fragment Offset in Bits. 75 uint64_t OffsetInBits = 0; 76 77 /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. 78 unsigned SubRegisterSizeInBits : 16; 79 unsigned SubRegisterOffsetInBits : 16; 80 81 /// The kind of location description being produced. 82 enum { Unknown = 0, Register, Memory, Implicit }; 83 84 /// Additional location flags which may be combined with any location kind. 85 /// Currently, entry values are not supported for the Memory location kind. 86 enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 }; 87 88 unsigned LocationKind : 3; 89 unsigned SavedLocationKind : 3; 90 unsigned LocationFlags : 3; 91 unsigned DwarfVersion : 4; 92 93 public: 94 /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe. 95 void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr); 96 isUnknownLocation()97 bool isUnknownLocation() const { return LocationKind == Unknown; } 98 isMemoryLocation()99 bool isMemoryLocation() const { return LocationKind == Memory; } 100 isRegisterLocation()101 bool isRegisterLocation() const { return LocationKind == Register; } 102 isImplicitLocation()103 bool isImplicitLocation() const { return LocationKind == Implicit; } 104 isEntryValue()105 bool isEntryValue() const { return LocationFlags & EntryValue; } 106 isIndirect()107 bool isIndirect() const { return LocationFlags & Indirect; } 108 isParameterValue()109 bool isParameterValue() { return LocationFlags & CallSiteParamValue; } 110 111 std::optional<uint8_t> TagOffset; 112 113 protected: 114 /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed 115 /// to represent a subregister. setSubRegisterPiece(unsigned SizeInBits,unsigned OffsetInBits)116 void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { 117 assert(SizeInBits < 65536 && OffsetInBits < 65536); 118 SubRegisterSizeInBits = SizeInBits; 119 SubRegisterOffsetInBits = OffsetInBits; 120 } 121 122 /// Add masking operations to stencil out a subregister. 123 void maskSubRegister(); 124 125 /// Output a dwarf operand and an optional assembler comment. 126 virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0; 127 128 /// Emit a raw signed value. 129 virtual void emitSigned(int64_t Value) = 0; 130 131 /// Emit a raw unsigned value. 132 virtual void emitUnsigned(uint64_t Value) = 0; 133 134 virtual void emitData1(uint8_t Value) = 0; 135 136 virtual void emitBaseTypeRef(uint64_t Idx) = 0; 137 138 /// Start emitting data to the temporary buffer. The data stored in the 139 /// temporary buffer can be committed to the main output using 140 /// commitTemporaryBuffer(). 141 virtual void enableTemporaryBuffer() = 0; 142 143 /// Disable emission to the temporary buffer. This does not commit data 144 /// in the temporary buffer to the main output. 145 virtual void disableTemporaryBuffer() = 0; 146 147 /// Return the emitted size, in number of bytes, for the data stored in the 148 /// temporary buffer. 149 virtual unsigned getTemporaryBufferSize() = 0; 150 151 /// Commit the data stored in the temporary buffer to the main output. 152 virtual void commitTemporaryBuffer() = 0; 153 154 /// Emit a normalized unsigned constant. 155 void emitConstu(uint64_t Value); 156 157 /// Return whether the given machine register is the frame register in the 158 /// current function. 159 virtual bool isFrameRegister(const TargetRegisterInfo &TRI, 160 llvm::Register MachineReg) = 0; 161 162 /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF 163 /// register location description. 164 void addReg(int DwarfReg, const char *Comment = nullptr); 165 166 /// Emit a DW_OP_breg operation. 167 void addBReg(int DwarfReg, int Offset); 168 169 /// Emit DW_OP_fbreg <Offset>. 170 void addFBReg(int Offset); 171 172 /// Emit a partial DWARF register operation. 173 /// 174 /// \param MachineReg The register number. 175 /// \param MaxSize If the register must be composed from 176 /// sub-registers this is an upper bound 177 /// for how many bits the emitted DW_OP_piece 178 /// may cover. 179 /// 180 /// If size and offset is zero an operation for the entire register is 181 /// emitted: Some targets do not provide a DWARF register number for every 182 /// register. If this is the case, this function will attempt to emit a DWARF 183 /// register by emitting a fragment of a super-register or by piecing together 184 /// multiple subregisters that alias the register. 185 /// 186 /// \return false if no DWARF register exists for MachineReg. 187 bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register MachineReg, 188 unsigned MaxSize = ~1U); 189 190 /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. 191 /// \param OffsetInBits This is an optional offset into the location that 192 /// is at the top of the DWARF stack. 193 void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); 194 195 /// Emit a shift-right dwarf operation. 196 void addShr(unsigned ShiftBy); 197 198 /// Emit a bitwise and dwarf operation. 199 void addAnd(unsigned Mask); 200 201 /// Emit a DW_OP_stack_value, if supported. 202 /// 203 /// The proper way to describe a constant value is DW_OP_constu <const>, 204 /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available 205 /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for 206 /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const 207 /// <const> actually describes a value at a constant address, not a constant 208 /// value. However, in the past there was no better way to describe a 209 /// constant value, so the producers and consumers started to rely on 210 /// heuristics to disambiguate the value vs. location status of the 211 /// expression. See PR21176 for more details. 212 void addStackValue(); 213 214 /// Finalize an entry value by emitting its size operand, and committing the 215 /// DWARF block which has been emitted to the temporary buffer. 216 void finalizeEntryValue(); 217 218 /// Cancel the emission of an entry value. 219 void cancelEntryValue(); 220 221 ~DwarfExpression() = default; 222 223 public: DwarfExpression(unsigned DwarfVersion,DwarfCompileUnit & CU)224 DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) 225 : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), 226 LocationKind(Unknown), SavedLocationKind(Unknown), 227 LocationFlags(Unknown), DwarfVersion(DwarfVersion) {} 228 229 /// This needs to be called last to commit any pending changes. 230 void finalize(); 231 232 /// Emit a signed constant. 233 void addSignedConstant(int64_t Value); 234 235 /// Emit an unsigned constant. 236 void addUnsignedConstant(uint64_t Value); 237 238 /// Emit an unsigned constant. 239 void addUnsignedConstant(const APInt &Value); 240 241 /// Emit an floating point constant. 242 void addConstantFP(const APFloat &Value, const AsmPrinter &AP); 243 244 /// Lock this down to become a memory location description. setMemoryLocationKind()245 void setMemoryLocationKind() { 246 assert(isUnknownLocation()); 247 LocationKind = Memory; 248 } 249 250 /// Lock this down to become an entry value location. 251 void setEntryValueFlags(const MachineLocation &Loc); 252 253 /// Lock this down to become a call site parameter location. setCallSiteParamValueFlag()254 void setCallSiteParamValueFlag() { LocationFlags |= CallSiteParamValue; } 255 256 /// Emit a machine register location. As an optimization this may also consume 257 /// the prefix of a DwarfExpression if a more efficient representation for 258 /// combining the register location and the first operation exists. 259 /// 260 /// \param FragmentOffsetInBits If this is one fragment out of a 261 /// fragmented 262 /// location, this is the offset of the 263 /// fragment inside the entire variable. 264 /// \return false if no DWARF register exists 265 /// for MachineReg. 266 bool addMachineRegExpression(const TargetRegisterInfo &TRI, 267 DIExpressionCursor &Expr, 268 llvm::Register MachineReg, 269 unsigned FragmentOffsetInBits = 0); 270 271 /// Begin emission of an entry value dwarf operation. The entry value's 272 /// first operand is the size of the DWARF block (its second operand), 273 /// which needs to be calculated at time of emission, so we don't emit 274 /// any operands here. 275 void beginEntryValueExpression(DIExpressionCursor &ExprCursor); 276 277 /// Return the index of a base type with the given properties and 278 /// create one if necessary. 279 unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding); 280 281 /// Emit all remaining operations in the DIExpressionCursor. The 282 /// cursor must not contain any DW_OP_LLVM_arg operations. 283 void addExpression(DIExpressionCursor &&Expr); 284 285 /// Emit all remaining operations in the DIExpressionCursor. 286 /// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg). 287 // 288 /// \return false if any call to (\p InsertArg) returns false. 289 bool addExpression( 290 DIExpressionCursor &&Expr, 291 llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg); 292 293 /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to 294 /// the fragment described by \c Expr. 295 void addFragmentOffset(const DIExpression *Expr); 296 297 void emitLegacySExt(unsigned FromBits); 298 void emitLegacyZExt(unsigned FromBits); 299 300 /// Emit location information expressed via WebAssembly location + offset 301 /// The Index is an identifier for locals, globals or operand stack. 302 void addWasmLocation(unsigned Index, uint64_t Offset); 303 }; 304 305 /// DwarfExpression implementation for .debug_loc entries. 306 class DebugLocDwarfExpression final : public DwarfExpression { 307 308 struct TempBuffer { 309 SmallString<32> Bytes; 310 std::vector<std::string> Comments; 311 BufferByteStreamer BS; 312 TempBufferTempBuffer313 TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {} 314 }; 315 316 std::unique_ptr<TempBuffer> TmpBuf; 317 BufferByteStreamer &OutBS; 318 bool IsBuffering = false; 319 320 /// Return the byte streamer that currently is being emitted to. getActiveStreamer()321 ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; } 322 323 void emitOp(uint8_t Op, const char *Comment = nullptr) override; 324 void emitSigned(int64_t Value) override; 325 void emitUnsigned(uint64_t Value) override; 326 void emitData1(uint8_t Value) override; 327 void emitBaseTypeRef(uint64_t Idx) override; 328 329 void enableTemporaryBuffer() override; 330 void disableTemporaryBuffer() override; 331 unsigned getTemporaryBufferSize() override; 332 void commitTemporaryBuffer() override; 333 334 bool isFrameRegister(const TargetRegisterInfo &TRI, 335 llvm::Register MachineReg) override; 336 337 public: DebugLocDwarfExpression(unsigned DwarfVersion,BufferByteStreamer & BS,DwarfCompileUnit & CU)338 DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, 339 DwarfCompileUnit &CU) 340 : DwarfExpression(DwarfVersion, CU), OutBS(BS) {} 341 }; 342 343 /// DwarfExpression implementation for singular DW_AT_location. 344 class DIEDwarfExpression final : public DwarfExpression { 345 const AsmPrinter &AP; 346 DIELoc &OutDIE; 347 DIELoc TmpDIE; 348 bool IsBuffering = false; 349 350 /// Return the DIE that currently is being emitted to. getActiveDIE()351 DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; } 352 353 void emitOp(uint8_t Op, const char *Comment = nullptr) override; 354 void emitSigned(int64_t Value) override; 355 void emitUnsigned(uint64_t Value) override; 356 void emitData1(uint8_t Value) override; 357 void emitBaseTypeRef(uint64_t Idx) override; 358 359 void enableTemporaryBuffer() override; 360 void disableTemporaryBuffer() override; 361 unsigned getTemporaryBufferSize() override; 362 void commitTemporaryBuffer() override; 363 364 bool isFrameRegister(const TargetRegisterInfo &TRI, 365 llvm::Register MachineReg) override; 366 367 public: 368 DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); 369 finalize()370 DIELoc *finalize() { 371 DwarfExpression::finalize(); 372 return &OutDIE; 373 } 374 }; 375 376 } // end namespace llvm 377 378 #endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H 379