Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:42

0001 //===- DWARFTypePrinter.h ---------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
0011 
0012 #include "llvm/ADT/StringExtras.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/BinaryFormat/Dwarf.h"
0015 #include "llvm/Support/Error.h"
0016 
0017 #include <string>
0018 
0019 namespace llvm {
0020 
0021 class raw_ostream;
0022 
0023 // FIXME: We should have pretty printers per language. Currently we print
0024 // everything as if it was C++ and fall back to the TAG type name.
0025 template <typename DieType> struct DWARFTypePrinter {
0026   raw_ostream &OS;
0027   bool Word = true;
0028   bool EndedWithTemplate = false;
0029 
0030   DWARFTypePrinter(raw_ostream &OS) : OS(OS) {}
0031 
0032   /// Dump the name encoded in the type tag.
0033   void appendTypeTagName(dwarf::Tag T);
0034 
0035   void appendArrayType(const DieType &D);
0036 
0037   DieType skipQualifiers(DieType D);
0038 
0039   bool needsParens(DieType D);
0040 
0041   void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
0042 
0043   DieType appendUnqualifiedNameBefore(DieType D,
0044                                       std::string *OriginalFullName = nullptr);
0045 
0046   void appendUnqualifiedNameAfter(DieType D, DieType Inner,
0047                                   bool SkipFirstParamIfArtificial = false);
0048   void appendQualifiedName(DieType D);
0049   DieType appendQualifiedNameBefore(DieType D);
0050   bool appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
0051   void appendAndTerminateTemplateParameters(DieType D);
0052   void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
0053   void appendConstVolatileQualifierAfter(DieType N);
0054   void appendConstVolatileQualifierBefore(DieType N);
0055 
0056   /// Recursively append the DIE type name when applicable.
0057   void appendUnqualifiedName(DieType D,
0058                              std::string *OriginalFullName = nullptr);
0059 
0060   void appendSubroutineNameAfter(DieType D, DieType Inner,
0061                                  bool SkipFirstParamIfArtificial, bool Const,
0062                                  bool Volatile);
0063   void appendScopes(DieType D);
0064 
0065 private:
0066   /// Returns True if the DIE TAG is one of the ones that is scopped.
0067   static inline bool scopedTAGs(dwarf::Tag Tag) {
0068     switch (Tag) {
0069     case dwarf::DW_TAG_structure_type:
0070     case dwarf::DW_TAG_class_type:
0071     case dwarf::DW_TAG_union_type:
0072     case dwarf::DW_TAG_namespace:
0073     case dwarf::DW_TAG_enumeration_type:
0074     case dwarf::DW_TAG_typedef:
0075       return true;
0076     default:
0077       break;
0078     }
0079     return false;
0080   }
0081 };
0082 
0083 template <typename DieType>
0084 void DWARFTypePrinter<DieType>::appendTypeTagName(dwarf::Tag T) {
0085   StringRef TagStr = TagString(T);
0086   static constexpr StringRef Prefix = "DW_TAG_";
0087   static constexpr StringRef Suffix = "_type";
0088   if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
0089     return;
0090   OS << TagStr.substr(Prefix.size(),
0091                       TagStr.size() - (Prefix.size() + Suffix.size()))
0092      << " ";
0093 }
0094 
0095 template <typename DieType>
0096 void DWARFTypePrinter<DieType>::appendArrayType(const DieType &D) {
0097   for (const DieType &C : D.children()) {
0098     if (C.getTag() != dwarf::DW_TAG_subrange_type)
0099       continue;
0100     std::optional<uint64_t> LB;
0101     std::optional<uint64_t> Count;
0102     std::optional<uint64_t> UB;
0103     std::optional<unsigned> DefaultLB;
0104     if (std::optional<typename DieType::DWARFFormValue> L =
0105             C.find(dwarf::DW_AT_lower_bound))
0106       LB = L->getAsUnsignedConstant();
0107     if (std::optional<typename DieType::DWARFFormValue> CountV =
0108             C.find(dwarf::DW_AT_count))
0109       Count = CountV->getAsUnsignedConstant();
0110     if (std::optional<typename DieType::DWARFFormValue> UpperV =
0111             C.find(dwarf::DW_AT_upper_bound))
0112       UB = UpperV->getAsUnsignedConstant();
0113     if (std::optional<uint64_t> LV = D.getLanguage())
0114       if ((DefaultLB =
0115                LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LV))))
0116         if (LB && *LB == *DefaultLB)
0117           LB = std::nullopt;
0118     if (!LB && !Count && !UB)
0119       OS << "[]";
0120     else if (!LB && (Count || UB) && DefaultLB)
0121       OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
0122     else {
0123       OS << "[[";
0124       if (LB)
0125         OS << *LB;
0126       else
0127         OS << '?';
0128       OS << ", ";
0129       if (Count)
0130         if (LB)
0131           OS << *LB + *Count;
0132         else
0133           OS << "? + " << *Count;
0134       else if (UB)
0135         OS << *UB + 1;
0136       else
0137         OS << '?';
0138       OS << ")]";
0139     }
0140   }
0141   EndedWithTemplate = false;
0142 }
0143 
0144 namespace detail {
0145 template <typename DieType>
0146 DieType resolveReferencedType(DieType D,
0147                               dwarf::Attribute Attr = dwarf::DW_AT_type) {
0148   return D.resolveReferencedType(Attr);
0149 }
0150 template <typename DieType>
0151 DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
0152   return D.resolveReferencedType(F);
0153 }
0154 template <typename DWARFFormValueType>
0155 const char *toString(std::optional<DWARFFormValueType> F) {
0156   if (F) {
0157     llvm::Expected<const char *> E = F->getAsCString();
0158     if (E)
0159       return *E;
0160     llvm::consumeError(E.takeError());
0161   }
0162   return nullptr;
0163 }
0164 } // namespace detail
0165 
0166 template <typename DieType>
0167 DieType DWARFTypePrinter<DieType>::skipQualifiers(DieType D) {
0168   while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
0169                D.getTag() == dwarf::DW_TAG_volatile_type))
0170     D = detail::resolveReferencedType(D);
0171   return D;
0172 }
0173 
0174 template <typename DieType>
0175 bool DWARFTypePrinter<DieType>::needsParens(DieType D) {
0176   D = skipQualifiers(D);
0177   return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
0178                D.getTag() == dwarf::DW_TAG_array_type);
0179 }
0180 
0181 template <typename DieType>
0182 void DWARFTypePrinter<DieType>::appendPointerLikeTypeBefore(DieType D,
0183                                                             DieType Inner,
0184                                                             StringRef Ptr) {
0185   appendQualifiedNameBefore(Inner);
0186   if (Word)
0187     OS << ' ';
0188   if (needsParens(Inner))
0189     OS << '(';
0190   OS << Ptr;
0191   Word = false;
0192   EndedWithTemplate = false;
0193 }
0194 
0195 template <typename DieType>
0196 DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
0197     DieType D, std::string *OriginalFullName) {
0198   Word = true;
0199   if (!D) {
0200     OS << "void";
0201     return DieType();
0202   }
0203   DieType InnerDIE;
0204   auto Inner = [&] { return InnerDIE = detail::resolveReferencedType(D); };
0205   const dwarf::Tag T = D.getTag();
0206   switch (T) {
0207   case dwarf::DW_TAG_pointer_type: {
0208     appendPointerLikeTypeBefore(D, Inner(), "*");
0209     break;
0210   }
0211   case dwarf::DW_TAG_subroutine_type: {
0212     appendQualifiedNameBefore(Inner());
0213     if (Word) {
0214       OS << ' ';
0215     }
0216     Word = false;
0217     break;
0218   }
0219   case dwarf::DW_TAG_array_type: {
0220     appendQualifiedNameBefore(Inner());
0221     break;
0222   }
0223   case dwarf::DW_TAG_reference_type:
0224     appendPointerLikeTypeBefore(D, Inner(), "&");
0225     break;
0226   case dwarf::DW_TAG_rvalue_reference_type:
0227     appendPointerLikeTypeBefore(D, Inner(), "&&");
0228     break;
0229   case dwarf::DW_TAG_ptr_to_member_type: {
0230     appendQualifiedNameBefore(Inner());
0231     if (needsParens(InnerDIE))
0232       OS << '(';
0233     else if (Word)
0234       OS << ' ';
0235     if (DieType Cont =
0236             detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
0237       appendQualifiedName(Cont);
0238       EndedWithTemplate = false;
0239       OS << "::";
0240     }
0241     OS << "*";
0242     Word = false;
0243     break;
0244   }
0245   case dwarf::DW_TAG_LLVM_ptrauth_type:
0246     appendQualifiedNameBefore(Inner());
0247     break;
0248   case dwarf::DW_TAG_const_type:
0249   case dwarf::DW_TAG_volatile_type:
0250     appendConstVolatileQualifierBefore(D);
0251     break;
0252   case dwarf::DW_TAG_namespace: {
0253     if (const char *Name = detail::toString(D.find(dwarf::DW_AT_name)))
0254       OS << Name;
0255     else
0256       OS << "(anonymous namespace)";
0257     break;
0258   }
0259   case dwarf::DW_TAG_unspecified_type: {
0260     StringRef TypeName = D.getShortName();
0261     if (TypeName == "decltype(nullptr)")
0262       TypeName = "std::nullptr_t";
0263     Word = true;
0264     OS << TypeName;
0265     EndedWithTemplate = false;
0266     break;
0267   }
0268     /*
0269   case DW_TAG_structure_type:
0270   case DW_TAG_class_type:
0271   case DW_TAG_enumeration_type:
0272   case DW_TAG_base_type:
0273   */
0274   default: {
0275     const char *NamePtr = detail::toString(D.find(dwarf::DW_AT_name));
0276     if (!NamePtr) {
0277       appendTypeTagName(D.getTag());
0278       return DieType();
0279     }
0280     Word = true;
0281     StringRef Name = NamePtr;
0282     static constexpr StringRef MangledPrefix = "_STN|";
0283     if (Name.consume_front(MangledPrefix)) {
0284       auto Separator = Name.find('|');
0285       assert(Separator != StringRef::npos);
0286       StringRef BaseName = Name.substr(0, Separator);
0287       StringRef TemplateArgs = Name.substr(Separator + 1);
0288       if (OriginalFullName)
0289         *OriginalFullName = (BaseName + TemplateArgs).str();
0290       Name = BaseName;
0291     } else
0292       EndedWithTemplate = Name.ends_with(">");
0293     OS << Name;
0294     // This check would be insufficient for operator overloads like
0295     // "operator>>" - but for now Clang doesn't try to simplify them, so this
0296     // is OK. Add more nuanced operator overload handling here if/when needed.
0297     if (Name.ends_with(">"))
0298       break;
0299     if (!appendTemplateParameters(D))
0300       break;
0301 
0302     if (EndedWithTemplate)
0303       OS << ' ';
0304     OS << '>';
0305     EndedWithTemplate = true;
0306     Word = true;
0307     break;
0308   }
0309   }
0310   return InnerDIE;
0311 }
0312 
0313 template <typename DieType>
0314 void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
0315     DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
0316   if (!D)
0317     return;
0318   switch (D.getTag()) {
0319   case dwarf::DW_TAG_subroutine_type: {
0320     appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
0321                               false);
0322     break;
0323   }
0324   case dwarf::DW_TAG_array_type: {
0325     appendArrayType(D);
0326     break;
0327   }
0328   case dwarf::DW_TAG_const_type:
0329   case dwarf::DW_TAG_volatile_type:
0330     appendConstVolatileQualifierAfter(D);
0331     break;
0332   case dwarf::DW_TAG_ptr_to_member_type:
0333   case dwarf::DW_TAG_reference_type:
0334   case dwarf::DW_TAG_rvalue_reference_type:
0335   case dwarf::DW_TAG_pointer_type: {
0336     if (needsParens(Inner))
0337       OS << ')';
0338     appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner),
0339                                /*SkipFirstParamIfArtificial=*/D.getTag() ==
0340                                    dwarf::DW_TAG_ptr_to_member_type);
0341     break;
0342   }
0343   case dwarf::DW_TAG_LLVM_ptrauth_type: {
0344     auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
0345       if (auto Form = D.find(Attr))
0346         return *Form->getAsUnsignedConstant();
0347       return 0;
0348     };
0349     SmallVector<const char *, 2> optionsVec;
0350     if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
0351       optionsVec.push_back("isa-pointer");
0352     if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))
0353       optionsVec.push_back("authenticates-null-values");
0354     if (auto AuthenticationMode =
0355             D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {
0356       switch (*AuthenticationMode->getAsUnsignedConstant()) {
0357       case 0:
0358       case 1:
0359         optionsVec.push_back("strip");
0360         break;
0361       case 2:
0362         optionsVec.push_back("sign-and-strip");
0363         break;
0364       default:
0365         // Default authentication policy
0366         break;
0367       }
0368     }
0369     std::string options;
0370     for (const auto *option : optionsVec) {
0371       if (options.size())
0372         options += ",";
0373       options += option;
0374     }
0375     if (options.size())
0376       options = ", \"" + options + "\"";
0377     std::string PtrauthString;
0378     llvm::raw_string_ostream PtrauthStream(PtrauthString);
0379     PtrauthStream
0380         << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "
0381         << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
0382         << ", 0x0"
0383         << utohexstr(
0384                getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
0385                true)
0386         << options << ")";
0387     OS << PtrauthStream.str();
0388     break;
0389   }
0390     /*
0391   case DW_TAG_structure_type:
0392   case DW_TAG_class_type:
0393   case DW_TAG_enumeration_type:
0394   case DW_TAG_base_type:
0395   case DW_TAG_namespace:
0396   */
0397   default:
0398     break;
0399   }
0400 }
0401 
0402 template <typename DieType>
0403 void DWARFTypePrinter<DieType>::appendQualifiedName(DieType D) {
0404   if (D && scopedTAGs(D.getTag()))
0405     appendScopes(D.getParent());
0406   appendUnqualifiedName(D);
0407 }
0408 
0409 template <typename DieType>
0410 DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
0411   if (D && scopedTAGs(D.getTag()))
0412     appendScopes(D.getParent());
0413   return appendUnqualifiedNameBefore(D);
0414 }
0415 
0416 template <typename DieType>
0417 bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
0418                                                          bool *FirstParameter) {
0419   bool FirstParameterValue = true;
0420   bool IsTemplate = false;
0421   if (!FirstParameter)
0422     FirstParameter = &FirstParameterValue;
0423   for (const DieType &C : D) {
0424     auto Sep = [&] {
0425       if (*FirstParameter)
0426         OS << '<';
0427       else
0428         OS << ", ";
0429       IsTemplate = true;
0430       EndedWithTemplate = false;
0431       *FirstParameter = false;
0432     };
0433     if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
0434       IsTemplate = true;
0435       appendTemplateParameters(C, FirstParameter);
0436     }
0437     if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
0438       DieType T = detail::resolveReferencedType(C);
0439       Sep();
0440       if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
0441         OS << '(';
0442         appendQualifiedName(T);
0443         OS << ')';
0444         auto V = C.find(dwarf::DW_AT_const_value);
0445         OS << std::to_string(*V->getAsSignedConstant());
0446         continue;
0447       }
0448       // /Maybe/ we could do pointer/reference type parameters, looking for the
0449       // symbol in the ELF symbol table to get back to the variable...
0450       // but probably not worth it.
0451       if (T.getTag() == dwarf::DW_TAG_pointer_type ||
0452           T.getTag() == dwarf::DW_TAG_reference_type)
0453         continue;
0454       const char *RawName = detail::toString(T.find(dwarf::DW_AT_name));
0455       assert(RawName);
0456       StringRef Name = RawName;
0457       auto V = C.find(dwarf::DW_AT_const_value);
0458       bool IsQualifiedChar = false;
0459       if (Name == "bool") {
0460         OS << (*V->getAsUnsignedConstant() ? "true" : "false");
0461       } else if (Name == "short") {
0462         OS << "(short)";
0463         OS << std::to_string(*V->getAsSignedConstant());
0464       } else if (Name == "unsigned short") {
0465         OS << "(unsigned short)";
0466         OS << std::to_string(*V->getAsSignedConstant());
0467       } else if (Name == "int")
0468         OS << std::to_string(*V->getAsSignedConstant());
0469       else if (Name == "long") {
0470         OS << std::to_string(*V->getAsSignedConstant());
0471         OS << "L";
0472       } else if (Name == "long long") {
0473         OS << std::to_string(*V->getAsSignedConstant());
0474         OS << "LL";
0475       } else if (Name == "unsigned int") {
0476         OS << std::to_string(*V->getAsUnsignedConstant());
0477         OS << "U";
0478       } else if (Name == "unsigned long") {
0479         OS << std::to_string(*V->getAsUnsignedConstant());
0480         OS << "UL";
0481       } else if (Name == "unsigned long long") {
0482         OS << std::to_string(*V->getAsUnsignedConstant());
0483         OS << "ULL";
0484       } else if (Name == "char" ||
0485                  (IsQualifiedChar =
0486                       (Name == "unsigned char" || Name == "signed char"))) {
0487         // FIXME: check T's DW_AT_type to see if it's signed or not (since
0488         // char signedness is implementation defined).
0489         auto Val = *V->getAsSignedConstant();
0490         // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
0491         // (doesn't actually support different character types/widths, sign
0492         // handling's not done, and doesn't correctly test if a character is
0493         // printable or needs to use a numeric escape sequence instead)
0494         if (IsQualifiedChar) {
0495           OS << '(';
0496           OS << Name;
0497           OS << ')';
0498         }
0499         switch (Val) {
0500         case '\\':
0501           OS << "'\\\\'";
0502           break;
0503         case '\'':
0504           OS << "'\\''";
0505           break;
0506         case '\a':
0507           // TODO: K&R: the meaning of '\\a' is different in traditional C
0508           OS << "'\\a'";
0509           break;
0510         case '\b':
0511           OS << "'\\b'";
0512           break;
0513         case '\f':
0514           OS << "'\\f'";
0515           break;
0516         case '\n':
0517           OS << "'\\n'";
0518           break;
0519         case '\r':
0520           OS << "'\\r'";
0521           break;
0522         case '\t':
0523           OS << "'\\t'";
0524           break;
0525         case '\v':
0526           OS << "'\\v'";
0527           break;
0528         default:
0529           if ((Val & ~0xFFu) == ~0xFFu)
0530             Val &= 0xFFu;
0531           if (Val < 127 && Val >= 32) {
0532             OS << "'";
0533             OS << (char)Val;
0534             OS << "'";
0535           } else if (Val < 256)
0536             OS << llvm::format("'\\x%02" PRIx64 "'", Val);
0537           else if (Val <= 0xFFFF)
0538             OS << llvm::format("'\\u%04" PRIx64 "'", Val);
0539           else
0540             OS << llvm::format("'\\U%08" PRIx64 "'", Val);
0541         }
0542       }
0543       continue;
0544     }
0545     if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
0546       const char *RawName =
0547           detail::toString(C.find(dwarf::DW_AT_GNU_template_name));
0548       assert(RawName);
0549       StringRef Name = RawName;
0550       Sep();
0551       OS << Name;
0552       continue;
0553     }
0554     if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
0555       continue;
0556     auto TypeAttr = C.find(dwarf::DW_AT_type);
0557     Sep();
0558     appendQualifiedName(TypeAttr ? detail::resolveReferencedType(C, *TypeAttr)
0559                                  : DieType());
0560   }
0561   if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
0562     OS << '<';
0563     EndedWithTemplate = false;
0564   }
0565   return IsTemplate;
0566 }
0567 
0568 template <typename DieType>
0569 void DWARFTypePrinter<DieType>::appendAndTerminateTemplateParameters(
0570     DieType D) {
0571   bool R = appendTemplateParameters(D);
0572   if (!R)
0573     return;
0574 
0575   if (EndedWithTemplate)
0576     OS << " ";
0577   OS << ">";
0578   EndedWithTemplate = true;
0579   Word = true;
0580 }
0581 
0582 template <typename DieType>
0583 void DWARFTypePrinter<DieType>::decomposeConstVolatile(DieType &N, DieType &T,
0584                                                        DieType &C, DieType &V) {
0585   (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
0586   T = detail::resolveReferencedType(N);
0587   if (T) {
0588     auto Tag = T.getTag();
0589     if (Tag == dwarf::DW_TAG_const_type) {
0590       C = T;
0591       T = detail::resolveReferencedType(T);
0592     } else if (Tag == dwarf::DW_TAG_volatile_type) {
0593       V = T;
0594       T = detail::resolveReferencedType(T);
0595     }
0596   }
0597 }
0598 
0599 template <typename DieType>
0600 void DWARFTypePrinter<DieType>::appendConstVolatileQualifierAfter(DieType N) {
0601   DieType C;
0602   DieType V;
0603   DieType T;
0604   decomposeConstVolatile(N, T, C, V);
0605   if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
0606     appendSubroutineNameAfter(T, detail::resolveReferencedType(T), false,
0607                               static_cast<bool>(C), static_cast<bool>(V));
0608   else
0609     appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T));
0610 }
0611 
0612 template <typename DieType>
0613 void DWARFTypePrinter<DieType>::appendConstVolatileQualifierBefore(DieType N) {
0614   DieType C;
0615   DieType V;
0616   DieType T;
0617   decomposeConstVolatile(N, T, C, V);
0618   bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
0619   DieType A = T;
0620   while (A && A.getTag() == dwarf::DW_TAG_array_type)
0621     A = detail::resolveReferencedType(A);
0622   bool Leading =
0623       (!A || (A.getTag() != dwarf::DW_TAG_pointer_type &&
0624               A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
0625       !Subroutine;
0626   if (Leading) {
0627     if (C)
0628       OS << "const ";
0629     if (V)
0630       OS << "volatile ";
0631   }
0632   appendQualifiedNameBefore(T);
0633   if (!Leading && !Subroutine) {
0634     Word = true;
0635     if (C)
0636       OS << "const";
0637     if (V) {
0638       if (C)
0639         OS << ' ';
0640       OS << "volatile";
0641     }
0642   }
0643 }
0644 
0645 template <typename DieType>
0646 void DWARFTypePrinter<DieType>::appendUnqualifiedName(
0647     DieType D, std::string *OriginalFullName) {
0648   // FIXME: We should have pretty printers per language. Currently we print
0649   // everything as if it was C++ and fall back to the TAG type name.
0650   DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
0651   appendUnqualifiedNameAfter(D, Inner);
0652 }
0653 
0654 template <typename DieType>
0655 void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
0656     DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
0657     bool Volatile) {
0658   DieType FirstParamIfArtificial;
0659   OS << '(';
0660   EndedWithTemplate = false;
0661   bool First = true;
0662   bool RealFirst = true;
0663   for (DieType P : D) {
0664     if (P.getTag() != dwarf::DW_TAG_formal_parameter &&
0665         P.getTag() != dwarf::DW_TAG_unspecified_parameters)
0666       return;
0667     DieType T = detail::resolveReferencedType(P);
0668     if (SkipFirstParamIfArtificial && RealFirst &&
0669         P.find(dwarf::DW_AT_artificial)) {
0670       FirstParamIfArtificial = T;
0671       RealFirst = false;
0672       continue;
0673     }
0674     if (!First) {
0675       OS << ", ";
0676     }
0677     First = false;
0678     if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
0679       OS << "...";
0680     else
0681       appendQualifiedName(T);
0682   }
0683   EndedWithTemplate = false;
0684   OS << ')';
0685   if (FirstParamIfArtificial) {
0686     if (DieType P = FirstParamIfArtificial) {
0687       if (P.getTag() == dwarf::DW_TAG_pointer_type) {
0688         auto CVStep = [&](DieType CV) {
0689           if (DieType U = detail::resolveReferencedType(CV)) {
0690             Const |= U.getTag() == dwarf::DW_TAG_const_type;
0691             Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
0692             return U;
0693           }
0694           return DieType();
0695         };
0696         if (DieType CV = CVStep(P)) {
0697           CVStep(CV);
0698         }
0699       }
0700     }
0701   }
0702 
0703   if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {
0704     switch (*CC->getAsUnsignedConstant()) {
0705     case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
0706       OS << " __attribute__((stdcall))";
0707       break;
0708     case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
0709       OS << " __attribute__((fastcall))";
0710       break;
0711     case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
0712       OS << " __attribute__((thiscall))";
0713       break;
0714     case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
0715       OS << " __attribute__((vectorcall))";
0716       break;
0717     case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
0718       OS << " __attribute__((pascal))";
0719       break;
0720     case dwarf::CallingConvention::DW_CC_LLVM_Win64:
0721       OS << " __attribute__((ms_abi))";
0722       break;
0723     case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
0724       OS << " __attribute__((sysv_abi))";
0725       break;
0726     case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
0727       // AArch64VectorCall missing?
0728       OS << " __attribute__((pcs(\"aapcs\")))";
0729       break;
0730     case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
0731       OS << " __attribute__((pcs(\"aapcs-vfp\")))";
0732       break;
0733     case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
0734       OS << " __attribute__((intel_ocl_bicc))";
0735       break;
0736     case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
0737     case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
0738       // These aren't available as attributes, but maybe we should still
0739       // render them somehow? (Clang doesn't render them, but that's an issue
0740       // for template names too - since then the DWARF names of templates
0741       // instantiated with function types with these calling conventions won't
0742       // have distinct names - so we'd need to fix that too)
0743       break;
0744     case dwarf::CallingConvention::DW_CC_LLVM_Swift:
0745       // SwiftAsync missing
0746       OS << " __attribute__((swiftcall))";
0747       break;
0748     case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
0749       OS << " __attribute__((preserve_most))";
0750       break;
0751     case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
0752       OS << " __attribute__((preserve_all))";
0753       break;
0754     case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
0755       OS << " __attribute__((preserve_none))";
0756       break;
0757     case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
0758       OS << " __attribute__((regcall))";
0759       break;
0760     case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
0761       OS << " __attribute__((m68k_rtd))";
0762       break;
0763     }
0764   }
0765 
0766   if (Const)
0767     OS << " const";
0768   if (Volatile)
0769     OS << " volatile";
0770   if (D.find(dwarf::DW_AT_reference))
0771     OS << " &";
0772   if (D.find(dwarf::DW_AT_rvalue_reference))
0773     OS << " &&";
0774 
0775   appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner));
0776 }
0777 
0778 template <typename DieType>
0779 void DWARFTypePrinter<DieType>::appendScopes(DieType D) {
0780   if (D.getTag() == dwarf::DW_TAG_compile_unit)
0781     return;
0782   if (D.getTag() == dwarf::DW_TAG_type_unit)
0783     return;
0784   if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
0785     return;
0786   if (D.getTag() == dwarf::DW_TAG_subprogram)
0787     return;
0788   if (D.getTag() == dwarf::DW_TAG_lexical_block)
0789     return;
0790   D = D.resolveTypeUnitReference();
0791   if (DieType P = D.getParent())
0792     appendScopes(P);
0793   appendUnqualifiedName(D);
0794   OS << "::";
0795 }
0796 } // namespace llvm
0797 
0798 #endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H