LLVM 23.0.0git
DWARFTypePrinter.h
Go to the documentation of this file.
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/SmallSet.h"
14#include "llvm/ADT/StringRef.h"
16#include "llvm/Support/Error.h"
18
19#include <string>
20
21namespace llvm {
22
23class raw_ostream;
24
25// FIXME: We should have pretty printers per language. Currently we print
26// everything as if it was C++ and fall back to the TAG type name.
27template <typename DieType> struct DWARFTypePrinter {
29 bool Word = true;
30 bool EndedWithTemplate = false;
31
33
34 /// Dump the name encoded in the type tag.
36
37 void appendArrayType(const DieType &D);
38
39 DieType skipQualifiers(DieType D);
40
41 bool needsParens(DieType D);
42
43 void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
44
45 DieType appendUnqualifiedNameBefore(DieType D,
46 std::string *OriginalFullName = nullptr);
47
48 void appendUnqualifiedNameAfter(DieType D, DieType Inner,
49 bool SkipFirstParamIfArtificial = false);
50 void appendQualifiedName(DieType D);
51 DieType appendQualifiedNameBefore(DieType D);
52 bool appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
54 void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
57
58 /// Recursively append the DIE type name when applicable.
59 void appendUnqualifiedName(DieType D,
60 std::string *OriginalFullName = nullptr);
61
62 void appendSubroutineNameAfter(DieType D, DieType Inner,
63 bool SkipFirstParamIfArtificial, bool Const,
64 bool Volatile);
65 void appendScopes(DieType D);
66
67private:
68 /// Returns True if the DIE TAG is one of the ones that is scopped.
69 static inline bool scopedTAGs(dwarf::Tag Tag) {
70 switch (Tag) {
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:
77 return true;
78 default:
79 break;
80 }
81 return false;
82 }
83
84 /// If FormValue is a valid constant Form, print into \c OS the integral value
85 /// casted to the type referred to by \c Cast.
86 template <typename FormValueType>
87 void appendCastedValue(const FormValueType &FormValue, DieType Cast,
88 bool IsUnsigned);
89};
90
91template <typename DieType>
93 StringRef TagStr = TagString(T);
94 static constexpr StringRef Prefix = "DW_TAG_";
95 static constexpr StringRef Suffix = "_type";
96 if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
97 return;
98 OS << TagStr.substr(Prefix.size(),
99 TagStr.size() - (Prefix.size() + Suffix.size()))
100 << " ";
101}
102
103template <typename DieType>
105 for (const DieType &C : D.children()) {
106 if (C.getTag() != dwarf::DW_TAG_subrange_type)
107 continue;
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())
122 if ((DefaultLB =
123 LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LV))))
124 if (LB && *LB == *DefaultLB)
125 LB = std::nullopt;
126 if (!LB && !Count && !UB)
127 OS << "[]";
128 else if (!LB && (Count || UB) && DefaultLB)
129 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
130 else {
131 OS << "[[";
132 if (LB)
133 OS << *LB;
134 else
135 OS << '?';
136 OS << ", ";
137 if (Count)
138 if (LB)
139 OS << *LB + *Count;
140 else
141 OS << "? + " << *Count;
142 else if (UB)
143 OS << *UB + 1;
144 else
145 OS << '?';
146 OS << ")]";
147 }
148 }
149 EndedWithTemplate = false;
150}
151
152namespace detail {
153template <typename DieType>
154DieType resolveReferencedType(DieType D,
155 dwarf::Attribute Attr = dwarf::DW_AT_type) {
156 return D.resolveReferencedType(Attr);
157}
158template <typename DieType>
159DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
160 return D.resolveReferencedType(F);
161}
162template <typename DWARFFormValueType>
163const char *toString(std::optional<DWARFFormValueType> F) {
164 if (F) {
165 llvm::Expected<const char *> E = F->getAsCString();
166 if (E)
167 return *E;
168 llvm::consumeError(E.takeError());
169 }
170 return nullptr;
171}
172
173/// Resolve the DW_AT_type of \c D until we reach a DIE that is not a
174/// DW_TAG_typedef. Gives up if a cycle is detected in malformed DWARF.
175/// In this case, returns the typedef DIE where the cycle is formed.
176template <typename DieType> DieType unwrapReferencedTypedefType(DieType D) {
177 SmallSet<uint64_t, 4> Visited;
178 while (true) {
179 auto TypeAttr = D.find(dwarf::DW_AT_type);
180 if (!TypeAttr)
181 return DieType();
182
183 auto Unwrapped = detail::resolveReferencedType(D, *TypeAttr);
184 if (!Unwrapped || Unwrapped.getTag() != dwarf::DW_TAG_typedef)
185 return Unwrapped;
186
187 if (!Visited.insert(Unwrapped.getOffset()).second) {
189 << "typedef cycle detected: DW_TAG_typedef at offset 0x"
190 << utohexstr(Unwrapped.getOffset())
191 << " references itself through DW_TAG_typedef chain\n";
192 return Unwrapped;
193 }
194
195 D = Unwrapped;
196 }
197}
198} // namespace detail
199
200template <typename DieType>
202 while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
203 D.getTag() == dwarf::DW_TAG_volatile_type))
205 return D;
206}
207
208template <typename DieType>
210 D = skipQualifiers(D);
211 return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
212 D.getTag() == dwarf::DW_TAG_array_type);
213}
214
215template <typename DieType>
217 DieType Inner,
218 StringRef Ptr) {
220 if (Word)
221 OS << ' ';
222 if (needsParens(Inner))
223 OS << '(';
224 OS << Ptr;
225 Word = false;
226 EndedWithTemplate = false;
227}
228
229template <typename DieType>
231 DieType D, std::string *OriginalFullName) {
232 Word = true;
233 if (!D) {
234 OS << "void";
235 return DieType();
236 }
237 DieType InnerDIE;
238 auto Inner = [&] { return InnerDIE = detail::resolveReferencedType(D); };
239 const dwarf::Tag T = D.getTag();
240 switch (T) {
241 case dwarf::DW_TAG_pointer_type: {
242 appendPointerLikeTypeBefore(D, Inner(), "*");
243 break;
244 }
245 case dwarf::DW_TAG_subroutine_type: {
247 if (Word) {
248 OS << ' ';
249 }
250 Word = false;
251 break;
252 }
253 case dwarf::DW_TAG_array_type: {
255 break;
256 }
257 case dwarf::DW_TAG_reference_type:
258 appendPointerLikeTypeBefore(D, Inner(), "&");
259 break;
260 case dwarf::DW_TAG_rvalue_reference_type:
261 appendPointerLikeTypeBefore(D, Inner(), "&&");
262 break;
263 case dwarf::DW_TAG_ptr_to_member_type: {
265 if (needsParens(InnerDIE))
266 OS << '(';
267 else if (Word)
268 OS << ' ';
269 if (DieType Cont =
270 detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
272 EndedWithTemplate = false;
273 OS << "::";
274 }
275 OS << "*";
276 Word = false;
277 break;
278 }
279 case dwarf::DW_TAG_LLVM_ptrauth_type:
281 break;
282 case dwarf::DW_TAG_const_type:
283 case dwarf::DW_TAG_volatile_type:
285 break;
286 case dwarf::DW_TAG_namespace: {
287 if (const char *Name = detail::toString(D.find(dwarf::DW_AT_name)))
288 OS << Name;
289 else
290 OS << "(anonymous namespace)";
291 break;
292 }
293 case dwarf::DW_TAG_unspecified_type: {
294 StringRef TypeName = D.getShortName();
295 if (TypeName == "decltype(nullptr)")
296 TypeName = "std::nullptr_t";
297 Word = true;
298 OS << TypeName;
299 EndedWithTemplate = false;
300 break;
301 }
302 /*
303 case DW_TAG_structure_type:
304 case DW_TAG_class_type:
305 case DW_TAG_enumeration_type:
306 case DW_TAG_base_type:
307 */
308 default: {
309 const char *NamePtr = detail::toString(D.find(dwarf::DW_AT_name));
310 if (!NamePtr) {
311 appendTypeTagName(D.getTag());
312 return DieType();
313 }
314 Word = true;
315 StringRef Name = NamePtr;
316 static constexpr StringRef MangledPrefix = "_STN|";
317 if (Name.consume_front(MangledPrefix)) {
318 auto Separator = Name.find('|');
319 assert(Separator != StringRef::npos);
320 StringRef BaseName = Name.substr(0, Separator);
321 StringRef TemplateArgs = Name.substr(Separator + 1);
322 if (OriginalFullName)
323 *OriginalFullName = (BaseName + TemplateArgs).str();
324 Name = BaseName;
325 } else
326 EndedWithTemplate = Name.ends_with(">");
327 OS << Name;
328 // This check would be insufficient for operator overloads like
329 // "operator>>" - but for now Clang doesn't try to simplify them, so this
330 // is OK. Add more nuanced operator overload handling here if/when needed.
331 if (Name.ends_with(">"))
332 break;
334 break;
335
337 OS << ' ';
338 OS << '>';
339 EndedWithTemplate = true;
340 Word = true;
341 break;
342 }
343 }
344 return InnerDIE;
345}
346
347template <typename DieType>
349 DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
350 if (!D)
351 return;
352 switch (D.getTag()) {
353 case dwarf::DW_TAG_subroutine_type: {
354 appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
355 false);
356 break;
357 }
358 case dwarf::DW_TAG_array_type: {
360 break;
361 }
362 case dwarf::DW_TAG_const_type:
363 case dwarf::DW_TAG_volatile_type:
365 break;
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: {
370 if (needsParens(Inner))
371 OS << ')';
373 /*SkipFirstParamIfArtificial=*/D.getTag() ==
374 dwarf::DW_TAG_ptr_to_member_type);
375 break;
376 }
377 case dwarf::DW_TAG_LLVM_ptrauth_type: {
378 auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
379 if (auto Form = D.find(Attr))
380 return *Form->getAsUnsignedConstant();
381 return 0;
382 };
384 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
385 optionsVec.push_back("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()) {
391 case 0:
392 case 1:
393 optionsVec.push_back("strip");
394 break;
395 case 2:
396 optionsVec.push_back("sign-and-strip");
397 break;
398 default:
399 // Default authentication policy
400 break;
401 }
402 }
403 std::string options;
404 for (const auto *option : optionsVec) {
405 if (options.size())
406 options += ",";
407 options += option;
408 }
409 if (options.size())
410 options = ", \"" + options + "\"";
411 std::string PtrauthString;
412 llvm::raw_string_ostream PtrauthStream(PtrauthString);
413 PtrauthStream
414 << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "
415 << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
416 << ", 0x0"
417 << utohexstr(
418 getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
419 true)
420 << options << ")";
421 OS << PtrauthStream.str();
422 break;
423 }
424 /*
425 case DW_TAG_structure_type:
426 case DW_TAG_class_type:
427 case DW_TAG_enumeration_type:
428 case DW_TAG_base_type:
429 case DW_TAG_namespace:
430 */
431 default:
432 break;
433 }
434}
435
436template <typename DieType>
438 if (D && scopedTAGs(D.getTag()))
439 appendScopes(D.getParent());
441}
442
443template <typename DieType>
445 if (D && scopedTAGs(D.getTag()))
446 appendScopes(D.getParent());
448}
449
450template <typename DieType>
451template <typename FormValueType>
452void DWARFTypePrinter<DieType>::appendCastedValue(
453 const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {
454 std::string ValStr;
455 if (IsUnsigned) {
456 std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
457 if (!UVal)
458 return;
459
460 ValStr = std::to_string(*UVal);
461 } else {
462 std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
463 if (!SVal)
464 return;
465
466 ValStr = std::to_string(*SVal);
467 }
468
469 OS << '(';
470 appendQualifiedName(Cast);
471 OS << ')';
472 OS << std::move(ValStr);
473}
474
475template <typename DieType>
477 bool *FirstParameter) {
478 bool FirstParameterValue = true;
479 bool IsTemplate = false;
480 if (!FirstParameter)
481 FirstParameter = &FirstParameterValue;
482 for (const DieType &C : D) {
483 auto Sep = [&] {
484 if (*FirstParameter)
485 OS << '<';
486 else
487 OS << ", ";
488 IsTemplate = true;
489 EndedWithTemplate = false;
490 *FirstParameter = false;
491 };
492 if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
493 IsTemplate = true;
494 appendTemplateParameters(C, FirstParameter);
495 }
496 if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
498 Sep();
499 if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
500 auto V = C.find(dwarf::DW_AT_const_value);
501 appendCastedValue(*V, T, /*IsUnsigned=*/false);
502 continue;
503 }
504
505 // /Maybe/ we could do pointer/reference type parameters, looking for the
506 // symbol in the ELF symbol table to get back to the variable...
507 // but probably not worth it.
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)
511 continue;
512 const char *RawName = detail::toString(T.find(dwarf::DW_AT_name));
513 assert(RawName);
514 StringRef Name = RawName;
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") {
520 OS << "(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());
529 OS << "L";
530 } else if (Name == "long long") {
531 OS << std::to_string(*V->getAsSignedConstant());
532 OS << "LL";
533 } else if (Name == "unsigned int") {
534 OS << std::to_string(*V->getAsUnsignedConstant());
535 OS << "U";
536 } else if (Name == "unsigned long") {
537 OS << std::to_string(*V->getAsUnsignedConstant());
538 OS << "UL";
539 } else if (Name == "unsigned long long") {
540 OS << std::to_string(*V->getAsUnsignedConstant());
541 OS << "ULL";
542 } else if (Name == "char" ||
543 (IsQualifiedChar =
544 (Name == "unsigned char" || Name == "signed char"))) {
545 // FIXME: check T's DW_AT_type to see if it's signed or not (since
546 // char signedness is implementation defined).
547 auto Val = *V->getAsSignedConstant();
548 // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
549 // (doesn't actually support different character types/widths, sign
550 // handling's not done, and doesn't correctly test if a character is
551 // printable or needs to use a numeric escape sequence instead)
552 if (IsQualifiedChar) {
553 OS << '(';
554 OS << Name;
555 OS << ')';
556 }
557 switch (Val) {
558 case '\\':
559 OS << "'\\\\'";
560 break;
561 case '\'':
562 OS << "'\\''";
563 break;
564 case '\a':
565 // TODO: K&R: the meaning of '\\a' is different in traditional C
566 OS << "'\\a'";
567 break;
568 case '\b':
569 OS << "'\\b'";
570 break;
571 case '\f':
572 OS << "'\\f'";
573 break;
574 case '\n':
575 OS << "'\\n'";
576 break;
577 case '\r':
578 OS << "'\\r'";
579 break;
580 case '\t':
581 OS << "'\\t'";
582 break;
583 case '\v':
584 OS << "'\\v'";
585 break;
586 default:
587 if ((Val & ~0xFFu) == ~0xFFu)
588 Val &= 0xFFu;
589 if (Val < 127 && Val >= 32) {
590 OS << "'";
591 OS << (char)Val;
592 OS << "'";
593 } else if (Val < 256)
594 OS << llvm::format("'\\x%02" PRIx64 "'", Val);
595 else if (Val <= 0xFFFF)
596 OS << llvm::format("'\\u%04" PRIx64 "'", Val);
597 else
598 OS << llvm::format("'\\U%08" PRIx64 "'", Val);
599 }
600 // FIXME: Handle _BitInt's larger than 64-bits which are emitted as
601 // block data.
602 } else if (Name.starts_with("_BitInt")) {
603 appendCastedValue(*V, T, /*IsUnsigned=*/false);
604 } else if (Name.starts_with("unsigned _BitInt")) {
605 appendCastedValue(*V, T, /*IsUnsigned=*/true);
606 }
607 continue;
608 }
609 if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
610 const char *RawName =
611 detail::toString(C.find(dwarf::DW_AT_GNU_template_name));
612 assert(RawName);
613 StringRef Name = RawName;
614 Sep();
615 OS << Name;
616 continue;
617 }
618 if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
619 continue;
620 Sep();
621
623 }
624 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
625 OS << '<';
626 EndedWithTemplate = false;
627 }
628 return IsTemplate;
629}
630
631template <typename DieType>
633 DieType D) {
634 bool R = appendTemplateParameters(D);
635 if (!R)
636 return;
637
639 OS << " ";
640 OS << ">";
641 EndedWithTemplate = true;
642 Word = true;
643}
644
645template <typename DieType>
647 DieType &C, DieType &V) {
648 (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
650 if (T) {
651 auto Tag = T.getTag();
652 if (Tag == dwarf::DW_TAG_const_type) {
653 C = T;
655 } else if (Tag == dwarf::DW_TAG_volatile_type) {
656 V = T;
658 }
659 }
660}
661
662template <typename DieType>
664 DieType C;
665 DieType V;
666 DieType T;
668 if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
670 static_cast<bool>(C), static_cast<bool>(V));
671 else
673}
674
675template <typename DieType>
677 DieType C;
678 DieType V;
679 DieType T;
681 bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
682 DieType A = T;
683 while (A && A.getTag() == dwarf::DW_TAG_array_type)
685 bool Leading =
686 (!A || (A.getTag() != dwarf::DW_TAG_pointer_type &&
687 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
688 !Subroutine;
689 if (Leading) {
690 if (C)
691 OS << "const ";
692 if (V)
693 OS << "volatile ";
694 }
696 if (!Leading && !Subroutine) {
697 Word = true;
698 if (C)
699 OS << "const";
700 if (V) {
701 if (C)
702 OS << ' ';
703 OS << "volatile";
704 }
705 }
706}
707
708template <typename DieType>
710 DieType D, std::string *OriginalFullName) {
711 // FIXME: We should have pretty printers per language. Currently we print
712 // everything as if it was C++ and fall back to the TAG type name.
713 DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
715}
716
717template <typename DieType>
719 DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
720 bool Volatile) {
721 DieType FirstParamIfArtificial;
722 OS << '(';
723 EndedWithTemplate = false;
724 ListSeparator LS;
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)
729 return;
731 if (SkipFirstParamIfArtificial && RealFirst &&
732 P.find(dwarf::DW_AT_artificial)) {
733 FirstParamIfArtificial = T;
734 RealFirst = false;
735 continue;
736 }
737 OS << LS;
738 if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
739 OS << "...";
740 else
742 }
743 EndedWithTemplate = false;
744 OS << ')';
745 if (FirstParamIfArtificial) {
746 if (DieType P = FirstParamIfArtificial) {
747 if (P.getTag() == dwarf::DW_TAG_pointer_type) {
748 auto CVStep = [&](DieType CV) {
749 if (DieType U = detail::resolveReferencedType(CV)) {
750 Const |= U.getTag() == dwarf::DW_TAG_const_type;
751 Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
752 return U;
753 }
754 return DieType();
755 };
756 if (DieType CV = CVStep(P)) {
757 CVStep(CV);
758 }
759 }
760 }
761 }
762
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))";
767 break;
768 case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
769 OS << " __attribute__((fastcall))";
770 break;
771 case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
772 OS << " __attribute__((thiscall))";
773 break;
774 case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
775 OS << " __attribute__((vectorcall))";
776 break;
777 case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
778 OS << " __attribute__((pascal))";
779 break;
780 case dwarf::CallingConvention::DW_CC_LLVM_Win64:
781 OS << " __attribute__((ms_abi))";
782 break;
783 case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
784 OS << " __attribute__((sysv_abi))";
785 break;
786 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
787 // AArch64VectorCall missing?
788 OS << " __attribute__((pcs(\"aapcs\")))";
789 break;
790 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
791 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
792 break;
793 case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
794 OS << " __attribute__((intel_ocl_bicc))";
795 break;
796 case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
797 // This isn't available as an attribute, but maybe we should still
798 // render it somehow? (Clang doesn't render it, but that's an issue
799 // for template names too - since then the DWARF names of templates
800 // instantiated with function types with these calling conventions won't
801 // have distinct names - so we'd need to fix that too)
802 break;
803 case dwarf::CallingConvention::DW_CC_LLVM_DeviceKernel:
804 OS << " __attribute__((device_kernel))";
805 break;
806 case dwarf::CallingConvention::DW_CC_LLVM_Swift:
807 // SwiftAsync missing
808 OS << " __attribute__((swiftcall))";
809 break;
810 case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
811 OS << " __attribute__((preserve_most))";
812 break;
813 case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
814 OS << " __attribute__((preserve_all))";
815 break;
816 case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
817 OS << " __attribute__((preserve_none))";
818 break;
819 case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
820 OS << " __attribute__((regcall))";
821 break;
822 case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
823 OS << " __attribute__((m68k_rtd))";
824 break;
825 }
826 }
827
828 if (Const)
829 OS << " const";
830 if (Volatile)
831 OS << " volatile";
832 if (D.find(dwarf::DW_AT_reference))
833 OS << " &";
834 if (D.find(dwarf::DW_AT_rvalue_reference))
835 OS << " &&";
836
838}
839
840template <typename DieType>
842 if (D.getTag() == dwarf::DW_TAG_compile_unit)
843 return;
844 if (D.getTag() == dwarf::DW_TAG_type_unit)
845 return;
846 if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
847 return;
848 if (D.getTag() == dwarf::DW_TAG_subprogram)
849 return;
850 if (D.getTag() == dwarf::DW_TAG_lexical_block)
851 return;
852 D = D.resolveTypeUnitReference();
853 if (DieType P = D.getParent())
856 OS << "::";
857}
858} // namespace llvm
859
860#endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
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.
#define F(x, y, z)
Definition MD5.cpp:54
#define T
#define P(N)
This file defines the SmallSet class.
This file contains some functions that are useful when dealing with strings.
static dwarf::Attribute TypeAttr[]
Tagged union holding either a T or a Error.
Definition Error.h:485
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...
Definition SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
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.
Definition StringRef.h:56
static constexpr size_t npos
Definition StringRef.h:58
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:270
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition WithColor.cpp:85
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
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.
Definition CallingConv.h:34
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.
Attribute
Attributes.
Definition Dwarf.h:125
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
Definition InstrProf.h:139
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:129
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
#define N
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)