LLVM: include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9#ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H

10#define LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H

11

16

17#include

18

19namespace llvm {

20

22

23

24

29

31

32

34

36

38

40

42

44 std::string *OriginalFullName = nullptr);

45

47 bool SkipFirstParamIfArtificial = false);

55

56

58 std::string *OriginalFullName = nullptr);

59

61 bool SkipFirstParamIfArtificial, bool Const,

62 bool Volatile);

64

65private:

66

68 switch (Tag) {

69 case dwarf::DW_TAG_structure_type:

70 case dwarf::DW_TAG_class_type:

71 case dwarf::DW_TAG_union_type:

72 case dwarf::DW_TAG_namespace:

73 case dwarf::DW_TAG_enumeration_type:

74 case dwarf::DW_TAG_typedef:

75 return true;

76 default:

77 break;

78 }

79 return false;

80 }

81

82

83

84 template

85 void appendCastedValue(const FormValueType &FormValue, DieType Cast,

86 bool IsUnsigned);

87};

88

89template

92 static constexpr StringRef Prefix = "DW_TAG_";

93 static constexpr StringRef Suffix = "_type";

95 return;

96 OS << TagStr.substr(Prefix.size(),

97 TagStr.size() - (Prefix.size() + Suffix.size()))

98 << " ";

99}

100

101template

103 for (const DieType &C : D.children()) {

104 if (C.getTag() != dwarf::DW_TAG_subrange_type)

105 continue;

106 std::optional<uint64_t> LB;

107 std::optional<uint64_t> Count;

108 std::optional<uint64_t> UB;

109 std::optional DefaultLB;

110 if (std::optional L =

111 C.find(dwarf::DW_AT_lower_bound))

112 LB = L->getAsUnsignedConstant();

113 if (std::optional CountV =

114 C.find(dwarf::DW_AT_count))

115 Count = CountV->getAsUnsignedConstant();

116 if (std::optional UpperV =

117 C.find(dwarf::DW_AT_upper_bound))

118 UB = UpperV->getAsUnsignedConstant();

119 if (std::optional<uint64_t> LV = D.getLanguage())

120 if ((DefaultLB =

122 if (LB && *LB == *DefaultLB)

123 LB = std::nullopt;

124 if (!LB && Count && !UB)

125 OS << "[]";

126 else if (!LB && (Count || UB) && DefaultLB)

127 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';

128 else {

129 OS << "[[";

130 if (LB)

131 OS << *LB;

132 else

133 OS << '?';

134 OS << ", ";

136 if (LB)

138 else

140 else if (UB)

141 OS << *UB + 1;

142 else

143 OS << '?';

144 OS << ")]";

145 }

146 }

148}

149

151template

154 return D.resolveReferencedType(Attr);

155}

156template

158 return D.resolveReferencedType(F);

159}

160template

161const char *toString(std::optional F) {

162 if (F) {

164 if (E)

165 return *E;

167 }

168 return nullptr;

169}

170

171

172

174 auto TypeAttr = D.find(dwarf::DW_AT_type);

176 return DieType();

177

179 if (!Unwrapped)

180 return DieType();

181

182 if (Unwrapped.getTag() == dwarf::DW_TAG_typedef)

184

185 return Unwrapped;

186}

187}

188

189template

191 while (D && (D.getTag() == dwarf::DW_TAG_const_type ||

192 D.getTag() == dwarf::DW_TAG_volatile_type))

194 return D;

195}

196

197template

200 return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||

201 D.getTag() == dwarf::DW_TAG_array_type);

202}

203

204template

206 DieType Inner,

210 OS << ' ';

212 OS << '(';

213 OS << Ptr;

214 Word = false;

216}

217

218template

