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 && && !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 () {
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 ()
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) {
640 if (Tag == dwarf::DW_TAG_const_type) {
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;
671 while (A && A.getTag() == dwarf::DW_TAG_array_type)
673 bool Leading =
674 ( || (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;
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