9#ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
10#define LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
46 std::string *OriginalFullName =
nullptr);
49 bool SkipFirstParamIfArtificial =
false);
60 std::string *OriginalFullName =
nullptr);
63 bool SkipFirstParamIfArtificial,
bool Const,
71 case dwarf::DW_TAG_structure_type:
72 case dwarf::DW_TAG_class_type:
73 case dwarf::DW_TAG_union_type:
74 case dwarf::DW_TAG_namespace:
75 case dwarf::DW_TAG_enumeration_type:
76 case dwarf::DW_TAG_typedef:
86 template <
typename FormValueType>
87 void appendCastedValue(
const FormValueType &FormValue, DieType Cast,
91template <
typename DieType>
94 static constexpr StringRef Prefix =
"DW_TAG_";
95 static constexpr StringRef Suffix =
"_type";
99 TagStr.
size() - (Prefix.size() + Suffix.
size()))
103template <
typename DieType>
105 for (
const DieType &
C :
D.children()) {
106 if (
C.getTag() != dwarf::DW_TAG_subrange_type)
108 std::optional<uint64_t> LB;
109 std::optional<uint64_t>
Count;
110 std::optional<uint64_t> UB;
111 std::optional<unsigned> DefaultLB;
112 if (std::optional<typename DieType::DWARFFormValue> L =
113 C.find(dwarf::DW_AT_lower_bound))
114 LB = L->getAsUnsignedConstant();
115 if (std::optional<typename DieType::DWARFFormValue> CountV =
116 C.find(dwarf::DW_AT_count))
117 Count = CountV->getAsUnsignedConstant();
118 if (std::optional<typename DieType::DWARFFormValue> UpperV =
119 C.find(dwarf::DW_AT_upper_bound))
120 UB = UpperV->getAsUnsignedConstant();
121 if (std::optional<uint64_t> LV =
D.getLanguage())
124 if (LB && *LB == *DefaultLB)
126 if (!LB && !
Count && !UB)
128 else if (!LB && (
Count || UB) && DefaultLB)
129 OS <<
'[' << (
Count ? *
Count : *UB - *DefaultLB + 1) <<
']';
153template <
typename DieType>
156 return D.resolveReferencedType(Attr);
158template <
typename DieType>
160 return D.resolveReferencedType(
F);
162template <
typename DWARFFormValueType>
163const char *
toString(std::optional<DWARFFormValueType>
F) {
179 auto TypeAttr =
D.find(dwarf::DW_AT_type);
184 if (!Unwrapped || Unwrapped.getTag() != dwarf::DW_TAG_typedef)
187 if (!Visited.
insert(Unwrapped.getOffset()).second) {
189 <<
"typedef cycle detected: DW_TAG_typedef at offset 0x"
191 <<
" references itself through DW_TAG_typedef chain\n";
200template <
typename DieType>
202 while (
D && (
D.getTag() == dwarf::DW_TAG_const_type ||
203 D.getTag() == dwarf::DW_TAG_volatile_type))
208template <
typename DieType>
211 return D && (
D.getTag() == dwarf::DW_TAG_subroutine_type ||
212 D.getTag() == dwarf::DW_TAG_array_type);
215template <
typename DieType>
229template <
typename DieType>
231 DieType
D, std::string *OriginalFullName) {
241 case dwarf::DW_TAG_pointer_type: {
245 case dwarf::DW_TAG_subroutine_type: {
253 case dwarf::DW_TAG_array_type: {
257 case dwarf::DW_TAG_reference_type:
260 case dwarf::DW_TAG_rvalue_reference_type:
263 case dwarf::DW_TAG_ptr_to_member_type: {
279 case dwarf::DW_TAG_LLVM_ptrauth_type:
282 case dwarf::DW_TAG_const_type:
283 case dwarf::DW_TAG_volatile_type:
286 case dwarf::DW_TAG_namespace: {
290 OS <<
"(anonymous namespace)";
293 case dwarf::DW_TAG_unspecified_type: {
295 if (TypeName ==
"decltype(nullptr)")
296 TypeName =
"std::nullptr_t";
316 static constexpr StringRef MangledPrefix =
"_STN|";
317 if (Name.consume_front(MangledPrefix)) {
318 auto Separator = Name.find(
'|');
320 StringRef BaseName = Name.substr(0, Separator);
322 if (OriginalFullName)
331 if (Name.ends_with(
">"))
347template <
typename DieType>
349 DieType
D, DieType Inner,
bool SkipFirstParamIfArtificial) {
352 switch (
D.getTag()) {
353 case dwarf::DW_TAG_subroutine_type: {
358 case dwarf::DW_TAG_array_type: {
362 case dwarf::DW_TAG_const_type:
363 case dwarf::DW_TAG_volatile_type:
366 case dwarf::DW_TAG_ptr_to_member_type:
367 case dwarf::DW_TAG_reference_type:
368 case dwarf::DW_TAG_rvalue_reference_type:
369 case dwarf::DW_TAG_pointer_type: {
374 dwarf::DW_TAG_ptr_to_member_type);
377 case dwarf::DW_TAG_LLVM_ptrauth_type: {
379 if (
auto Form =
D.find(Attr))
380 return *Form->getAsUnsignedConstant();
384 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
386 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))
387 optionsVec.
push_back(
"authenticates-null-values");
388 if (
auto AuthenticationMode =
389 D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {
390 switch (*AuthenticationMode->getAsUnsignedConstant()) {
404 for (
const auto *option : optionsVec) {
410 options =
", \"" + options +
"\"";
411 std::string PtrauthString;
414 <<
"__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) <<
", "
415 << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
418 getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
421 OS << PtrauthStream.
str();
436template <
typename DieType>
438 if (
D && scopedTAGs(
D.getTag()))
443template <
typename DieType>
445 if (
D && scopedTAGs(
D.getTag()))
450template <
typename DieType>
451template <
typename FormValueType>
452void DWARFTypePrinter<DieType>::appendCastedValue(
453 const FormValueType &FormValue, DieType Cast,
bool IsUnsigned) {
456 std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
460 ValStr = std::to_string(*UVal);
462 std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
466 ValStr = std::to_string(*SVal);
470 appendQualifiedName(Cast);
472 OS << std::move(ValStr);
475template <
typename DieType>
477 bool *FirstParameter) {
478 bool FirstParameterValue =
true;
479 bool IsTemplate =
false;
481 FirstParameter = &FirstParameterValue;
482 for (
const DieType &
C :
D) {
490 *FirstParameter =
false;
492 if (
C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
496 if (
C.getTag() == dwarf::DW_TAG_template_value_parameter) {
499 if (
T.getTag() == dwarf::DW_TAG_enumeration_type) {
500 auto V =
C.find(dwarf::DW_AT_const_value);
501 appendCastedValue(*V,
T,
false);
508 if (
T.getTag() == dwarf::DW_TAG_pointer_type ||
509 T.getTag() == dwarf::DW_TAG_reference_type ||
510 T.getTag() == dwarf::DW_TAG_ptr_to_member_type)
515 auto V =
C.find(dwarf::DW_AT_const_value);
516 bool IsQualifiedChar =
false;
517 if (Name ==
"bool") {
518 OS << (*V->getAsUnsignedConstant() ?
"true" :
"false");
519 }
else if (Name ==
"short") {
521 OS << std::to_string(*V->getAsSignedConstant());
522 }
else if (Name ==
"unsigned short") {
523 OS <<
"(unsigned short)";
524 OS << std::to_string(*V->getAsSignedConstant());
525 }
else if (Name ==
"int")
526 OS << std::to_string(*V->getAsSignedConstant());
527 else if (Name ==
"long") {
528 OS << std::to_string(*V->getAsSignedConstant());
530 }
else if (Name ==
"long long") {
531 OS << std::to_string(*V->getAsSignedConstant());
533 }
else if (Name ==
"unsigned int") {
534 OS << std::to_string(*V->getAsUnsignedConstant());
536 }
else if (Name ==
"unsigned long") {
537 OS << std::to_string(*V->getAsUnsignedConstant());
539 }
else if (Name ==
"unsigned long long") {
540 OS << std::to_string(*V->getAsUnsignedConstant());
542 }
else if (Name ==
"char" ||
544 (Name ==
"unsigned char" || Name ==
"signed char"))) {
547 auto Val = *V->getAsSignedConstant();
552 if (IsQualifiedChar) {
587 if ((Val & ~0xFFu) == ~0xFFu)
589 if (Val < 127 && Val >= 32) {
593 }
else if (Val < 256)
595 else if (Val <= 0xFFFF)
602 }
else if (Name.starts_with(
"_BitInt")) {
603 appendCastedValue(*V,
T,
false);
604 }
else if (Name.starts_with(
"unsigned _BitInt")) {
605 appendCastedValue(*V,
T,
true);
609 if (
C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
610 const char *RawName =
618 if (
C.getTag() != dwarf::DW_TAG_template_type_parameter)
624 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
631template <
typename DieType>
645template <
typename DieType>
647 DieType &
C, DieType &V) {
648 (
N.getTag() == dwarf::DW_TAG_const_type ?
C : V) =
N;
651 auto Tag =
T.getTag();
652 if (
Tag == dwarf::DW_TAG_const_type) {
655 }
else if (
Tag == dwarf::DW_TAG_volatile_type) {
662template <
typename DieType>
668 if (
T &&
T.getTag() == dwarf::DW_TAG_subroutine_type)
670 static_cast<bool>(
C),
static_cast<bool>(V));
675template <
typename DieType>
681 bool Subroutine =
T &&
T.getTag() == dwarf::DW_TAG_subroutine_type;
683 while (
A &&
A.getTag() == dwarf::DW_TAG_array_type)
686 (!
A || (
A.getTag() != dwarf::DW_TAG_pointer_type &&
687 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
696 if (!Leading && !Subroutine) {
708template <
typename DieType>
710 DieType
D, std::string *OriginalFullName) {
717template <
typename DieType>
719 DieType
D, DieType Inner,
bool SkipFirstParamIfArtificial,
bool Const,
721 DieType FirstParamIfArtificial;
725 bool RealFirst =
true;
726 for (DieType
P :
D) {
727 if (
P.getTag() != dwarf::DW_TAG_formal_parameter &&
728 P.getTag() != dwarf::DW_TAG_unspecified_parameters)
731 if (SkipFirstParamIfArtificial && RealFirst &&
732 P.find(dwarf::DW_AT_artificial)) {
733 FirstParamIfArtificial =
T;
738 if (
P.getTag() == dwarf::DW_TAG_unspecified_parameters)
745 if (FirstParamIfArtificial) {
746 if (DieType
P = FirstParamIfArtificial) {
747 if (
P.getTag() == dwarf::DW_TAG_pointer_type) {
748 auto CVStep = [&](DieType CV) {
750 Const |= U.getTag() == dwarf::DW_TAG_const_type;
751 Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
756 if (DieType CV = CVStep(
P)) {
763 if (
auto CC =
D.find(dwarf::DW_AT_calling_convention)) {
764 switch (*CC->getAsUnsignedConstant()) {
765 case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
766 OS <<
" __attribute__((stdcall))";
768 case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
769 OS <<
" __attribute__((fastcall))";
771 case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
772 OS <<
" __attribute__((thiscall))";
774 case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
775 OS <<
" __attribute__((vectorcall))";
777 case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
778 OS <<
" __attribute__((pascal))";
780 case dwarf::CallingConvention::DW_CC_LLVM_Win64:
781 OS <<
" __attribute__((ms_abi))";
783 case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
784 OS <<
" __attribute__((sysv_abi))";
786 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
788 OS <<
" __attribute__((pcs(\"aapcs\")))";
790 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
791 OS <<
" __attribute__((pcs(\"aapcs-vfp\")))";
793 case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
794 OS <<
" __attribute__((intel_ocl_bicc))";
796 case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
803 case dwarf::CallingConvention::DW_CC_LLVM_DeviceKernel:
804 OS <<
" __attribute__((device_kernel))";
806 case dwarf::CallingConvention::DW_CC_LLVM_Swift:
808 OS <<
" __attribute__((swiftcall))";
810 case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
811 OS <<
" __attribute__((preserve_most))";
813 case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
814 OS <<
" __attribute__((preserve_all))";
816 case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
817 OS <<
" __attribute__((preserve_none))";
819 case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
820 OS <<
" __attribute__((regcall))";
822 case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
823 OS <<
" __attribute__((m68k_rtd))";
832 if (
D.find(dwarf::DW_AT_reference))
834 if (
D.find(dwarf::DW_AT_rvalue_reference))
840template <
typename DieType>
842 if (
D.getTag() == dwarf::DW_TAG_compile_unit)
844 if (
D.getTag() == dwarf::DW_TAG_type_unit)
846 if (
D.getTag() == dwarf::DW_TAG_skeleton_unit)
848 if (
D.getTag() == dwarf::DW_TAG_subprogram)
850 if (
D.getTag() == dwarf::DW_TAG_lexical_block)
852 D =
D.resolveTypeUnitReference();
853 if (DieType
P =
D.getParent())
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.
This file defines the SmallSet class.
static dwarf::Attribute TypeAttr[]
Tagged union holding either a T or a Error.
A helper class to return the specified delimiter string after the first invocation of operator String...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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
Get the string size.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
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)
DieType unwrapReferencedTypedefType(DieType D)
Resolve the DW_AT_type of D until we reach a DIE that is not a DW_TAG_typedef.
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.
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)