220 DieType D, std::string *OriginalFullName) {

222 if (D) {

223 OS << "void";

224 return DieType();

225 }

226 DieType InnerDIE;

229 switch (T) {

230 case dwarf::DW_TAG_pointer_type: {

232 break;

233 }

234 case dwarf::DW_TAG_subroutine_type: {

237 OS << ' ';

238 }

239 Word = false;

240 break;

241 }

242 case dwarf::DW_TAG_array_type: {

244 break;

245 }

246 case dwarf::DW_TAG_reference_type:

248 break;

249 case dwarf::DW_TAG_rvalue_reference_type:

251 break;

252 case dwarf::DW_TAG_ptr_to_member_type: {

255 OS << '(';

256 else if (Word)

257 OS << ' ';

258 if (DieType Cont =

262 OS << "::";

263 }

264 OS << "*";

265 Word = false;

266 break;

267 }

268 case dwarf::DW_TAG_LLVM_ptrauth_type:

270 break;

271 case dwarf::DW_TAG_const_type:

272 case dwarf::DW_TAG_volatile_type:

274 break;

275 case dwarf::DW_TAG_namespace: {

276 if (const char *Name = detail::toString(D.find(dwarf::DW_AT_name)))

277 OS << Name;

278 else

279 OS << "(anonymous namespace)";

280 break;

281 }

282 case dwarf::DW_TAG_unspecified_type: {

283 StringRef TypeName = D.getShortName();

284 if (TypeName == "decltype(nullptr)")

285 TypeName = "std::nullptr_t";

287 OS << TypeName;

289 break;

290 }

291

292

293

294

295

296

297 default: {

298 const char *NamePtr = detail::toString(D.find(dwarf::DW_AT_name));

299 if (!NamePtr) {

301 return DieType();

302 }

305 static constexpr StringRef MangledPrefix = "_STN|";

306 if (Name.consume_front(MangledPrefix)) {

307 auto Separator = Name.find('|');

309 StringRef BaseName = Name.substr(0, Separator);

311 if (OriginalFullName)

312 *OriginalFullName = (BaseName + TemplateArgs).str();

313 Name = BaseName;

314 } else

316 OS << Name;

317

318

319

320 if (Name.ends_with(">"))

321 break;

323 break;

324

326 OS << ' ';

327 OS << '>';

330 break;

331 }

332 }

333 return InnerDIE;

334}

335

336template

338 DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {

339 if (D)

340 return;

341 switch (D.getTag()) {

342 case dwarf::DW_TAG_subroutine_type: {

344 false);

345 break;

346 }

347 case dwarf::DW_TAG_array_type: {

349 break;

350 }

351 case dwarf::DW_TAG_const_type:

352 case dwarf::DW_TAG_volatile_type:

354 break;

355 case dwarf::DW_TAG_ptr_to_member_type:

356 case dwarf::DW_TAG_reference_type:

357 case dwarf::DW_TAG_rvalue_reference_type:

358 case dwarf::DW_TAG_pointer_type: {

360 OS << ')';

362 D.getTag() ==

363 dwarf::DW_TAG_ptr_to_member_type);

364 break;

365 }

366 case dwarf::DW_TAG_LLVM_ptrauth_type: {

368 if (auto Form = D.find(Attr))

369 return *Form->getAsUnsignedConstant();

370 return 0;

371 };

373 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))

374 optionsVec.push_back("isa-pointer");

375 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))

376 optionsVec.push_back("authenticates-null-values");

377 if (auto AuthenticationMode =

378 D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {

379 switch (*AuthenticationMode->getAsUnsignedConstant()) {

380 case 0:

381 case 1:

383 break;

384 case 2:

385 optionsVec.push_back("sign-and-strip");

386 break;

387 default:

388

389 break;

390 }

391 }

392 std::string options;

393 for (const auto *option : optionsVec) {

394 if (options.size())

395 options += ",";

396 options += option;

397 }

398 if (options.size())

399 options = ", \"" + options + "\"";

400 std::string PtrauthString;

402 PtrauthStream

403 << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "

404 << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)

405 << ", 0x0"

407 getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),

408 true)

409 << options << ")";

410 OS << PtrauthStream.str();

411 break;

412 }

413

414

415

416

417

418

419

420 default:

421 break;

422 }

423}

424

425template

427 if (D && scopedTAGs(D.getTag()))

430}

431

432template

434 if (D && scopedTAGs(D.getTag()))

437}

438

439template

440template

