LLVM: lib/CodeGen/AsmPrinter/DwarfExpression.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
23#include
24
25using namespace llvm;
26
27#define DEBUG_TYPE "dwarfdebug"
28
32 else if (Value == std::numeric_limits<uint64_t>::max()) {
33
34
35 emitOp(dwarf::DW_OP_lit0);
36 emitOp(dwarf::DW_OP_not);
37 } else {
38 emitOp(dwarf::DW_OP_constu);
40 }
41}
42
44 assert(DwarfReg >= 0 && "invalid negative dwarf register number");
46 "location description already locked down");
48 if (DwarfReg < 32) {
49 emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
50 } else {
51 emitOp(dwarf::DW_OP_regx, Comment);
53 }
54}
55
57 assert(DwarfReg >= 0 && "invalid negative dwarf register number");
59 if (DwarfReg < 32) {
60 emitOp(dwarf::DW_OP_breg0 + DwarfReg);
61 } else {
62 emitOp(dwarf::DW_OP_bregx);
64 }
66}
67
69 emitOp(dwarf::DW_OP_fbreg);
71}
72
74 if (!SizeInBits)
75 return;
76
77 const unsigned SizeOfByte = 8;
78 if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
79 emitOp(dwarf::DW_OP_bit_piece);
82 } else {
83 emitOp(dwarf::DW_OP_piece);
84 unsigned ByteSize = SizeInBits / SizeOfByte;
86 }
87 this->OffsetInBits += SizeInBits;
88}
89
92 emitOp(dwarf::DW_OP_shr);
93}
94
97 emitOp(dwarf::DW_OP_and);
98}
99
102 unsigned MaxSize) {
106 return true;
107 }
108
109 int64_t Reg = TRI.getDwarfRegNumForVirtReg(MachineReg, false);
110 if (Reg > 0) {
112 return true;
113 }
114 return false;
115 }
116
117 int64_t Reg = TRI.getDwarfRegNum(MachineReg, false);
118
119
120 if (Reg >= 0) {
122 return true;
123 }
124
125
126
127 for (MCPhysReg SR : TRI.superregs(MachineReg)) {
128 Reg = TRI.getDwarfRegNum(SR, false);
129 if (Reg >= 0) {
130 unsigned Idx = TRI.getSubRegIndex(SR, MachineReg);
131 unsigned Size = TRI.getSubRegIdxSize(Idx);
132 unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
134
136 return true;
137 }
138 }
139
140
141
142 unsigned CurPos = 0;
143
145 unsigned RegSize = TRI.getRegSizeInBits(*RC);
146
147
148
149
150
152 for (MCPhysReg SR : TRI.subregs(MachineReg)) {
153 unsigned Idx = TRI.getSubRegIndex(MachineReg, SR);
154 unsigned Size = TRI.getSubRegIdxSize(Idx);
155 unsigned Offset = TRI.getSubRegIdxOffset(Idx);
156 Reg = TRI.getDwarfRegNum(SR, false);
158 continue;
159
160
161
164
165
166
167 if (Offset < MaxSize && CurSubReg.test(Coverage)) {
168
171 -1, Offset - CurPos, "no DWARF register encoding"));
174 else
176 Reg, std::min(Size, MaxSize - Offset), "sub-register"));
177 }
178
181 }
182
183 if (CurPos == 0)
184 return false;
185
188 -1, RegSize - CurPos, "no DWARF register encoding"));
189 return true;
190}
191
194 emitOp(dwarf::DW_OP_stack_value);
195}
196
201 emitOp(dwarf::DW_OP_lit0);
202 else
203 emitOp(dwarf::DW_OP_lit1);
204}
205
209 emitOp(dwarf::DW_OP_consts);
211}
212
218
222
223 unsigned Size = Value.getBitWidth();
225
226
227
232 break;
236 }
237}
238
243 if (NumBytes == 4 || NumBytes == 8 ) {
244
245 emitOp(dwarf::DW_OP_implicit_value);
246 emitUnsigned(NumBytes );
247
248
249
250
253
254 for (int i = 0; i < NumBytes; ++i) {
256 API = API.lshr(8);
257 }
258
259 return;
260 }
262 dbgs() << "Skipped DW_OP_implicit_value creation for ConstantFP of size: "
264}
265
269 unsigned FragmentOffsetInBits) {
271 if ((TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U)) {
273 return false;
274 }
275
276 bool HasComplexExpression = false;
277 auto Op = ExprCursor.peek();
279 HasComplexExpression = true;
280
281
282
283
284
285
286
287
288
289
290
291
297 return false;
298 }
299
300
301
302
303
309 RegSize += Reg.SubRegSize;
310 if (Reg.DwarfRegNo >= 0)
311 addReg(Reg.DwarfRegNo, Reg.Comment);
312 if (FragmentInfo)
313 if (RegSize > FragmentInfo->SizeInBits)
314
315
316 break;
318 }
319
322
325 emitOp(dwarf::DW_OP_stack_value);
326 }
327
329
330
331 auto NextOp = ExprCursor.peek();
335 return true;
336 }
337
338
341 return Op.getOp() == dwarf::DW_OP_stack_value;
342 })) {
345 return false;
346 }
347
348
349
351 LLVM_DEBUG(dbgs() << "TODO: giving up on debug information due to "
352 "multi-register usage.\n");
355 return false;
356 }
357
360 int SignedOffset = 0;
361 assert(!Reg.isSubRegister() && "full register expected");
362
363
364
365 if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) {
367 uint64_t IntMax = static_cast<uint64_t>(std::numeric_limits::max());
368 if (Offset <= IntMax) {
369 SignedOffset = Offset;
370 ExprCursor.take();
371 }
372 }
373
374
375
376
377 if (Op && Op->getOp() == dwarf::DW_OP_constu) {
379 uint64_t IntMax = static_cast<uint64_t>(std::numeric_limits::max());
381 if (N && N->getOp() == dwarf::DW_OP_plus && Offset <= IntMax) {
382 SignedOffset = Offset;
384 } else if (N && N->getOp() == dwarf::DW_OP_minus &&
386 SignedOffset = -static_cast<int64_t>(Offset);
388 }
389 }
390
391 if (FBReg)
393 else
394 addBReg(Reg.DwarfRegNo, SignedOffset);
396
397
398
399 auto NextOp = ExprCursor.peek();
403
404 return true;
405}
406
409 if (Loc.isIndirect())
411}
412
415 if (Loc.isIndirect())
417
420}
421
424 auto Op = ExprCursor.take();
425 (void)Op;
429 "Can currently only emit entry values covering a single operation");
430
436}
437
441
442 emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));
443
444
447
448
450
454}
455
459
460
461
463 "Began emitting entry value block before cancelling entry value");
464
467}
468
471
472
473 unsigned I = 0, E = CU.ExprRefedBaseTypes.size();
475 if (CU.ExprRefedBaseTypes[I].BitSize == BitSize &&
476 CU.ExprRefedBaseTypes[I].Encoding == Encoding)
477 break;
478
479 if (I == E)
480 CU.ExprRefedBaseTypes.emplace_back(BitSize, Encoding);
481 return I;
482}
483
484
485
487 while (ExprCursor) {
488 auto Op = ExprCursor.take();
489 switch (Op->getOp()) {
490 case dwarf::DW_OP_deref:
492 break;
493 default:
494 return false;
495 }
496 }
497 return true;
498}
499
506
510
511
513
514 std::optionalDIExpression::ExprOperand PrevConvertOp;
515
516 while (ExprCursor) {
517 auto Op = ExprCursor.take();
519
520 if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
522 continue;
523 } else if (OpNum >= dwarf::DW_OP_breg0 && OpNum <= dwarf::DW_OP_breg31) {
524 addBReg(OpNum - dwarf::DW_OP_breg0, Op->getArg(0));
525 continue;
526 }
527
528 switch (OpNum) {
530 if (!InsertArg(Op->getArg(0), ExprCursor)) {
532 return false;
533 }
534 break;
536 unsigned SizeInBits = Op->getArg(1);
537 unsigned FragmentOffset = Op->getArg(0);
538
539
540
541 assert(OffsetInBits >= FragmentOffset && "fragment offset not added?");
542 assert(SizeInBits >= OffsetInBits - FragmentOffset && "size underflow");
543
544
545
546
548
549
550
553
554
557
558
561
563 return true;
564 }
567 unsigned SizeInBits = Op->getArg(1);
568 unsigned BitOffset = Op->getArg(0);
569 unsigned DerefSize = 0;
570
571
572 unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();
573
574
575
576
578 DerefSize = alignTo(BitOffset + SizeInBits, 8) / 8;
579 if (DerefSize == PtrSizeInBytes) {
580 emitOp(dwarf::DW_OP_deref);
581 } else {
582 emitOp(dwarf::DW_OP_deref_size);
584 }
585 }
586
587
588
589
591 if (8 * DerefSize == SizeInBits) {
592
593 } else {
594
595 emitOp(dwarf::DW_OP_constu);
597 emitOp(dwarf::DW_OP_and);
598 }
599 } else {
600
601
602
603 unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
604 unsigned RightShift = LeftShift + BitOffset;
605 if (LeftShift) {
606 emitOp(dwarf::DW_OP_constu);
608 emitOp(dwarf::DW_OP_shl);
609 }
610 if (RightShift) {
611 emitOp(dwarf::DW_OP_constu);
614 ? dwarf::DW_OP_shra
615 : dwarf::DW_OP_shr);
616 }
617 }
618
619
620
622 break;
623 }
624 case dwarf::DW_OP_plus_uconst:
626 emitOp(dwarf::DW_OP_plus_uconst);
628 break;
629 case dwarf::DW_OP_plus:
630 case dwarf::DW_OP_minus:
631 case dwarf::DW_OP_mul:
632 case dwarf::DW_OP_div:
633 case dwarf::DW_OP_mod:
634 case dwarf::DW_OP_or:
635 case dwarf::DW_OP_and:
636 case dwarf::DW_OP_xor:
637 case dwarf::DW_OP_shl:
638 case dwarf::DW_OP_shr:
639 case dwarf::DW_OP_shra:
640 case dwarf::DW_OP_lit0:
641 case dwarf::DW_OP_not:
642 case dwarf::DW_OP_dup:
643 case dwarf::DW_OP_push_object_address:
644 case dwarf::DW_OP_over:
645 case dwarf::DW_OP_rot:
646 case dwarf::DW_OP_eq:
647 case dwarf::DW_OP_ne:
648 case dwarf::DW_OP_gt:
649 case dwarf::DW_OP_ge:
650 case dwarf::DW_OP_lt:
651 case dwarf::DW_OP_le:
652 case dwarf::DW_OP_neg:
653 case dwarf::DW_OP_abs:
655 break;
656 case dwarf::DW_OP_deref:
659
660
662 else
663 emitOp(dwarf::DW_OP_deref);
664 break;
665 case dwarf::DW_OP_constu:
668 break;
669 case dwarf::DW_OP_consts:
671 emitOp(dwarf::DW_OP_consts);
673 break;
675 unsigned BitSize = Op->getArg(0);
677 if (DwarfVersion >= 5 && CU.getDwarfDebug().useOpConvert()) {
678 emitOp(dwarf::DW_OP_convert);
679
680
681
682
683
684
686 } else {
687 if (PrevConvertOp && PrevConvertOp->getArg(0) < BitSize) {
688 if (Encoding == dwarf::DW_ATE_signed)
690 else if (Encoding == dwarf::DW_ATE_unsigned)
692 PrevConvertOp = std::nullopt;
693 } else {
694 PrevConvertOp = Op;
695 }
696 }
697 break;
698 }
699 case dwarf::DW_OP_stack_value:
701 break;
702 case dwarf::DW_OP_swap:
704 emitOp(dwarf::DW_OP_swap);
705 break;
706 case dwarf::DW_OP_xderef:
708 emitOp(dwarf::DW_OP_xderef);
709 break;
710 case dwarf::DW_OP_deref_size:
711 emitOp(dwarf::DW_OP_deref_size);
713 break;
716 break;
717 case dwarf::DW_OP_regx:
718 emitOp(dwarf::DW_OP_regx);
720 break;
721 case dwarf::DW_OP_bregx:
722 emitOp(dwarf::DW_OP_bregx);
725 break;
726 default:
728 }
729 }
730
732
734
735 return true;
736}
737
738
746
748 assert(DwarfRegs.size() == 0 && "dwarf registers not emitted");
749
751 return;
752
754 return;
756}
757
760 return;
761
764 "overlapping or duplicate fragments");
768}
769
771
772 emitOp(dwarf::DW_OP_dup);
773 emitOp(dwarf::DW_OP_constu);
775 emitOp(dwarf::DW_OP_shr);
776 emitOp(dwarf::DW_OP_lit0);
777 emitOp(dwarf::DW_OP_not);
778 emitOp(dwarf::DW_OP_mul);
779 emitOp(dwarf::DW_OP_constu);
781 emitOp(dwarf::DW_OP_shl);
782 emitOp(dwarf::DW_OP_or);
783}
784
786
787
788 if (FromBits / 7 < 1+1+1+1+1) {
789
790 emitOp(dwarf::DW_OP_constu);
792 } else {
793
794
795
796
797
798 emitOp(dwarf::DW_OP_lit1);
799 emitOp(dwarf::DW_OP_constu);
801 emitOp(dwarf::DW_OP_shl);
802 emitOp(dwarf::DW_OP_lit1);
803 emitOp(dwarf::DW_OP_minus);
804 }
805 emitOp(dwarf::DW_OP_and);
806}
807
809 emitOp(dwarf::DW_OP_WASM_location);
810 emitUnsigned(Index == 4 ? 0 : Index);
812 if (Index == 4 ) {
815 } else {
818 }
819}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isMemoryLocation(DIExpressionCursor ExprCursor)
Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?
Definition DwarfExpression.cpp:486
This file contains constants used for implementing Dwarf debug support.
Register const TargetRegisterInfo * TRI
This file implements the SmallBitVector class.
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
LLVM_ABI APInt byteSwap() const
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class is intended to be used as a driving class for all asm writers.
const DataLayout & getDataLayout() const
Return information about data layout.
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.
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.
A lightweight wrapper around an expression operand.
LLVM_ABI bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
bool isFragment() const
Return whether this is a piece of an aggregate variable.
static LLVM_ABI std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
void addAnd(unsigned Mask)
Emit a bitwise and dwarf operation.
Definition DwarfExpression.cpp:95
void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr)
Set the location (Loc) and DIExpression (DIExpr) to describe.
Definition DwarfExpression.cpp:413
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.
Definition DwarfExpression.cpp:747
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...
Definition DwarfExpression.cpp:758
void emitLegacySExt(unsigned FromBits)
Definition DwarfExpression.cpp:770
void cancelEntryValue()
Cancel the emission of an entry value.
Definition DwarfExpression.cpp:456
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.
Definition DwarfExpression.cpp:100
unsigned SavedLocationKind
std::optional< uint8_t > TagOffset
bool isImplicitLocation() const
virtual void emitUnsigned(uint64_t Value)=0
Emit a raw unsigned value.
void addBooleanConstant(int64_t Value)
Emit a boolean constant.
Definition DwarfExpression.cpp:197
void addConstantFP(const APFloat &Value, const AsmPrinter &AP)
Emit an floating point constant.
Definition DwarfExpression.cpp:239
void maskSubRegister()
Add masking operations to stencil out a subregister.
Definition DwarfExpression.cpp:739
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.
Definition DwarfExpression.cpp:266
void addStackValue()
Emit a DW_OP_stack_value, if supported.
Definition DwarfExpression.cpp:192
void finalizeEntryValue()
Finalize an entry value by emitting its size operand, and committing the DWARF block which has been e...
Definition DwarfExpression.cpp:438
bool isMemoryLocation() const
void addUnsignedConstant(uint64_t Value)
Emit an unsigned constant.
Definition DwarfExpression.cpp:213
unsigned SubRegisterSizeInBits
Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
void addFBReg(int64_t Offset)
Emit DW_OP_fbreg .
Definition DwarfExpression.cpp:68
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.
Definition DwarfExpression.cpp:500
bool isEntryValue() const
unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding)
Return the index of a base type with the given properties and create one if necessary.
Definition DwarfExpression.cpp:469
void addSignedConstant(int64_t Value)
Emit a signed constant.
Definition DwarfExpression.cpp:206
void emitLegacyZExt(unsigned FromBits)
Definition DwarfExpression.cpp:785
bool IsEmittingEntryValue
Whether we are currently emitting an entry value operation.
virtual void emitSigned(int64_t Value)=0
Emit a raw signed value.
void addReg(int64_t DwarfReg, const char *Comment=nullptr)
Emit a DW_OP_reg operation.
Definition DwarfExpression.cpp:43
unsigned SubRegisterOffsetInBits
void setEntryValueFlags(const MachineLocation &Loc)
Lock this down to become an entry value location.
Definition DwarfExpression.cpp:407
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.
Definition DwarfExpression.cpp:90
void addWasmLocation(unsigned Index, uint64_t Offset)
Emit location information expressed via WebAssembly location + offset The Index is an identifier for ...
Definition DwarfExpression.cpp:808
virtual void enableTemporaryBuffer()=0
Start emitting data to the temporary buffer.
void emitConstu(uint64_t Value)
Emit a normalized unsigned constant.
Definition DwarfExpression.cpp:29
void beginEntryValueExpression(DIExpressionCursor &ExprCursor)
Begin emission of an entry value dwarf operation.
Definition DwarfExpression.cpp:422
void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits=0)
Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
Definition DwarfExpression.cpp:73
void addBReg(int64_t DwarfReg, int64_t Offset)
Emit a DW_OP_breg operation.
Definition DwarfExpression.cpp:56
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ DW_OP_LLVM_entry_value
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_zext
Only used in LLVM metadata.
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
@ DW_OP_LLVM_convert
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_sext
Only used in LLVM metadata.
This is an optimization pass for GlobalISel generic memory operations.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
Holds information about all subregisters comprising a register location.
static Register createRegister(int64_t RegNo, const char *Comment)
Create a full register, no extra DW_OP_piece operators necessary.
static Register createSubRegister(int64_t RegNo, unsigned SizeInBits, const char *Comment)
Create a subregister that needs a DW_OP_piece operator with SizeInBits.