9#ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
10#define LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
44 std::string *OriginalFullName =
nullptr);
47 bool SkipFirstParamIfArtificial =
false);
58 std::string *OriginalFullName =
nullptr);
61 bool SkipFirstParamIfArtificial,
bool Const,
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:
83template <
typename DieType>
86 static constexpr StringRef Prefix =
"DW_TAG_";
87 static constexpr StringRef Suffix =
"_type";
91 TagStr.
size() - (Prefix.size() + Suffix.
size()))
95template <
typename DieType>
97 for (
const DieType &
C :
D.children()) {
98 if (
C.getTag() != dwarf::DW_TAG_subrange_type)
100 std::optional<uint64_t> LB;
101 std::optional<uint64_t> Count;
102 std::optional<uint64_t> UB;
103 std::optional<unsigned> DefaultLB;
104 if (std::optional<typename DieType::DWARFFormValue> L =
105 C.find(dwarf::DW_AT_lower_bound))
106 LB = L->getAsUnsignedConstant();
107 if (std::optional<typename DieType::DWARFFormValue> CountV =
108 C.find(dwarf::DW_AT_count))
109 Count = CountV->getAsUnsignedConstant();
110 if (std::optional<typename DieType::DWARFFormValue> UpperV =
111 C.find(dwarf::DW_AT_upper_bound))
112 UB = UpperV->getAsUnsignedConstant();
113 if (std::optional<uint64_t> LV =
D.getLanguage())
116 if (LB && *LB == *DefaultLB)
118 if (!LB && !Count && !UB)
120 else if (!LB && (Count || UB) && DefaultLB)
121 OS <<
'[' << (Count ? *Count : *UB - *DefaultLB + 1) <<
']';
133 OS <<
"? + " << *Count;
141 EndedWithTemplate =
false;
145template <
typename DieType>
148 return D.resolveReferencedType(Attr);
150template <
typename DieType>
152 return D.resolveReferencedType(
F);
154template <
typename DWARFFormValueType>
155const char *
toString(std::optional<DWARFFormValueType>
F) {
166template <
typename DieType>
168 while (
D && (
D.getTag() == dwarf::DW_TAG_const_type ||
169 D.getTag() == dwarf::DW_TAG_volatile_type))
174template <
typename DieType>
176 D = skipQualifiers(
D);
177 return D && (
D.getTag() == dwarf::DW_TAG_subroutine_type ||
178 D.getTag() == dwarf::DW_TAG_array_type);
181template <
typename DieType>
185 appendQualifiedNameBefore(Inner);
188 if (needsParens(Inner))
192 EndedWithTemplate =
false;
195template <
typename DieType>
197 DieType
D, std::string *OriginalFullName) {
207 case dwarf::DW_TAG_pointer_type: {
208 appendPointerLikeTypeBefore(
D, Inner(),
"*");
211 case dwarf::DW_TAG_subroutine_type: {
212 appendQualifiedNameBefore(Inner());
219 case dwarf::DW_TAG_array_type: {
220 appendQualifiedNameBefore(Inner());
223 case dwarf::DW_TAG_reference_type:
224 appendPointerLikeTypeBefore(
D, Inner(),
"&");
226 case dwarf::DW_TAG_rvalue_reference_type:
227 appendPointerLikeTypeBefore(
D, Inner(),
"&&");
229 case dwarf::DW_TAG_ptr_to_member_type: {
230 appendQualifiedNameBefore(Inner());
231 if (needsParens(InnerDIE))
237 appendQualifiedName(Cont);
238 EndedWithTemplate =
false;
245 case dwarf::DW_TAG_LLVM_ptrauth_type:
246 appendQualifiedNameBefore(Inner());
248 case dwarf::DW_TAG_const_type:
249 case dwarf::DW_TAG_volatile_type:
250 appendConstVolatileQualifierBefore(
D);
252 case dwarf::DW_TAG_namespace: {
256 OS <<
"(anonymous namespace)";
259 case dwarf::DW_TAG_unspecified_type: {
261 if (TypeName ==
"decltype(nullptr)")
262 TypeName =
"std::nullptr_t";
265 EndedWithTemplate =
false;
277 appendTypeTagName(
D.getTag());
282 static constexpr StringRef MangledPrefix =
"_STN|";
283 if (
Name.consume_front(MangledPrefix)) {
284 auto Separator =
Name.find(
'|');
288 if (OriginalFullName)
292 EndedWithTemplate =
Name.ends_with(
">");
297 if (
Name.ends_with(
">"))
299 if (!appendTemplateParameters(
D))
302 if (EndedWithTemplate)
305 EndedWithTemplate =
true;
313template <
typename DieType>
315 DieType
D, DieType Inner,
bool SkipFirstParamIfArtificial) {
318 switch (
D.getTag()) {
319 case dwarf::DW_TAG_subroutine_type: {
320 appendSubroutineNameAfter(
D, Inner, SkipFirstParamIfArtificial,
false,
324 case dwarf::DW_TAG_array_type: {
328 case dwarf::DW_TAG_const_type:
329 case dwarf::DW_TAG_volatile_type:
330 appendConstVolatileQualifierAfter(
D);
332 case dwarf::DW_TAG_ptr_to_member_type:
333 case dwarf::DW_TAG_reference_type:
334 case dwarf::DW_TAG_rvalue_reference_type:
335 case dwarf::DW_TAG_pointer_type: {
336 if (needsParens(Inner))
340 dwarf::DW_TAG_ptr_to_member_type);
343 case dwarf::DW_TAG_LLVM_ptrauth_type: {
345 if (
auto Form =
D.find(Attr))
346 return *Form->getAsUnsignedConstant();
350 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
352 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))
353 optionsVec.
push_back(
"authenticates-null-values");
354 if (
auto AuthenticationMode =
355 D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {
356 switch (*AuthenticationMode->getAsUnsignedConstant()) {
370 for (
const auto *option : optionsVec) {
376 options =
", \"" + options +
"\"";
377 std::string PtrauthString;
380 <<
"__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) <<
", "
381 << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
384 getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
387 OS << PtrauthStream.
str();
402template <
typename DieType>
404 if (
D && scopedTAGs(
D.getTag()))
405 appendScopes(
D.getParent());
406 appendUnqualifiedName(
D);
409template <
typename DieType>
411 if (
D && scopedTAGs(
D.getTag()))
412 appendScopes(
D.getParent());
413 return appendUnqualifiedNameBefore(
D);
416template <
typename DieType>
418 bool *FirstParameter) {
419 bool FirstParameterValue =
true;
420 bool IsTemplate =
false;
422 FirstParameter = &FirstParameterValue;
423 for (
const DieType &
C :
D) {
430 EndedWithTemplate =
false;
431 *FirstParameter =
false;
433 if (
C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
435 appendTemplateParameters(
C, FirstParameter);
437 if (
C.getTag() == dwarf::DW_TAG_template_value_parameter) {
440 if (
T.getTag() == dwarf::DW_TAG_enumeration_type) {
442 appendQualifiedName(
T);
444 auto V =
C.find(dwarf::DW_AT_const_value);
445 OS << std::to_string(*V->getAsSignedConstant());
451 if (
T.getTag() == dwarf::DW_TAG_pointer_type ||
452 T.getTag() == dwarf::DW_TAG_reference_type)
457 auto V =
C.find(dwarf::DW_AT_const_value);
458 bool IsQualifiedChar =
false;
459 if (
Name ==
"bool") {
460 OS << (*V->getAsUnsignedConstant() ?
"true" :
"false");
461 }
else if (
Name ==
"short") {
463 OS << std::to_string(*V->getAsSignedConstant());
464 }
else if (
Name ==
"unsigned short") {
465 OS <<
"(unsigned short)";
466 OS << std::to_string(*V->getAsSignedConstant());
467 }
else if (
Name ==
"int")
468 OS << std::to_string(*V->getAsSignedConstant());
469 else if (
Name ==
"long") {
470 OS << std::to_string(*V->getAsSignedConstant());
472 }
else if (
Name ==
"long long") {
473 OS << std::to_string(*V->getAsSignedConstant());
475 }
else if (
Name ==
"unsigned int") {
476 OS << std::to_string(*V->getAsUnsignedConstant());
478 }
else if (
Name ==
"unsigned long") {
479 OS << std::to_string(*V->getAsUnsignedConstant());
481 }
else if (
Name ==
"unsigned long long") {
482 OS << std::to_string(*V->getAsUnsignedConstant());
484 }
else if (
Name ==
"char" ||
486 (
Name ==
"unsigned char" ||
Name ==
"signed char"))) {
489 auto Val = *V->getAsSignedConstant();
494 if (IsQualifiedChar) {
529 if ((Val & ~0xFFu) == ~0xFFu)
531 if (Val < 127 && Val >= 32) {
535 }
else if (Val < 256)
537 else if (Val <= 0xFFFF)
545 if (
C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
546 const char *RawName =
554 if (
C.getTag() != dwarf::DW_TAG_template_type_parameter)
556 auto TypeAttr =
C.find(dwarf::DW_AT_type);
561 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
563 EndedWithTemplate =
false;
568template <
typename DieType>
571 bool R = appendTemplateParameters(
D);
575 if (EndedWithTemplate)
578 EndedWithTemplate =
true;
582template <
typename DieType>
584 DieType &
C, DieType &V) {
585 (
N.getTag() == dwarf::DW_TAG_const_type ?
C : V) =
N;
588 auto Tag =
T.getTag();
589 if (
Tag == dwarf::DW_TAG_const_type) {
592 }
else if (
Tag == dwarf::DW_TAG_volatile_type) {
599template <
typename DieType>
604 decomposeConstVolatile(
N,
T,
C, V);
605 if (
T &&
T.getTag() == dwarf::DW_TAG_subroutine_type)
607 static_cast<bool>(
C),
static_cast<bool>(V));
612template <
typename DieType>
617 decomposeConstVolatile(
N,
T,
C, V);
618 bool Subroutine =
T &&
T.getTag() == dwarf::DW_TAG_subroutine_type;
620 while (
A &&
A.getTag() == dwarf::DW_TAG_array_type)
623 (!
A || (
A.getTag() != dwarf::DW_TAG_pointer_type &&
624 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
632 appendQualifiedNameBefore(
T);
633 if (!Leading && !Subroutine) {
645template <
typename DieType>
647 DieType
D, std::string *OriginalFullName) {
650 DieType Inner = appendUnqualifiedNameBefore(
D, OriginalFullName);
651 appendUnqualifiedNameAfter(
D, Inner);
654template <
typename DieType>
656 DieType
D, DieType Inner,
bool SkipFirstParamIfArtificial,
bool Const,
658 DieType FirstParamIfArtificial;
660 EndedWithTemplate =
false;
662 bool RealFirst =
true;
663 for (DieType
P :
D) {
664 if (
P.getTag() != dwarf::DW_TAG_formal_parameter &&
665 P.getTag() != dwarf::DW_TAG_unspecified_parameters)
668 if (SkipFirstParamIfArtificial && RealFirst &&
669 P.find(dwarf::DW_AT_artificial)) {
670 FirstParamIfArtificial =
T;
678 if (
P.getTag() == dwarf::DW_TAG_unspecified_parameters)
681 appendQualifiedName(
T);
683 EndedWithTemplate =
false;
685 if (FirstParamIfArtificial) {
686 if (DieType
P = FirstParamIfArtificial) {
687 if (
P.getTag() == dwarf::DW_TAG_pointer_type) {
688 auto CVStep = [&](DieType CV) {
690 Const |= U.getTag() == dwarf::DW_TAG_const_type;
691 Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
696 if (DieType CV = CVStep(
P)) {
703 if (
auto CC =
D.find(dwarf::DW_AT_calling_convention)) {
704 switch (*
CC->getAsUnsignedConstant()) {
705 case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
706 OS <<
" __attribute__((stdcall))";
708 case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
709 OS <<
" __attribute__((fastcall))";
711 case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
712 OS <<
" __attribute__((thiscall))";
714 case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
715 OS <<
" __attribute__((vectorcall))";
717 case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
718 OS <<
" __attribute__((pascal))";
720 case dwarf::CallingConvention::DW_CC_LLVM_Win64:
721 OS <<
" __attribute__((ms_abi))";
723 case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
724 OS <<
" __attribute__((sysv_abi))";
726 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
728 OS <<
" __attribute__((pcs(\"aapcs\")))";
730 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
731 OS <<
" __attribute__((pcs(\"aapcs-vfp\")))";
733 case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
734 OS <<
" __attribute__((intel_ocl_bicc))";
736 case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
737 case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
744 case dwarf::CallingConvention::DW_CC_LLVM_Swift:
746 OS <<
" __attribute__((swiftcall))";
748 case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
749 OS <<
" __attribute__((preserve_most))";
751 case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
752 OS <<
" __attribute__((preserve_all))";
754 case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
755 OS <<
" __attribute__((preserve_none))";
757 case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
758 OS <<
" __attribute__((regcall))";
760 case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
761 OS <<
" __attribute__((m68k_rtd))";
770 if (
D.find(dwarf::DW_AT_reference))
772 if (
D.find(dwarf::DW_AT_rvalue_reference))
778template <
typename DieType>
780 if (
D.getTag() == dwarf::DW_TAG_compile_unit)
782 if (
D.getTag() == dwarf::DW_TAG_type_unit)
784 if (
D.getTag() == dwarf::DW_TAG_skeleton_unit)
786 if (
D.getTag() == dwarf::DW_TAG_subprogram)
788 if (
D.getTag() == dwarf::DW_TAG_lexical_block)
790 D =
D.resolveTypeUnitReference();
791 if (DieType
P =
D.getParent())
793 appendUnqualifiedName(
D);
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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.
static constexpr size_t npos
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)
DieType resolveReferencedType(DieType D, dwarf::Attribute Attr=dwarf::DW_AT_type)
This is an optimization pass for GlobalISel generic memory operations.
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.
bool needsParens(DieType D)
void appendArrayType(const DieType &D)
DieType appendQualifiedNameBefore(DieType D)
void appendQualifiedName(DieType D)
void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V)
DieType skipQualifiers(DieType D)
void appendUnqualifiedName(DieType D, std::string *OriginalFullName=nullptr)
Recursively append the DIE type name when applicable.
void appendConstVolatileQualifierBefore(DieType N)
void appendScopes(DieType D)
DWARFTypePrinter(raw_ostream &OS)
void appendSubroutineNameAfter(DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const, bool Volatile)
bool appendTemplateParameters(DieType D, bool *FirstParameter=nullptr)
void appendConstVolatileQualifierAfter(DieType N)
void appendAndTerminateTemplateParameters(DieType D)
void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr)
void appendUnqualifiedNameAfter(DieType D, DieType Inner, bool SkipFirstParamIfArtificial=false)
DieType appendUnqualifiedNameBefore(DieType D, std::string *OriginalFullName=nullptr)