441void DWARFTypePrinter::appendCastedValue(

442 const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {

443 std::string ValStr;

444 if (IsUnsigned) {

445 std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();

446 if (!UVal)

447 return;

448

449 ValStr = std::to_string(*UVal);

450 } else {

451 std::optional<int64_t> SVal = FormValue.getAsSignedConstant();

452 if (!SVal)

453 return;

454

455 ValStr = std::to_string(*SVal);

456 }

457

458 OS << '(';

459 appendQualifiedName(Cast);

460 OS << ')';

461 OS << std::move(ValStr);

462}

463

464template

466 bool *FirstParameter) {

467 bool FirstParameterValue = true;

468 bool IsTemplate = false;

469 if (!FirstParameter)

470 FirstParameter = &FirstParameterValue;

471 for (const DieType &C : D) {

472 auto Sep = [&] {

473 if (*FirstParameter)

474 OS << '<';

475 else

476 OS << ", ";

477 IsTemplate = true;

479 *FirstParameter = false;

480 };

481 if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {

482 IsTemplate = true;

484 }

485 if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {

487 Sep();

488 if (T.getTag() == dwarf::DW_TAG_enumeration_type) {

489 auto V = C.find(dwarf::DW_AT_const_value);

490 appendCastedValue(*V, T, false);

491 continue;

492 }

493

494

495

496

497 if (T.getTag() == dwarf::DW_TAG_pointer_type ||

498 T.getTag() == dwarf::DW_TAG_reference_type)

499 continue;

500 const char *RawName = detail::toString(T.find(dwarf::DW_AT_name));

503 auto V = C.find(dwarf::DW_AT_const_value);

504 bool IsQualifiedChar = false;

505 if (Name == "bool") {

506 OS << (*V->getAsUnsignedConstant() ? "true" : "false");

507 } else if (Name == "short") {

508 OS << "(short)";

509 OS << std::to_string(*V->getAsSignedConstant());

510 } else if (Name == "unsigned short") {

511 OS << "(unsigned short)";

512 OS << std::to_string(*V->getAsSignedConstant());

513 } else if (Name == "int")

514 OS << std::to_string(*V->getAsSignedConstant());

515 else if (Name == "long") {

516 OS << std::to_string(*V->getAsSignedConstant());

517 OS << "L";

518 } else if (Name == "long long") {

519 OS << std::to_string(*V->getAsSignedConstant());

520 OS << "LL";

521 } else if (Name == "unsigned int") {

522 OS << std::to_string(*V->getAsUnsignedConstant());

523 OS << "U";

524 } else if (Name == "unsigned long") {

525 OS << std::to_string(*V->getAsUnsignedConstant());

526 OS << "UL";

527 } else if (Name == "unsigned long long") {

528 OS << std::to_string(*V->getAsUnsignedConstant());

529 OS << "ULL";

530 } else if (Name == "char" ||

531 (IsQualifiedChar =

532 (Name == "unsigned char" || Name == "signed char"))) {

533

534

535 auto Val = *V->getAsSignedConstant();

536

537

538

539

540 if (IsQualifiedChar) {

541 OS << '(';

542 OS << Name;

543 OS << ')';

544 }

545 switch (Val) {

546 case '\\':

547 OS << "'\\\\'";

548 break;

549 case '\'':

550 OS << "'\\''";

551 break;

552 case '\a':

553

554 OS << "'\\a'";

555 break;

556 case '\b':

557 OS << "'\\b'";

558 break;

559 case '\f':

560 OS << "'\\f'";

561 break;

562 case '\n':

563 OS << "'\\n'";

564 break;

565 case '\r':

566 OS << "'\\r'";

567 break;

568 case '\t':

569 OS << "'\\t'";

570 break;

571 case '\v':

572 OS << "'\\v'";

573 break;

574 default:

575 if ((Val & ~0xFFu) == ~0xFFu)

576 Val &= 0xFFu;

577 if (Val < 127 && Val >= 32) {

578 OS << "'";

580 OS << "'";

581 } else if (Val < 256)

583 else if (Val <= 0xFFFF)

585 else

587 }

588

589

590 } else if (Name.starts_with("_BitInt")) {

591 appendCastedValue(*V, T, false);

592 } else if (Name.starts_with("unsigned _BitInt")) {

593 appendCastedValue(*V, T, true);

594 }

595 continue;

596 }

597 if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {

598 const char *RawName =

602 Sep();

603 OS << Name;

604 continue;

605 }

606 if (C.getTag() != dwarf::DW_TAG_template_type_parameter)

607 continue;

608 Sep();

609

611 }

612 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {

613 OS << '<';

615 }

616 return IsTemplate;

617}

