xref: /llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h (revision f33e2369051e13a54a05dd361d89c1ba77f4f593)
1 //===- DWARFTypePrinter.h ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
10 #define LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
11 
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/Support/Error.h"
16 
17 #include <string>
18 
19 namespace llvm {
20 
21 class raw_ostream;
22 
23 // FIXME: We should have pretty printers per language. Currently we print
24 // everything as if it was C++ and fall back to the TAG type name.
25 template <typename DieType> struct DWARFTypePrinter {
26   raw_ostream &OS;
27   bool Word = true;
28   bool EndedWithTemplate = false;
29 
30   DWARFTypePrinter(raw_ostream &OS) : OS(OS) {}
31 
32   /// Dump the name encoded in the type tag.
33   void appendTypeTagName(dwarf::Tag T);
34 
35   void appendArrayType(const DieType &D);
36 
37   DieType skipQualifiers(DieType D);
38 
39   bool needsParens(DieType D);
40 
41   void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
42 
43   DieType appendUnqualifiedNameBefore(DieType D,
44                                       std::string *OriginalFullName = nullptr);
45 
46   void appendUnqualifiedNameAfter(DieType D, DieType Inner,
47                                   bool SkipFirstParamIfArtificial = false);
48   void appendQualifiedName(DieType D);
49   DieType appendQualifiedNameBefore(DieType D);
50   bool appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
51   void appendAndTerminateTemplateParameters(DieType D);
52   void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
53   void appendConstVolatileQualifierAfter(DieType N);
54   void appendConstVolatileQualifierBefore(DieType N);
55 
56   /// Recursively append the DIE type name when applicable.
57   void appendUnqualifiedName(DieType D,
58                              std::string *OriginalFullName = nullptr);
59 
60   void appendSubroutineNameAfter(DieType D, DieType Inner,
61                                  bool SkipFirstParamIfArtificial, bool Const,
62                                  bool Volatile);
63   void appendScopes(DieType D);
64 
65 private:
66   /// Returns True if the DIE TAG is one of the ones that is scopped.
67   static inline bool scopedTAGs(dwarf::Tag Tag) {
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 template <typename DieType>
84 void DWARFTypePrinter<DieType>::appendTypeTagName(dwarf::Tag T) {
85   StringRef TagStr = TagString(T);
86   static constexpr StringRef Prefix = "DW_TAG_";
87   static constexpr StringRef Suffix = "_type";
88   if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
89     return;
90   OS << TagStr.substr(Prefix.size(),
91                       TagStr.size() - (Prefix.size() + Suffix.size()))
92      << " ";
93 }
94 
95 template <typename DieType>
96 void DWARFTypePrinter<DieType>::appendArrayType(const DieType &D) {
97   for (const DieType &C : D.children()) {
98     if (C.getTag() != dwarf::DW_TAG_subrange_type)
99       continue;
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())
114       if ((DefaultLB =
115                LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LV))))
116         if (LB && *LB == *DefaultLB)
117           LB = std::nullopt;
118     if (!LB && !Count && !UB)
119       OS << "[]";
120     else if (!LB && (Count || UB) && DefaultLB)
121       OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
122     else {
123       OS << "[[";
124       if (LB)
125         OS << *LB;
126       else
127         OS << '?';
128       OS << ", ";
129       if (Count)
130         if (LB)
131           OS << *LB + *Count;
132         else
133           OS << "? + " << *Count;
134       else if (UB)
135         OS << *UB + 1;
136       else
137         OS << '?';
138       OS << ")]";
139     }
140   }
141   EndedWithTemplate = false;
142 }
143 
144 namespace detail {
145 template <typename DieType>
146 DieType resolveReferencedType(DieType D,
147                               dwarf::Attribute Attr = dwarf::DW_AT_type) {
148   return D.resolveReferencedType(Attr);
149 }
150 template <typename DieType>
151 DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
152   return D.resolveReferencedType(F);
153 }
154 template <typename DWARFFormValueType>
155 const char *toString(std::optional<DWARFFormValueType> F) {
156   if (F) {
157     llvm::Expected<const char *> E = F->getAsCString();
158     if (E)
159       return *E;
160     llvm::consumeError(E.takeError());
161   }
162   return nullptr;
163 }
164 } // namespace detail
165 
166 template <typename DieType>
167 DieType DWARFTypePrinter<DieType>::skipQualifiers(DieType D) {
168   while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
169                D.getTag() == dwarf::DW_TAG_volatile_type))
170     D = detail::resolveReferencedType(D);
171   return D;
172 }
173 
174 template <typename DieType>
175 bool DWARFTypePrinter<DieType>::needsParens(DieType D) {
176   D = skipQualifiers(D);
177   return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
178                D.getTag() == dwarf::DW_TAG_array_type);
179 }
180 
181 template <typename DieType>
182 void DWARFTypePrinter<DieType>::appendPointerLikeTypeBefore(DieType D,
183                                                             DieType Inner,
184                                                             StringRef Ptr) {
185   appendQualifiedNameBefore(Inner);
186   if (Word)
187     OS << ' ';
188   if (needsParens(Inner))
189     OS << '(';
190   OS << Ptr;
191   Word = false;
192   EndedWithTemplate = false;
193 }
194 
195 template <typename DieType>
196 DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
197     DieType D, std::string *OriginalFullName) {
198   Word = true;
199   if (!D) {
200     OS << "void";
201     return DieType();
202   }
203   DieType InnerDIE;
204   auto Inner = [&] { return InnerDIE = detail::resolveReferencedType(D); };
205   const dwarf::Tag T = D.getTag();
206   switch (T) {
207   case dwarf::DW_TAG_pointer_type: {
208     appendPointerLikeTypeBefore(D, Inner(), "*");
209     break;
210   }
211   case dwarf::DW_TAG_subroutine_type: {
212     appendQualifiedNameBefore(Inner());
213     if (Word) {
214       OS << ' ';
215     }
216     Word = false;
217     break;
218   }
219   case dwarf::DW_TAG_array_type: {
220     appendQualifiedNameBefore(Inner());
221     break;
222   }
223   case dwarf::DW_TAG_reference_type:
224     appendPointerLikeTypeBefore(D, Inner(), "&");
225     break;
226   case dwarf::DW_TAG_rvalue_reference_type:
227     appendPointerLikeTypeBefore(D, Inner(), "&&");
228     break;
229   case dwarf::DW_TAG_ptr_to_member_type: {
230     appendQualifiedNameBefore(Inner());
231     if (needsParens(InnerDIE))
232       OS << '(';
233     else if (Word)
234       OS << ' ';
235     if (DieType Cont =
236             detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
237       appendQualifiedName(Cont);
238       EndedWithTemplate = false;
239       OS << "::";
240     }
241     OS << "*";
242     Word = false;
243     break;
244   }
245   case dwarf::DW_TAG_LLVM_ptrauth_type:
246     appendQualifiedNameBefore(Inner());
247     break;
248   case dwarf::DW_TAG_const_type:
249   case dwarf::DW_TAG_volatile_type:
250     appendConstVolatileQualifierBefore(D);
251     break;
252   case dwarf::DW_TAG_namespace: {
253     if (const char *Name = detail::toString(D.find(dwarf::DW_AT_name)))
254       OS << Name;
255     else
256       OS << "(anonymous namespace)";
257     break;
258   }
259   case dwarf::DW_TAG_unspecified_type: {
260     StringRef TypeName = D.getShortName();
261     if (TypeName == "decltype(nullptr)")
262       TypeName = "std::nullptr_t";
263     Word = true;
264     OS << TypeName;
265     EndedWithTemplate = false;
266     break;
267   }
268     /*
269   case DW_TAG_structure_type:
270   case DW_TAG_class_type:
271   case DW_TAG_enumeration_type:
272   case DW_TAG_base_type:
273   */
274   default: {
275     const char *NamePtr = detail::toString(D.find(dwarf::DW_AT_name));
276     if (!NamePtr) {
277       appendTypeTagName(D.getTag());
278       return DieType();
279     }
280     Word = true;
281     StringRef Name = NamePtr;
282     static constexpr StringRef MangledPrefix = "_STN|";
283     if (Name.consume_front(MangledPrefix)) {
284       auto Separator = Name.find('|');
285       assert(Separator != StringRef::npos);
286       StringRef BaseName = Name.substr(0, Separator);
287       StringRef TemplateArgs = Name.substr(Separator + 1);
288       if (OriginalFullName)
289         *OriginalFullName = (BaseName + TemplateArgs).str();
290       Name = BaseName;
291     } else
292       EndedWithTemplate = Name.ends_with(">");
293     OS << Name;
294     // This check would be insufficient for operator overloads like
295     // "operator>>" - but for now Clang doesn't try to simplify them, so this
296     // is OK. Add more nuanced operator overload handling here if/when needed.
297     if (Name.ends_with(">"))
298       break;
299     if (!appendTemplateParameters(D))
300       break;
301 
302     if (EndedWithTemplate)
303       OS << ' ';
304     OS << '>';
305     EndedWithTemplate = true;
306     Word = true;
307     break;
308   }
309   }
310   return InnerDIE;
311 }
312 
313 template <typename DieType>
314 void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
315     DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
316   if (!D)
317     return;
318   switch (D.getTag()) {
319   case dwarf::DW_TAG_subroutine_type: {
320     appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
321                               false);
322     break;
323   }
324   case dwarf::DW_TAG_array_type: {
325     appendArrayType(D);
326     break;
327   }
328   case dwarf::DW_TAG_const_type:
329   case dwarf::DW_TAG_volatile_type:
330     appendConstVolatileQualifierAfter(D);
331     break;
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))
337       OS << ')';
338     appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner),
339                                /*SkipFirstParamIfArtificial=*/D.getTag() ==
340                                    dwarf::DW_TAG_ptr_to_member_type);
341     break;
342   }
343   case dwarf::DW_TAG_LLVM_ptrauth_type: {
344     auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
345       if (auto Form = D.find(Attr))
346         return *Form->getAsUnsignedConstant();
347       return 0;
348     };
349     SmallVector<const char *, 2> optionsVec;
350     if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
351       optionsVec.push_back("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()) {
357       case 0:
358       case 1:
359         optionsVec.push_back("strip");
360         break;
361       case 2:
362         optionsVec.push_back("sign-and-strip");
363         break;
364       default:
365         // Default authentication policy
366         break;
367       }
368     }
369     std::string options;
370     for (const auto *option : optionsVec) {
371       if (options.size())
372         options += ",";
373       options += option;
374     }
375     if (options.size())
376       options = ", \"" + options + "\"";
377     std::string PtrauthString;
378     llvm::raw_string_ostream PtrauthStream(PtrauthString);
379     PtrauthStream
380         << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "
381         << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
382         << ", 0x0"
383         << utohexstr(
384                getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
385                true)
386         << options << ")";
387     OS << PtrauthStream.str();
388     break;
389   }
390     /*
391   case DW_TAG_structure_type:
392   case DW_TAG_class_type:
393   case DW_TAG_enumeration_type:
394   case DW_TAG_base_type:
395   case DW_TAG_namespace:
396   */
397   default:
398     break;
399   }
400 }
401 
402 template <typename DieType>
403 void DWARFTypePrinter<DieType>::appendQualifiedName(DieType D) {
404   if (D && scopedTAGs(D.getTag()))
405     appendScopes(D.getParent());
406   appendUnqualifiedName(D);
407 }
408 
409 template <typename DieType>
410 DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
411   if (D && scopedTAGs(D.getTag()))
412     appendScopes(D.getParent());
413   return appendUnqualifiedNameBefore(D);
414 }
415 
416 template <typename DieType>
417 bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
418                                                          bool *FirstParameter) {
419   bool FirstParameterValue = true;
420   bool IsTemplate = false;
421   if (!FirstParameter)
422     FirstParameter = &FirstParameterValue;
423   for (const DieType &C : D) {
424     auto Sep = [&] {
425       if (*FirstParameter)
426         OS << '<';
427       else
428         OS << ", ";
429       IsTemplate = true;
430       EndedWithTemplate = false;
431       *FirstParameter = false;
432     };
433     if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
434       IsTemplate = true;
435       appendTemplateParameters(C, FirstParameter);
436     }
437     if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
438       DieType T = detail::resolveReferencedType(C);
439       Sep();
440       if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
441         OS << '(';
442         appendQualifiedName(T);
443         OS << ')';
444         auto V = C.find(dwarf::DW_AT_const_value);
445         OS << std::to_string(*V->getAsSignedConstant());
446         continue;
447       }
448       // /Maybe/ we could do pointer/reference type parameters, looking for the
449       // symbol in the ELF symbol table to get back to the variable...
450       // but probably not worth it.
451       if (T.getTag() == dwarf::DW_TAG_pointer_type ||
452           T.getTag() == dwarf::DW_TAG_reference_type)
453         continue;
454       const char *RawName = detail::toString(T.find(dwarf::DW_AT_name));
455       assert(RawName);
456       StringRef Name = RawName;
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") {
462         OS << "(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());
471         OS << "L";
472       } else if (Name == "long long") {
473         OS << std::to_string(*V->getAsSignedConstant());
474         OS << "LL";
475       } else if (Name == "unsigned int") {
476         OS << std::to_string(*V->getAsUnsignedConstant());
477         OS << "U";
478       } else if (Name == "unsigned long") {
479         OS << std::to_string(*V->getAsUnsignedConstant());
480         OS << "UL";
481       } else if (Name == "unsigned long long") {
482         OS << std::to_string(*V->getAsUnsignedConstant());
483         OS << "ULL";
484       } else if (Name == "char" ||
485                  (IsQualifiedChar =
486                       (Name == "unsigned char" || Name == "signed char"))) {
487         // FIXME: check T's DW_AT_type to see if it's signed or not (since
488         // char signedness is implementation defined).
489         auto Val = *V->getAsSignedConstant();
490         // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
491         // (doesn't actually support different character types/widths, sign
492         // handling's not done, and doesn't correctly test if a character is
493         // printable or needs to use a numeric escape sequence instead)
494         if (IsQualifiedChar) {
495           OS << '(';
496           OS << Name;
497           OS << ')';
498         }
499         switch (Val) {
500         case '\\':
501           OS << "'\\\\'";
502           break;
503         case '\'':
504           OS << "'\\''";
505           break;
506         case '\a':
507           // TODO: K&R: the meaning of '\\a' is different in traditional C
508           OS << "'\\a'";
509           break;
510         case '\b':
511           OS << "'\\b'";
512           break;
513         case '\f':
514           OS << "'\\f'";
515           break;
516         case '\n':
517           OS << "'\\n'";
518           break;
519         case '\r':
520           OS << "'\\r'";
521           break;
522         case '\t':
523           OS << "'\\t'";
524           break;
525         case '\v':
526           OS << "'\\v'";
527           break;
528         default:
529           if ((Val & ~0xFFu) == ~0xFFu)
530             Val &= 0xFFu;
531           if (Val < 127 && Val >= 32) {
532             OS << "'";
533             OS << (char)Val;
534             OS << "'";
535           } else if (Val < 256)
536             OS << llvm::format("'\\x%02" PRIx64 "'", Val);
537           else if (Val <= 0xFFFF)
538             OS << llvm::format("'\\u%04" PRIx64 "'", Val);
539           else
540             OS << llvm::format("'\\U%08" PRIx64 "'", Val);
541         }
542       }
543       continue;
544     }
545     if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
546       const char *RawName =
547           detail::toString(C.find(dwarf::DW_AT_GNU_template_name));
548       assert(RawName);
549       StringRef Name = RawName;
550       Sep();
551       OS << Name;
552       continue;
553     }
554     if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
555       continue;
556     auto TypeAttr = C.find(dwarf::DW_AT_type);
557     Sep();
558     appendQualifiedName(TypeAttr ? detail::resolveReferencedType(C, *TypeAttr)
559                                  : DieType());
560   }
561   if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
562     OS << '<';
563     EndedWithTemplate = false;
564   }
565   return IsTemplate;
566 }
567 
568 template <typename DieType>
569 void DWARFTypePrinter<DieType>::appendAndTerminateTemplateParameters(
570     DieType D) {
571   bool R = appendTemplateParameters(D);
572   if (!R)
573     return;
574 
575   if (EndedWithTemplate)
576     OS << " ";
577   OS << ">";
578   EndedWithTemplate = true;
579   Word = true;
580 }
581 
582 template <typename DieType>
583 void DWARFTypePrinter<DieType>::decomposeConstVolatile(DieType &N, DieType &T,
584                                                        DieType &C, DieType &V) {
585   (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
586   T = detail::resolveReferencedType(N);
587   if (T) {
588     auto Tag = T.getTag();
589     if (Tag == dwarf::DW_TAG_const_type) {
590       C = T;
591       T = detail::resolveReferencedType(T);
592     } else if (Tag == dwarf::DW_TAG_volatile_type) {
593       V = T;
594       T = detail::resolveReferencedType(T);
595     }
596   }
597 }
598 
599 template <typename DieType>
600 void DWARFTypePrinter<DieType>::appendConstVolatileQualifierAfter(DieType N) {
601   DieType C;
602   DieType V;
603   DieType T;
604   decomposeConstVolatile(N, T, C, V);
605   if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
606     appendSubroutineNameAfter(T, detail::resolveReferencedType(T), false,
607                               static_cast<bool>(C), static_cast<bool>(V));
608   else
609     appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T));
610 }
611 
612 template <typename DieType>
613 void DWARFTypePrinter<DieType>::appendConstVolatileQualifierBefore(DieType N) {
614   DieType C;
615   DieType V;
616   DieType T;
617   decomposeConstVolatile(N, T, C, V);
618   bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
619   DieType A = T;
620   while (A && A.getTag() == dwarf::DW_TAG_array_type)
621     A = detail::resolveReferencedType(A);
622   bool Leading =
623       (!A || (A.getTag() != dwarf::DW_TAG_pointer_type &&
624               A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
625       !Subroutine;
626   if (Leading) {
627     if (C)
628       OS << "const ";
629     if (V)
630       OS << "volatile ";
631   }
632   appendQualifiedNameBefore(T);
633   if (!Leading && !Subroutine) {
634     Word = true;
635     if (C)
636       OS << "const";
637     if (V) {
638       if (C)
639         OS << ' ';
640       OS << "volatile";
641     }
642   }
643 }
644 
645 template <typename DieType>
646 void DWARFTypePrinter<DieType>::appendUnqualifiedName(
647     DieType D, std::string *OriginalFullName) {
648   // FIXME: We should have pretty printers per language. Currently we print
649   // everything as if it was C++ and fall back to the TAG type name.
650   DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
651   appendUnqualifiedNameAfter(D, Inner);
652 }
653 
654 template <typename DieType>
655 void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
656     DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
657     bool Volatile) {
658   DieType FirstParamIfArtificial;
659   OS << '(';
660   EndedWithTemplate = false;
661   bool First = true;
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)
666       return;
667     DieType T = detail::resolveReferencedType(P);
668     if (SkipFirstParamIfArtificial && RealFirst &&
669         P.find(dwarf::DW_AT_artificial)) {
670       FirstParamIfArtificial = T;
671       RealFirst = false;
672       continue;
673     }
674     if (!First) {
675       OS << ", ";
676     }
677     First = false;
678     if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
679       OS << "...";
680     else
681       appendQualifiedName(T);
682   }
683   EndedWithTemplate = false;
684   OS << ')';
685   if (FirstParamIfArtificial) {
686     if (DieType P = FirstParamIfArtificial) {
687       if (P.getTag() == dwarf::DW_TAG_pointer_type) {
688         auto CVStep = [&](DieType CV) {
689           if (DieType U = detail::resolveReferencedType(CV)) {
690             Const |= U.getTag() == dwarf::DW_TAG_const_type;
691             Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
692             return U;
693           }
694           return DieType();
695         };
696         if (DieType CV = CVStep(P)) {
697           CVStep(CV);
698         }
699       }
700     }
701   }
702 
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))";
707       break;
708     case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
709       OS << " __attribute__((fastcall))";
710       break;
711     case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
712       OS << " __attribute__((thiscall))";
713       break;
714     case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
715       OS << " __attribute__((vectorcall))";
716       break;
717     case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
718       OS << " __attribute__((pascal))";
719       break;
720     case dwarf::CallingConvention::DW_CC_LLVM_Win64:
721       OS << " __attribute__((ms_abi))";
722       break;
723     case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
724       OS << " __attribute__((sysv_abi))";
725       break;
726     case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
727       // AArch64VectorCall missing?
728       OS << " __attribute__((pcs(\"aapcs\")))";
729       break;
730     case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
731       OS << " __attribute__((pcs(\"aapcs-vfp\")))";
732       break;
733     case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
734       OS << " __attribute__((intel_ocl_bicc))";
735       break;
736     case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
737     case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
738       // These aren't available as attributes, but maybe we should still
739       // render them somehow? (Clang doesn't render them, but that's an issue
740       // for template names too - since then the DWARF names of templates
741       // instantiated with function types with these calling conventions won't
742       // have distinct names - so we'd need to fix that too)
743       break;
744     case dwarf::CallingConvention::DW_CC_LLVM_Swift:
745       // SwiftAsync missing
746       OS << " __attribute__((swiftcall))";
747       break;
748     case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
749       OS << " __attribute__((preserve_most))";
750       break;
751     case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
752       OS << " __attribute__((preserve_all))";
753       break;
754     case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
755       OS << " __attribute__((preserve_none))";
756       break;
757     case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
758       OS << " __attribute__((regcall))";
759       break;
760     case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
761       OS << " __attribute__((m68k_rtd))";
762       break;
763     }
764   }
765 
766   if (Const)
767     OS << " const";
768   if (Volatile)
769     OS << " volatile";
770   if (D.find(dwarf::DW_AT_reference))
771     OS << " &";
772   if (D.find(dwarf::DW_AT_rvalue_reference))
773     OS << " &&";
774 
775   appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner));
776 }
777 
778 template <typename DieType>
779 void DWARFTypePrinter<DieType>::appendScopes(DieType D) {
780   if (D.getTag() == dwarf::DW_TAG_compile_unit)
781     return;
782   if (D.getTag() == dwarf::DW_TAG_type_unit)
783     return;
784   if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
785     return;
786   if (D.getTag() == dwarf::DW_TAG_subprogram)
787     return;
788   if (D.getTag() == dwarf::DW_TAG_lexical_block)
789     return;
790   D = D.resolveTypeUnitReference();
791   if (DieType P = D.getParent())
792     appendScopes(P);
793   appendUnqualifiedName(D);
794   OS << "::";
795 }
796 } // namespace llvm
797 
798 #endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
799