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