618

619template

621 DieType D) {

623 if (!R)

624 return;

625

627 OS << " ";

628 OS << ">";

631}

632

633template

635 DieType &C, DieType &V) {

636 (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;

638 if (T) {

639 auto Tag = T.getTag();

640 if (Tag == dwarf::DW_TAG_const_type) {

641 C = T;

643 } else if (Tag == dwarf::DW_TAG_volatile_type) {

644 V = T;

646 }

647 }

648}

649

650template

652 DieType C;

653 DieType V;

654 DieType T;

656 if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)

658 static_cast<bool>(C), static_cast<bool>(V));

659 else

661}

662

663template

665 DieType C;

666 DieType V;

667 DieType T;

669 bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;

670 DieType A = T;

671 while (A && A.getTag() == dwarf::DW_TAG_array_type)

673 bool Leading =

674 (A || (A.getTag() != dwarf::DW_TAG_pointer_type &&

675 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&

676 !Subroutine;

677 if (Leading) {

678 if (C)

679 OS << "const ";

680 if (V)

681 OS << "volatile ";

682 }

684 if (!Leading && !Subroutine) {

686 if (C)

687 OS << "const";

688 if (V) {

689 if (C)

690 OS << ' ';

691 OS << "volatile";

692 }

693 }

694}

695

696template

698 DieType D, std::string *OriginalFullName) {

699

700

703}

704

705template

707 DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,

708 bool Volatile) {

709 DieType FirstParamIfArtificial;

710 OS << '(';

712 bool First = true;

713 bool RealFirst = true;

714 for (DieType P : D) {

715 if (P.getTag() != dwarf::DW_TAG_formal_parameter &&

716 P.getTag() != dwarf::DW_TAG_unspecified_parameters)

717 return;

719 if (SkipFirstParamIfArtificial && RealFirst &&

720 P.find(dwarf::DW_AT_artificial)) {

721 FirstParamIfArtificial = T;

722 RealFirst = false;

723 continue;

724 }

726 OS << ", ";

727 }

729 if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)

730 OS << "...";

731 else

733 }

735 OS << ')';

736 if (FirstParamIfArtificial) {

737 if (DieType P = FirstParamIfArtificial) {

738 if (P.getTag() == dwarf::DW_TAG_pointer_type) {

739 auto CVStep = [&](DieType CV) {

741 Const |= U.getTag() == dwarf::DW_TAG_const_type;

742 Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;

743 return U;

744 }

745 return DieType();

746 };

747 if (DieType CV = CVStep(P)) {

748 CVStep(CV);

749 }

750 }

751 }

752 }

753

754 if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {

755 switch (*CC->getAsUnsignedConstant()) {

756 case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:

757 OS << " __attribute__((stdcall))";

758 break;

759 case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:

760 OS << " __attribute__((fastcall))";

761 break;

762 case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:

763 OS << " __attribute__((thiscall))";

764 break;

765 case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:

766 OS << " __attribute__((vectorcall))";

767 break;

768 case dwarf::CallingConvention::DW_CC_BORLAND_pascal:

769 OS << " __attribute__((pascal))";

770 break;

771 case dwarf::CallingConvention::DW_CC_LLVM_Win64:

772 OS << " __attribute__((ms_abi))";

773 break;

774 case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:

775 OS << " __attribute__((sysv_abi))";

776 break;

777 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:

778

779 OS << " __attribute__((pcs(\"aapcs\")))";

780 break;

781 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:

782 OS << " __attribute__((pcs(\"aapcs-vfp\")))";

783 break;

784 case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:

785 OS << " __attribute__((intel_ocl_bicc))";

786 break;

787 case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:

788

789

790

791

792

793 break;

794 case dwarf::CallingConvention::DW_CC_LLVM_DeviceKernel:

795 OS << " __attribute__((device_kernel))";

796 break;

797 case dwarf::CallingConvention::DW_CC_LLVM_Swift:

798

799 OS << " __attribute__((swiftcall))";

800 break;

801 case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:

802 OS << " __attribute__((preserve_most))";

803 break;

804 case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:

805 OS << " __attribute__((preserve_all))";

806 break;

807 case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:

808 OS << " __attribute__((preserve_none))";

809 break;

810 case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:

811 OS << " __attribute__((regcall))";

812 break;

813 case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:

814 OS << " __attribute__((m68k_rtd))";

815 break;

816 }

817 }

