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