LLVM 17.0.0git
DwarfExpression.h
Go to the documentation of this file.
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"
20#include <cassert>
21#include <cstdint>
22#include <iterator>
23#include <optional>
24
25namespace llvm {
26
27class AsmPrinter;
28class APInt;
29class DwarfCompileUnit;
30class DIELoc;
31class TargetRegisterInfo;
32class MachineLocation;
33
34/// Holds a DIExpression and keeps track of how many operands have been consumed
35/// so far.
38
39public:
41 if (!Expr) {
42 assert(Start == End);
43 return;
44 }
45 Start = Expr->expr_op_begin();
46 End = Expr->expr_op_end();
47 }
48
50 : Start(Expr.begin()), End(Expr.end()) {}
51
53
54 /// Consume one operation.
55 std::optional<DIExpression::ExprOperand> take() {
56 if (Start == End)
57 return std::nullopt;
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 std::optional<DIExpression::ExprOperand> peek() const {
66 if (Start == End)
67 return std::nullopt;
68 return *(Start);
69 }
70
71 /// Return the next operation.
72 std::optional<DIExpression::ExprOperand> peekNext() const {
73 if (Start == End)
74 return std::nullopt;
75
76 auto Next = Start.getNext();
77 if (Next == End)
78 return std::nullopt;
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 std::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.
106protected:
107 /// Holds information about all subregisters comprising a register location.
108 struct Register {
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.
129
131
132 /// The register location, if any.
134
135 /// Current Fragment Offset in Bits.
137
138 /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
141
142 /// The kind of location description being produced.
144
145 /// Additional location flags which may be combined with any location kind.
146 /// Currently, entry values are not supported for the Memory location kind.
147 enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 };
148
149 unsigned LocationKind : 3;
150 unsigned SavedLocationKind : 3;
151 unsigned LocationFlags : 3;
152 unsigned DwarfVersion : 4;
153
154public:
155 /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe.
156 void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr);
157
158 bool isUnknownLocation() const { return LocationKind == Unknown; }
159
160 bool isMemoryLocation() const { return LocationKind == Memory; }
161
162 bool isRegisterLocation() const { return LocationKind == Register; }
163
164 bool isImplicitLocation() const { return LocationKind == Implicit; }
165
166 bool isEntryValue() const { return LocationFlags & EntryValue; }
167
168 bool isIndirect() const { return LocationFlags & Indirect; }
169
171
172 std::optional<uint8_t> TagOffset;
173
174protected:
175 /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
176 /// to represent a subregister.
177 void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
178 assert(SizeInBits < 65536 && OffsetInBits < 65536);
179 SubRegisterSizeInBits = SizeInBits;
181 }
182
183 /// Add masking operations to stencil out a subregister.
184 void maskSubRegister();
185
186 /// Output a dwarf operand and an optional assembler comment.
187 virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0;
188
189 /// Emit a raw signed value.
190 virtual void emitSigned(int64_t Value) = 0;
191
192 /// Emit a raw unsigned value.
193 virtual void emitUnsigned(uint64_t Value) = 0;
194
195 virtual void emitData1(uint8_t Value) = 0;
196
197 virtual void emitBaseTypeRef(uint64_t Idx) = 0;
198
199 /// Start emitting data to the temporary buffer. The data stored in the
200 /// temporary buffer can be committed to the main output using
201 /// commitTemporaryBuffer().
202 virtual void enableTemporaryBuffer() = 0;
203
204 /// Disable emission to the temporary buffer. This does not commit data
205 /// in the temporary buffer to the main output.
206 virtual void disableTemporaryBuffer() = 0;
207
208 /// Return the emitted size, in number of bytes, for the data stored in the
209 /// temporary buffer.
210 virtual unsigned getTemporaryBufferSize() = 0;
211
212 /// Commit the data stored in the temporary buffer to the main output.
213 virtual void commitTemporaryBuffer() = 0;
214
215 /// Emit a normalized unsigned constant.
217
218 /// Return whether the given machine register is the frame register in the
219 /// current function.
221 llvm::Register MachineReg) = 0;
222
223 /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
224 /// register location description.
225 void addReg(int DwarfReg, const char *Comment = nullptr);
226
227 /// Emit a DW_OP_breg operation.
228 void addBReg(int DwarfReg, int Offset);
229
230 /// Emit DW_OP_fbreg <Offset>.
231 void addFBReg(int Offset);
232
233 /// Emit a partial DWARF register operation.
234 ///
235 /// \param MachineReg The register number.
236 /// \param MaxSize If the register must be composed from
237 /// sub-registers this is an upper bound
238 /// for how many bits the emitted DW_OP_piece
239 /// may cover.
240 ///
241 /// If size and offset is zero an operation for the entire register is
242 /// emitted: Some targets do not provide a DWARF register number for every
243 /// register. If this is the case, this function will attempt to emit a DWARF
244 /// register by emitting a fragment of a super-register or by piecing together
245 /// multiple subregisters that alias the register.
246 ///
247 /// \return false if no DWARF register exists for MachineReg.
248 bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register MachineReg,
249 unsigned MaxSize = ~1U);
250
251 /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
252 /// \param OffsetInBits This is an optional offset into the location that
253 /// is at the top of the DWARF stack.
254 void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
255
256 /// Emit a shift-right dwarf operation.
257 void addShr(unsigned ShiftBy);
258
259 /// Emit a bitwise and dwarf operation.
260 void addAnd(unsigned Mask);
261
262 /// Emit a DW_OP_stack_value, if supported.
263 ///
264 /// The proper way to describe a constant value is DW_OP_constu <const>,
265 /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available
266 /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
267 /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
268 /// <const> actually describes a value at a constant address, not a constant
269 /// value. However, in the past there was no better way to describe a
270 /// constant value, so the producers and consumers started to rely on
271 /// heuristics to disambiguate the value vs. location status of the
272 /// expression. See PR21176 for more details.
273 void addStackValue();
274
275 /// Finalize an entry value by emitting its size operand, and committing the
276 /// DWARF block which has been emitted to the temporary buffer.
277 void finalizeEntryValue();
278
279 /// Cancel the emission of an entry value.
280 void cancelEntryValue();
281
282 ~DwarfExpression() = default;
283
284public:
289
290 /// This needs to be called last to commit any pending changes.
291 void finalize();
292
293 /// Emit a signed constant.
294 void addSignedConstant(int64_t Value);
295
296 /// Emit an unsigned constant.
298
299 /// Emit an unsigned constant.
300 void addUnsignedConstant(const APInt &Value);
301
302 /// Emit an floating point constant.
303 void addConstantFP(const APFloat &Value, const AsmPrinter &AP);
304
305 /// Lock this down to become a memory location description.
309 }
310
311 /// Lock this down to become an entry value location.
312 void setEntryValueFlags(const MachineLocation &Loc);
313
314 /// Lock this down to become a call site parameter location.
316
317 /// Emit a machine register location. As an optimization this may also consume
318 /// the prefix of a DwarfExpression if a more efficient representation for
319 /// combining the register location and the first operation exists.
320 ///
321 /// \param FragmentOffsetInBits If this is one fragment out of a
322 /// fragmented
323 /// location, this is the offset of the
324 /// fragment inside the entire variable.
325 /// \return false if no DWARF register exists
326 /// for MachineReg.
328 DIExpressionCursor &Expr,
329 llvm::Register MachineReg,
330 unsigned FragmentOffsetInBits = 0);
331
332 /// Begin emission of an entry value dwarf operation. The entry value's
333 /// first operand is the size of the DWARF block (its second operand),
334 /// which needs to be calculated at time of emission, so we don't emit
335 /// any operands here.
337
338 /// Return the index of a base type with the given properties and
339 /// create one if necessary.
340 unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding);
341
342 /// Emit all remaining operations in the DIExpressionCursor. The
343 /// cursor must not contain any DW_OP_LLVM_arg operations.
345
346 /// Emit all remaining operations in the DIExpressionCursor.
347 /// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg).
348 //
349 /// \return false if any call to (\p InsertArg) returns false.
350 bool addExpression(
351 DIExpressionCursor &&Expr,
352 llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg);
353
354 /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
355 /// the fragment described by \c Expr.
356 void addFragmentOffset(const DIExpression *Expr);
357
358 void emitLegacySExt(unsigned FromBits);
359 void emitLegacyZExt(unsigned FromBits);
360
361 /// Emit location information expressed via WebAssembly location + offset
362 /// The Index is an identifier for locals, globals or operand stack.
363 void addWasmLocation(unsigned Index, uint64_t Offset);
364};
365
366/// DwarfExpression implementation for .debug_loc entries.
368
369 struct TempBuffer {
370 SmallString<32> Bytes;
371 std::vector<std::string> Comments;
373
374 TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {}
375 };
376
377 std::unique_ptr<TempBuffer> TmpBuf;
378 BufferByteStreamer &OutBS;
379 bool IsBuffering = false;
380
381 /// Return the byte streamer that currently is being emitted to.
382 ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; }
383
384 void emitOp(uint8_t Op, const char *Comment = nullptr) override;
385 void emitSigned(int64_t Value) override;
386 void emitUnsigned(uint64_t Value) override;
387 void emitData1(uint8_t Value) override;
388 void emitBaseTypeRef(uint64_t Idx) override;
389
390 void enableTemporaryBuffer() override;
391 void disableTemporaryBuffer() override;
392 unsigned getTemporaryBufferSize() override;
393 void commitTemporaryBuffer() override;
394
395 bool isFrameRegister(const TargetRegisterInfo &TRI,
396 llvm::Register MachineReg) override;
397
398public:
401 : DwarfExpression(DwarfVersion, CU), OutBS(BS) {}
402};
403
404/// DwarfExpression implementation for singular DW_AT_location.
406 const AsmPrinter &AP;
407 DIELoc &OutDIE;
408 DIELoc TmpDIE;
409 bool IsBuffering = false;
410
411 /// Return the DIE that currently is being emitted to.
412 DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; }
413
414 void emitOp(uint8_t Op, const char *Comment = nullptr) override;
415 void emitSigned(int64_t Value) override;
416 void emitUnsigned(uint64_t Value) override;
417 void emitData1(uint8_t Value) override;
418 void emitBaseTypeRef(uint64_t Idx) override;
419
420 void enableTemporaryBuffer() override;
421 void disableTemporaryBuffer() override;
422 unsigned getTemporaryBufferSize() override;
423 void commitTemporaryBuffer() override;
424
425 bool isFrameRegister(const TargetRegisterInfo &TRI,
426 llvm::Register MachineReg) override;
427
428public:
430
433 return &OutDIE;
434 }
435};
436
437} // end namespace llvm
438
439#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
Class for arbitrary precision integers.
Definition: APInt.h:75
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:84
DwarfExpression implementation for singular DW_AT_location.
DIELoc - Represents an expression location.
Definition: DIE.h:930
A structured debug information entry.
Definition: DIE.h:739
Holds a DIExpression and keeps track of how many operands have been consumed so far.
std::optional< DIExpression::ExprOperand > peekNext() const
Return the next operation.
std::optional< DIExpression::FragmentInfo > getFragmentInfo() const
Retrieve the fragment information, if any.
DIExpressionCursor(const DIExpressionCursor &)=default
DIExpressionCursor(const DIExpression *Expr)
DIExpression::expr_op_iterator end() const
std::optional< DIExpression::ExprOperand > peek() const
Return the current operation.
void consume(unsigned N)
Consume N operations.
std::optional< DIExpression::ExprOperand > take()
Consume one operation.
DIExpressionCursor(ArrayRef< uint64_t > Expr)
DIExpression::expr_op_iterator begin() const
An iterator for expression operands.
DWARF expression.
expr_op_iterator expr_op_begin() const
Visit the elements via ExprOperand wrappers.
expr_op_iterator expr_op_end() const
std::optional< FragmentInfo > getFragmentInfo() const
Retrieve the details of this fragment expression.
DwarfExpression implementation for .debug_loc entries.
DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, DwarfCompileUnit &CU)
Base class containing the logic for constructing DWARF expressions independently of whether they are ...
void addAnd(unsigned Mask)
Emit a bitwise and dwarf operation.
void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr)
Set the location (Loc) and DIExpression (DIExpr) to describe.
virtual void emitOp(uint8_t Op, const char *Comment=nullptr)=0
Output a dwarf operand and an optional assembler comment.
virtual void disableTemporaryBuffer()=0
Disable emission to the temporary buffer.
bool isUnknownLocation() const
virtual unsigned getTemporaryBufferSize()=0
Return the emitted size, in number of bytes, for the data stored in the temporary buffer.
uint64_t OffsetInBits
Current Fragment Offset in Bits.
virtual bool isFrameRegister(const TargetRegisterInfo &TRI, llvm::Register MachineReg)=0
Return whether the given machine register is the frame register in the current function.
void finalize()
This needs to be called last to commit any pending changes.
void addFragmentOffset(const DIExpression *Expr)
If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to the fragment described by Ex...
void emitLegacySExt(unsigned FromBits)
void cancelEntryValue()
Cancel the emission of an entry value.
bool isRegisterLocation() const
void setMemoryLocationKind()
Lock this down to become a memory location description.
virtual void emitBaseTypeRef(uint64_t Idx)=0
virtual void emitData1(uint8_t Value)=0
bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register MachineReg, unsigned MaxSize=~1U)
Emit a partial DWARF register operation.
void addReg(int DwarfReg, const char *Comment=nullptr)
Emit a DW_OP_reg operation.
std::optional< uint8_t > TagOffset
DwarfCompileUnit & CU
bool isImplicitLocation() const
void setCallSiteParamValueFlag()
Lock this down to become a call site parameter location.
virtual void emitUnsigned(uint64_t Value)=0
Emit a raw unsigned value.
void addConstantFP(const APFloat &Value, const AsmPrinter &AP)
Emit an floating point constant.
void maskSubRegister()
Add masking operations to stencil out a subregister.
SmallVector< Register, 2 > DwarfRegs
The register location, if any.
bool addMachineRegExpression(const TargetRegisterInfo &TRI, DIExpressionCursor &Expr, llvm::Register MachineReg, unsigned FragmentOffsetInBits=0)
Emit a machine register location.
~DwarfExpression()=default
void addStackValue()
Emit a DW_OP_stack_value, if supported.
void finalizeEntryValue()
Finalize an entry value by emitting its size operand, and committing the DWARF block which has been e...
void addBReg(int DwarfReg, int Offset)
Emit a DW_OP_breg operation.
bool isMemoryLocation() const
void addUnsignedConstant(uint64_t Value)
Emit an unsigned constant.
unsigned SubRegisterSizeInBits
Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
void addFBReg(int Offset)
Emit DW_OP_fbreg <Offset>.
void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits)
Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed to represent a subregister.
void addExpression(DIExpressionCursor &&Expr)
Emit all remaining operations in the DIExpressionCursor.
unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding)
Return the index of a base type with the given properties and create one if necessary.
void addSignedConstant(int64_t Value)
Emit a signed constant.
void emitLegacyZExt(unsigned FromBits)
bool IsEmittingEntryValue
Whether we are currently emitting an entry value operation.
virtual void emitSigned(int64_t Value)=0
Emit a raw signed value.
void setEntryValueFlags(const MachineLocation &Loc)
Lock this down to become an entry value location.
virtual void commitTemporaryBuffer()=0
Commit the data stored in the temporary buffer to the main output.
void addShr(unsigned ShiftBy)
Emit a shift-right dwarf operation.
DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU)
void addWasmLocation(unsigned Index, uint64_t Offset)
Emit location information expressed via WebAssembly location + offset The Index is an identifier for ...
virtual void enableTemporaryBuffer()=0
Start emitting data to the temporary buffer.
void emitConstu(uint64_t Value)
Emit a normalized unsigned constant.
void beginEntryValueExpression(DIExpressionCursor &ExprCursor)
Begin emission of an entry value dwarf operation.
void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits=0)
Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVM Value Representation.
Definition: Value.h:74
An efficient, type-erasing, non-owning reference to a callable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
#define N
Holds information about all subregisters comprising a register location.
static Register createRegister(int RegNo, const char *Comment)
Create a full register, no extra DW_OP_piece operators necessary.
static Register createSubRegister(int RegNo, unsigned SizeInBits, const char *Comment)
Create a subregister that needs a DW_OP_piece operator with SizeInBits.