1 #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
2 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
3 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
4 #include "llvm/Support/ScopedPrinter.h"
5 namespace llvm {
6 using namespace dwarf;
appendTypeTagName(dwarf::Tag T)7 void DWARFTypePrinter::appendTypeTagName(dwarf::Tag T) {
8   StringRef TagStr = TagString(T);
9   static constexpr StringRef Prefix = "DW_TAG_";
10   static constexpr StringRef Suffix = "_type";
11   if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
12     return;
13   OS << TagStr.substr(Prefix.size(),
14                       TagStr.size() - (Prefix.size() + Suffix.size()))
15      << " ";
16 }
17 
appendArrayType(const DWARFDie & D)18 void DWARFTypePrinter::appendArrayType(const DWARFDie &D) {
19   for (const DWARFDie &C : D.children()) {
20     if (C.getTag() != DW_TAG_subrange_type)
21       continue;
22     std::optional<uint64_t> LB;
23     std::optional<uint64_t> Count;
24     std::optional<uint64_t> UB;
25     std::optional<unsigned> DefaultLB;
26     if (std::optional<DWARFFormValue> L = C.find(DW_AT_lower_bound))
27       LB = L->getAsUnsignedConstant();
28     if (std::optional<DWARFFormValue> CountV = C.find(DW_AT_count))
29       Count = CountV->getAsUnsignedConstant();
30     if (std::optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound))
31       UB = UpperV->getAsUnsignedConstant();
32     if (std::optional<DWARFFormValue> LV =
33             D.getDwarfUnit()->getUnitDIE().find(DW_AT_language))
34       if (std::optional<uint64_t> LC = LV->getAsUnsignedConstant())
35         if ((DefaultLB =
36                  LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
37           if (LB && *LB == *DefaultLB)
38             LB = std::nullopt;
39     if (!LB && !Count && !UB)
40       OS << "[]";
41     else if (!LB && (Count || UB) && DefaultLB)
42       OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
43     else {
44       OS << "[[";
45       if (LB)
46         OS << *LB;
47       else
48         OS << '?';
49       OS << ", ";
50       if (Count)
51         if (LB)
52           OS << *LB + *Count;
53         else
54           OS << "? + " << *Count;
55       else if (UB)
56         OS << *UB + 1;
57       else
58         OS << '?';
59       OS << ")]";
60     }
61   }
62   EndedWithTemplate = false;
63 }
64 
resolveReferencedType(DWARFDie D,dwarf::Attribute Attr=DW_AT_type)65 static DWARFDie resolveReferencedType(DWARFDie D,
66                                       dwarf::Attribute Attr = DW_AT_type) {
67   return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
68 }
resolveReferencedType(DWARFDie D,DWARFFormValue F)69 static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
70   return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
71 }
skipQualifiers(DWARFDie D)72 DWARFDie DWARFTypePrinter::skipQualifiers(DWARFDie D) {
73   while (D && (D.getTag() == DW_TAG_const_type ||
74                D.getTag() == DW_TAG_volatile_type))
75     D = resolveReferencedType(D);
76   return D;
77 }
78 
needsParens(DWARFDie D)79 bool DWARFTypePrinter::needsParens(DWARFDie D) {
80   D = skipQualifiers(D);
81   return D && (D.getTag() == DW_TAG_subroutine_type ||
82                D.getTag() == DW_TAG_array_type);
83 }
84 
appendPointerLikeTypeBefore(DWARFDie D,DWARFDie Inner,StringRef Ptr)85 void DWARFTypePrinter::appendPointerLikeTypeBefore(DWARFDie D, DWARFDie Inner,
86                                                    StringRef Ptr) {
87   appendQualifiedNameBefore(Inner);
88   if (Word)
89     OS << ' ';
90   if (needsParens(Inner))
91     OS << '(';
92   OS << Ptr;
93   Word = false;
94   EndedWithTemplate = false;
95 }
96 
97 DWARFDie
appendUnqualifiedNameBefore(DWARFDie D,std::string * OriginalFullName)98 DWARFTypePrinter::appendUnqualifiedNameBefore(DWARFDie D,
99                                               std::string *OriginalFullName) {
100   Word = true;
101   if (!D) {
102     OS << "void";
103     return DWARFDie();
104   }
105   DWARFDie InnerDIE;
106   auto Inner = [&] { return InnerDIE = resolveReferencedType(D); };
107   const dwarf::Tag T = D.getTag();
108   switch (T) {
109   case DW_TAG_pointer_type: {
110     appendPointerLikeTypeBefore(D, Inner(), "*");
111     break;
112   }
113   case DW_TAG_subroutine_type: {
114     appendQualifiedNameBefore(Inner());
115     if (Word) {
116       OS << ' ';
117     }
118     Word = false;
119     break;
120   }
121   case DW_TAG_array_type: {
122     appendQualifiedNameBefore(Inner());
123     break;
124   }
125   case DW_TAG_reference_type:
126     appendPointerLikeTypeBefore(D, Inner(), "&");
127     break;
128   case DW_TAG_rvalue_reference_type:
129     appendPointerLikeTypeBefore(D, Inner(), "&&");
130     break;
131   case DW_TAG_ptr_to_member_type: {
132     appendQualifiedNameBefore(Inner());
133     if (needsParens(InnerDIE))
134       OS << '(';
135     else if (Word)
136       OS << ' ';
137     if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) {
138       appendQualifiedName(Cont);
139       EndedWithTemplate = false;
140       OS << "::";
141     }
142     OS << "*";
143     Word = false;
144     break;
145   }
146   case DW_TAG_LLVM_ptrauth_type:
147     appendQualifiedNameBefore(Inner());
148     break;
149   case DW_TAG_const_type:
150   case DW_TAG_volatile_type:
151     appendConstVolatileQualifierBefore(D);
152     break;
153   case DW_TAG_namespace: {
154     if (const char *Name = dwarf::toString(D.find(DW_AT_name), nullptr))
155       OS << Name;
156     else
157       OS << "(anonymous namespace)";
158     break;
159   }
160   case DW_TAG_unspecified_type: {
161     StringRef TypeName = D.getShortName();
162     if (TypeName == "decltype(nullptr)")
163       TypeName = "std::nullptr_t";
164     Word = true;
165     OS << TypeName;
166     EndedWithTemplate = false;
167     break;
168   }
169     /*
170   case DW_TAG_structure_type:
171   case DW_TAG_class_type:
172   case DW_TAG_enumeration_type:
173   case DW_TAG_base_type:
174   */
175   default: {
176     const char *NamePtr = dwarf::toString(D.find(DW_AT_name), nullptr);
177     if (!NamePtr) {
178       appendTypeTagName(D.getTag());
179       return DWARFDie();
180     }
181     Word = true;
182     StringRef Name = NamePtr;
183     static constexpr StringRef MangledPrefix = "_STN|";
184     if (Name.consume_front(MangledPrefix)) {
185       auto Separator = Name.find('|');
186       assert(Separator != StringRef::npos);
187       StringRef BaseName = Name.substr(0, Separator);
188       StringRef TemplateArgs = Name.substr(Separator + 1);
189       if (OriginalFullName)
190         *OriginalFullName = (BaseName + TemplateArgs).str();
191       Name = BaseName;
192     } else
193       EndedWithTemplate = Name.ends_with(">");
194     OS << Name;
195     // This check would be insufficient for operator overloads like
196     // "operator>>" - but for now Clang doesn't try to simplify them, so this
197     // is OK. Add more nuanced operator overload handling here if/when needed.
198     if (Name.ends_with(">"))
199       break;
200     if (!appendTemplateParameters(D))
201       break;
202 
203     if (EndedWithTemplate)
204       OS << ' ';
205     OS << '>';
206     EndedWithTemplate = true;
207     Word = true;
208     break;
209   }
210   }
211   return InnerDIE;
212 }
213 
appendUnqualifiedNameAfter(DWARFDie D,DWARFDie Inner,bool SkipFirstParamIfArtificial)214 void DWARFTypePrinter::appendUnqualifiedNameAfter(
215     DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial) {
216   if (!D)
217     return;
218   switch (D.getTag()) {
219   case DW_TAG_subroutine_type: {
220     appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
221                               false);
222     break;
223   }
224   case DW_TAG_array_type: {
225     appendArrayType(D);
226     break;
227   }
228   case DW_TAG_const_type:
229   case DW_TAG_volatile_type:
230     appendConstVolatileQualifierAfter(D);
231     break;
232   case DW_TAG_ptr_to_member_type:
233   case DW_TAG_reference_type:
234   case DW_TAG_rvalue_reference_type:
235   case DW_TAG_pointer_type: {
236     if (needsParens(Inner))
237       OS << ')';
238     appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner),
239                                /*SkipFirstParamIfArtificial=*/D.getTag() ==
240                                    DW_TAG_ptr_to_member_type);
241     break;
242   }
243   case DW_TAG_LLVM_ptrauth_type: {
244     auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
245       if (auto Form = D.find(Attr))
246         return *Form->getAsUnsignedConstant();
247       return 0;
248     };
249     SmallVector<const char *, 2> optionsVec;
250     if (getValOrNull(DW_AT_LLVM_ptrauth_isa_pointer))
251       optionsVec.push_back("isa-pointer");
252     if (getValOrNull(DW_AT_LLVM_ptrauth_authenticates_null_values))
253       optionsVec.push_back("authenticates-null-values");
254     std::string options;
255     for (const auto *option : optionsVec) {
256       if (options.size())
257         options += ",";
258       options += option;
259     }
260     if (options.size())
261       options = ", \"" + options + "\"";
262     std::string PtrauthString;
263     llvm::raw_string_ostream PtrauthStream(PtrauthString);
264     PtrauthStream
265         << "__ptrauth(" << getValOrNull(DW_AT_LLVM_ptrauth_key) << ", "
266         << getValOrNull(DW_AT_LLVM_ptrauth_address_discriminated) << ", 0x0"
267         << utohexstr(getValOrNull(DW_AT_LLVM_ptrauth_extra_discriminator), true)
268         << options << ")";
269     OS << PtrauthStream.str();
270     break;
271   }
272     /*
273   case DW_TAG_structure_type:
274   case DW_TAG_class_type:
275   case DW_TAG_enumeration_type:
276   case DW_TAG_base_type:
277   case DW_TAG_namespace:
278   */
279   default:
280     break;
281   }
282 }
283 
284 /// Returns True if the DIE TAG is one of the ones that is scopped.
scopedTAGs(dwarf::Tag Tag)285 static bool scopedTAGs(dwarf::Tag Tag) {
286   switch (Tag) {
287   case dwarf::DW_TAG_structure_type:
288   case dwarf::DW_TAG_class_type:
289   case dwarf::DW_TAG_union_type:
290   case dwarf::DW_TAG_namespace:
291   case dwarf::DW_TAG_enumeration_type:
292     return true;
293   default:
294     break;
295   }
296   return false;
297 }
appendQualifiedName(DWARFDie D)298 void DWARFTypePrinter::appendQualifiedName(DWARFDie D) {
299   if (D && scopedTAGs(D.getTag()))
300     appendScopes(D.getParent());
301   appendUnqualifiedName(D);
302 }
appendQualifiedNameBefore(DWARFDie D)303 DWARFDie DWARFTypePrinter::appendQualifiedNameBefore(DWARFDie D) {
304   if (D && scopedTAGs(D.getTag()))
305     appendScopes(D.getParent());
306   return appendUnqualifiedNameBefore(D);
307 }
appendTemplateParameters(DWARFDie D,bool * FirstParameter)308 bool DWARFTypePrinter::appendTemplateParameters(DWARFDie D,
309                                                 bool *FirstParameter) {
310   bool FirstParameterValue = true;
311   bool IsTemplate = false;
312   if (!FirstParameter)
313     FirstParameter = &FirstParameterValue;
314   for (const DWARFDie &C : D) {
315     auto Sep = [&] {
316       if (*FirstParameter)
317         OS << '<';
318       else
319         OS << ", ";
320       IsTemplate = true;
321       EndedWithTemplate = false;
322       *FirstParameter = false;
323     };
324     if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
325       IsTemplate = true;
326       appendTemplateParameters(C, FirstParameter);
327     }
328     if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
329       DWARFDie T = resolveReferencedType(C);
330       Sep();
331       if (T.getTag() == DW_TAG_enumeration_type) {
332         OS << '(';
333         appendQualifiedName(T);
334         OS << ')';
335         auto V = C.find(DW_AT_const_value);
336         OS << std::to_string(*V->getAsSignedConstant());
337         continue;
338       }
339       // /Maybe/ we could do pointer type parameters, looking for the
340       // symbol in the ELF symbol table to get back to the variable...
341       // but probably not worth it.
342       if (T.getTag() == DW_TAG_pointer_type)
343         continue;
344       const char *RawName = dwarf::toString(T.find(DW_AT_name), nullptr);
345       assert(RawName);
346       StringRef Name = RawName;
347       auto V = C.find(DW_AT_const_value);
348       bool IsQualifiedChar = false;
349       if (Name == "bool") {
350         OS << (*V->getAsUnsignedConstant() ? "true" : "false");
351       } else if (Name == "short") {
352         OS << "(short)";
353         OS << std::to_string(*V->getAsSignedConstant());
354       } else if (Name == "unsigned short") {
355         OS << "(unsigned short)";
356         OS << std::to_string(*V->getAsSignedConstant());
357       } else if (Name == "int")
358         OS << std::to_string(*V->getAsSignedConstant());
359       else if (Name == "long") {
360         OS << std::to_string(*V->getAsSignedConstant());
361         OS << "L";
362       } else if (Name == "long long") {
363         OS << std::to_string(*V->getAsSignedConstant());
364         OS << "LL";
365       } else if (Name == "unsigned int") {
366         OS << std::to_string(*V->getAsUnsignedConstant());
367         OS << "U";
368       } else if (Name == "unsigned long") {
369         OS << std::to_string(*V->getAsUnsignedConstant());
370         OS << "UL";
371       } else if (Name == "unsigned long long") {
372         OS << std::to_string(*V->getAsUnsignedConstant());
373         OS << "ULL";
374       } else if (Name == "char" ||
375                  (IsQualifiedChar =
376                       (Name == "unsigned char" || Name == "signed char"))) {
377         // FIXME: check T's DW_AT_type to see if it's signed or not (since
378         // char signedness is implementation defined).
379         auto Val = *V->getAsSignedConstant();
380         // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
381         // (doesn't actually support different character types/widths, sign
382         // handling's not done, and doesn't correctly test if a character is
383         // printable or needs to use a numeric escape sequence instead)
384         if (IsQualifiedChar) {
385           OS << '(';
386           OS << Name;
387           OS << ')';
388         }
389         switch (Val) {
390         case '\\':
391           OS << "'\\\\'";
392           break;
393         case '\'':
394           OS << "'\\''";
395           break;
396         case '\a':
397           // TODO: K&R: the meaning of '\\a' is different in traditional C
398           OS << "'\\a'";
399           break;
400         case '\b':
401           OS << "'\\b'";
402           break;
403         case '\f':
404           OS << "'\\f'";
405           break;
406         case '\n':
407           OS << "'\\n'";
408           break;
409         case '\r':
410           OS << "'\\r'";
411           break;
412         case '\t':
413           OS << "'\\t'";
414           break;
415         case '\v':
416           OS << "'\\v'";
417           break;
418         default:
419           if ((Val & ~0xFFu) == ~0xFFu)
420             Val &= 0xFFu;
421           if (Val < 127 && Val >= 32) {
422             OS << "'";
423             OS << (char)Val;
424             OS << "'";
425           } else if (Val < 256)
426             OS << llvm::format("'\\x%02" PRIx64 "'", Val);
427           else if (Val <= 0xFFFF)
428             OS << llvm::format("'\\u%04" PRIx64 "'", Val);
429           else
430             OS << llvm::format("'\\U%08" PRIx64 "'", Val);
431         }
432       }
433       continue;
434     }
435     if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
436       const char *RawName =
437           dwarf::toString(C.find(DW_AT_GNU_template_name), nullptr);
438       assert(RawName);
439       StringRef Name = RawName;
440       Sep();
441       OS << Name;
442       continue;
443     }
444     if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
445       continue;
446     auto TypeAttr = C.find(DW_AT_type);
447     Sep();
448     appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr)
449                                  : DWARFDie());
450   }
451   if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
452     OS << '<';
453     EndedWithTemplate = false;
454   }
455   return IsTemplate;
456 }
decomposeConstVolatile(DWARFDie & N,DWARFDie & T,DWARFDie & C,DWARFDie & V)457 void DWARFTypePrinter::decomposeConstVolatile(DWARFDie &N, DWARFDie &T,
458                                               DWARFDie &C, DWARFDie &V) {
459   (N.getTag() == DW_TAG_const_type ? C : V) = N;
460   T = resolveReferencedType(N);
461   if (T) {
462     auto Tag = T.getTag();
463     if (Tag == DW_TAG_const_type) {
464       C = T;
465       T = resolveReferencedType(T);
466     } else if (Tag == DW_TAG_volatile_type) {
467       V = T;
468       T = resolveReferencedType(T);
469     }
470   }
471 }
appendConstVolatileQualifierAfter(DWARFDie N)472 void DWARFTypePrinter::appendConstVolatileQualifierAfter(DWARFDie N) {
473   DWARFDie C;
474   DWARFDie V;
475   DWARFDie T;
476   decomposeConstVolatile(N, T, C, V);
477   if (T && T.getTag() == DW_TAG_subroutine_type)
478     appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(),
479                               V.isValid());
480   else
481     appendUnqualifiedNameAfter(T, resolveReferencedType(T));
482 }
appendConstVolatileQualifierBefore(DWARFDie N)483 void DWARFTypePrinter::appendConstVolatileQualifierBefore(DWARFDie N) {
484   DWARFDie C;
485   DWARFDie V;
486   DWARFDie T;
487   decomposeConstVolatile(N, T, C, V);
488   bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type;
489   DWARFDie A = T;
490   while (A && A.getTag() == DW_TAG_array_type)
491     A = resolveReferencedType(A);
492   bool Leading =
493       (!A || (A.getTag() != DW_TAG_pointer_type &&
494               A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
495       !Subroutine;
496   if (Leading) {
497     if (C)
498       OS << "const ";
499     if (V)
500       OS << "volatile ";
501   }
502   appendQualifiedNameBefore(T);
503   if (!Leading && !Subroutine) {
504     Word = true;
505     if (C)
506       OS << "const";
507     if (V) {
508       if (C)
509         OS << ' ';
510       OS << "volatile";
511     }
512   }
513 }
appendUnqualifiedName(DWARFDie D,std::string * OriginalFullName)514 void DWARFTypePrinter::appendUnqualifiedName(DWARFDie D,
515                                              std::string *OriginalFullName) {
516   // FIXME: We should have pretty printers per language. Currently we print
517   // everything as if it was C++ and fall back to the TAG type name.
518   DWARFDie Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
519   appendUnqualifiedNameAfter(D, Inner);
520 }
appendSubroutineNameAfter(DWARFDie D,DWARFDie Inner,bool SkipFirstParamIfArtificial,bool Const,bool Volatile)521 void DWARFTypePrinter::appendSubroutineNameAfter(
522     DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const,
523     bool Volatile) {
524   DWARFDie FirstParamIfArtificial;
525   OS << '(';
526   EndedWithTemplate = false;
527   bool First = true;
528   bool RealFirst = true;
529   for (DWARFDie P : D) {
530     if (P.getTag() != DW_TAG_formal_parameter &&
531         P.getTag() != DW_TAG_unspecified_parameters)
532       return;
533     DWARFDie T = resolveReferencedType(P);
534     if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) {
535       FirstParamIfArtificial = T;
536       RealFirst = false;
537       continue;
538     }
539     if (!First) {
540       OS << ", ";
541     }
542     First = false;
543     if (P.getTag() == DW_TAG_unspecified_parameters)
544       OS << "...";
545     else
546       appendQualifiedName(T);
547   }
548   EndedWithTemplate = false;
549   OS << ')';
550   if (FirstParamIfArtificial) {
551     if (DWARFDie P = FirstParamIfArtificial) {
552       if (P.getTag() == DW_TAG_pointer_type) {
553         auto CVStep = [&](DWARFDie CV) {
554           if (DWARFDie U = resolveReferencedType(CV)) {
555             Const |= U.getTag() == DW_TAG_const_type;
556             Volatile |= U.getTag() == DW_TAG_volatile_type;
557             return U;
558           }
559           return DWARFDie();
560         };
561         if (DWARFDie CV = CVStep(P)) {
562           CVStep(CV);
563         }
564       }
565     }
566   }
567 
568   if (auto CC = D.find(DW_AT_calling_convention)) {
569     switch (*CC->getAsUnsignedConstant()) {
570     case CallingConvention::DW_CC_BORLAND_stdcall:
571       OS << " __attribute__((stdcall))";
572       break;
573     case CallingConvention::DW_CC_BORLAND_msfastcall:
574       OS << " __attribute__((fastcall))";
575       break;
576     case CallingConvention::DW_CC_BORLAND_thiscall:
577       OS << " __attribute__((thiscall))";
578       break;
579     case CallingConvention::DW_CC_LLVM_vectorcall:
580       OS << " __attribute__((vectorcall))";
581       break;
582     case CallingConvention::DW_CC_BORLAND_pascal:
583       OS << " __attribute__((pascal))";
584       break;
585     case CallingConvention::DW_CC_LLVM_Win64:
586       OS << " __attribute__((ms_abi))";
587       break;
588     case CallingConvention::DW_CC_LLVM_X86_64SysV:
589       OS << " __attribute__((sysv_abi))";
590       break;
591     case CallingConvention::DW_CC_LLVM_AAPCS:
592       // AArch64VectorCall missing?
593       OS << " __attribute__((pcs(\"aapcs\")))";
594       break;
595     case CallingConvention::DW_CC_LLVM_AAPCS_VFP:
596       OS << " __attribute__((pcs(\"aapcs-vfp\")))";
597       break;
598     case CallingConvention::DW_CC_LLVM_IntelOclBicc:
599       OS << " __attribute__((intel_ocl_bicc))";
600       break;
601     case CallingConvention::DW_CC_LLVM_SpirFunction:
602     case CallingConvention::DW_CC_LLVM_OpenCLKernel:
603       // These aren't available as attributes, but maybe we should still
604       // render them somehow? (Clang doesn't render them, but that's an issue
605       // for template names too - since then the DWARF names of templates
606       // instantiated with function types with these calling conventions won't
607       // have distinct names - so we'd need to fix that too)
608       break;
609     case CallingConvention::DW_CC_LLVM_Swift:
610       // SwiftAsync missing
611       OS << " __attribute__((swiftcall))";
612       break;
613     case CallingConvention::DW_CC_LLVM_PreserveMost:
614       OS << " __attribute__((preserve_most))";
615       break;
616     case CallingConvention::DW_CC_LLVM_PreserveAll:
617       OS << " __attribute__((preserve_all))";
618       break;
619     case CallingConvention::DW_CC_LLVM_X86RegCall:
620       OS << " __attribute__((regcall))";
621       break;
622     case CallingConvention::DW_CC_LLVM_M68kRTD:
623       OS << " __attribute__((m68k_rtd))";
624       break;
625     }
626   }
627 
628   if (Const)
629     OS << " const";
630   if (Volatile)
631     OS << " volatile";
632   if (D.find(DW_AT_reference))
633     OS << " &";
634   if (D.find(DW_AT_rvalue_reference))
635     OS << " &&";
636 
637   appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner));
638 }
appendScopes(DWARFDie D)639 void DWARFTypePrinter::appendScopes(DWARFDie D) {
640   if (D.getTag() == DW_TAG_compile_unit)
641     return;
642   if (D.getTag() == DW_TAG_type_unit)
643     return;
644   if (D.getTag() == DW_TAG_skeleton_unit)
645     return;
646   if (D.getTag() == DW_TAG_subprogram)
647     return;
648   if (D.getTag() == DW_TAG_lexical_block)
649     return;
650   D = D.resolveTypeUnitReference();
651   if (DWARFDie P = D.getParent())
652     appendScopes(P);
653   appendUnqualifiedName(D);
654   OS << "::";
655 }
656 } // namespace llvm
657