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 (addMachineReg(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();

474 for (; I != E; ++I)

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.