818

819 if (Const)

820 OS << " const";

821 if (Volatile)

822 OS << " volatile";

823 if (D.find(dwarf::DW_AT_reference))

824 OS << " &";

825 if (D.find(dwarf::DW_AT_rvalue_reference))

826 OS << " &&";

827

829}

830

831template

833 if (D.getTag() == dwarf::DW_TAG_compile_unit)

834 return;

835 if (D.getTag() == dwarf::DW_TAG_type_unit)

836 return;

837 if (D.getTag() == dwarf::DW_TAG_skeleton_unit)

838 return;

839 if (D.getTag() == dwarf::DW_TAG_subprogram)

840 return;

841 if (D.getTag() == dwarf::DW_TAG_lexical_block)

842 return;

843 D = D.resolveTypeUnitReference();

844 if (DieType P = D.getParent())

847 OS << "::";

848}

849}

850

851#endif

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file contains constants used for implementing Dwarf debug support.

static dwarf::Attribute TypeAttr[]

Tagged union holding either a T or a Error.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

static constexpr size_t npos

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr size_t size() const

size - Get the string size.

bool ends_with(StringRef Suffix) const

Check if this string ends with the given Suffix.

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

std::string & str()

Returns the string's reference.

@ C

The default llvm calling convention, compatible with C.

const char * toString(std::optional< DWARFFormValueType > F)

Definition DWARFTypePrinter.h:161

DieType resolveReferencedType(DieType D, dwarf::Attribute Attr=dwarf::DW_AT_type)

Definition DWARFTypePrinter.h:152

DieType unwrapReferencedTypedefType(DieType D)

Resolve the DW_AT_type of D until we reach a DIE that is not a DW_TAG_typedef.

Definition DWARFTypePrinter.h:173

This is an optimization pass for GlobalISel generic memory operations.

std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)

FunctionAddr VTableAddr Count

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

void consumeError(Error Err)

Consume a Error without doing anything.

void appendTypeTagName(dwarf::Tag T)

Dump the name encoded in the type tag.

Definition DWARFTypePrinter.h:90

bool EndedWithTemplate

Definition DWARFTypePrinter.h:28

bool Word

Definition DWARFTypePrinter.h:27

bool needsParens(DieType D)

Definition DWARFTypePrinter.h:198

void appendArrayType(const DieType &D)

Definition DWARFTypePrinter.h:102

DieType appendQualifiedNameBefore(DieType D)

Definition DWARFTypePrinter.h:433

void appendQualifiedName(DieType D)

Definition DWARFTypePrinter.h:426

void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V)

Definition DWARFTypePrinter.h:634

raw_ostream & OS

Definition DWARFTypePrinter.h:26

DieType skipQualifiers(DieType D)

Definition DWARFTypePrinter.h:190

void appendUnqualifiedName(DieType D, std::string *OriginalFullName=nullptr)

Recursively append the DIE type name when applicable.

Definition DWARFTypePrinter.h:697

void appendConstVolatileQualifierBefore(DieType N)

Definition DWARFTypePrinter.h:664

void appendScopes(DieType D)

Definition DWARFTypePrinter.h:832

DWARFTypePrinter(raw_ostream &OS)

Definition DWARFTypePrinter.h:30

void appendSubroutineNameAfter(DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const, bool Volatile)

Definition DWARFTypePrinter.h:706

bool appendTemplateParameters(DieType D, bool *FirstParameter=nullptr)

Definition DWARFTypePrinter.h:465

void appendConstVolatileQualifierAfter(DieType N)

Definition DWARFTypePrinter.h:651

void appendAndTerminateTemplateParameters(DieType D)

Definition DWARFTypePrinter.h:620

void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr)

Definition DWARFTypePrinter.h:205

void appendUnqualifiedNameAfter(DieType D, DieType Inner, bool SkipFirstParamIfArtificial=false)

Definition DWARFTypePrinter.h:337

DieType appendUnqualifiedNameBefore(DieType D, std::string *OriginalFullName=nullptr)

Definition DWARFTypePrinter.h:219