LLVM 22.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
13#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Error.h"
16
17#include <string>
18
19namespace llvm {
20
21class 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.
25template <typename DieType> struct DWARFTypePrinter {
27 bool Word = true;
28 bool EndedWithTemplate = false;
29
31
32 /// Dump the name encoded in the type tag.
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);
52 void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
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
65private:
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 /// If FormValue is a valid constant Form, print into \c OS the integral value
83 /// casted to the type referred to by \c Cast.
84 template <typename FormValueType>
85 void appendCastedValue(const FormValueType &FormValue, DieType Cast,
86 bool IsUnsigned);
87};
88
89template <typename DieType>
91 StringRef TagStr = TagString(T);
92 static constexpr StringRef Prefix = "DW_TAG_";
93 static constexpr StringRef Suffix = "_type";
94 if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
95 return;
96 OS << TagStr.substr(Prefix.size(),
97 TagStr.size() - (Prefix.size() + Suffix.size()))
98 << " ";
99}
100
101template <typename DieType>
103 for (const DieType &C : D.children()) {
104 if (C.getTag() != dwarf::DW_TAG_subrange_type)
105 continue;
106 std::optional<uint64_t> LB;
107 std::optional<uint64_t> Count;
108 std::optional<uint64_t> UB;
109 std::optional<unsigned> DefaultLB;
110 if (std::optional<typename DieType::DWARFFormValue> L =
111 C.find(dwarf::DW_AT_lower_bound))
112 LB = L->getAsUnsignedConstant();
113 if (std::optional<typename DieType::DWARFFormValue> CountV =
114 C.find(dwarf::DW_AT_count))
115 Count = CountV->getAsUnsignedConstant();
116 if (std::optional<typename DieType::DWARFFormValue> UpperV =
117 C.find(dwarf::DW_AT_upper_bound))
118 UB = UpperV->getAsUnsignedConstant();
119 if (std::optional<uint64_t> LV = D.getLanguage())
120 if ((DefaultLB =
121 LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LV))))
122 if (LB && *LB == *DefaultLB)
123 LB = std::nullopt;
124 if (!LB && !Count && !UB)
125 OS << "[]";
126 else if (!LB && (Count || UB) && DefaultLB)
127 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
128 else {
129 OS << "[[";
130 if (LB)
131 OS << *LB;
132 else
133 OS << '?';
134 OS << ", ";
135 if (Count)
136 if (LB)
137 OS << *LB + *Count;
138 else
139 OS << "? + " << *Count;
140 else if (UB)
141 OS << *UB + 1;
142 else
143 OS << '?';
144 OS << ")]";
145 }
146 }
147 EndedWithTemplate = false;
148}
149
150namespace detail {
151template <typename DieType>
152DieType resolveReferencedType(DieType D,
153 dwarf::Attribute Attr = dwarf::DW_AT_type) {
154 return D.resolveReferencedType(Attr);
155}
156template <typename DieType>
157DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
158 return D.resolveReferencedType(F);
159}
160template <typename DWARFFormValueType>
161const char *toString(std::optional<DWARFFormValueType> F) {
162 if (F) {
163 llvm::Expected<const char *> E = F->getAsCString();
164 if (E)
165 return *E;
166 llvm::consumeError(E.takeError());
167 }
168 return nullptr;
169}
170
171/// Resolve the DW_AT_type of \c D until we reach a DIE that is not a
172/// DW_TAG_typedef.
173template <typename DieType> DieType unwrapReferencedTypedefType(DieType D) {
174 auto TypeAttr = D.find(dwarf::DW_AT_type);
175 if (!TypeAttr)
176 return DieType();
177
178 auto Unwrapped = detail::resolveReferencedType(D, *TypeAttr);
179 if (!Unwrapped)
180 return DieType();
181
182 if (Unwrapped.getTag() == dwarf::DW_TAG_typedef)
183 return unwrapReferencedTypedefType(Unwrapped);
184
185 return Unwrapped;
186}
187} // namespace detail
188
189template <typename DieType>
191 while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
192 D.getTag() == dwarf::DW_TAG_volatile_type))
194 return D;
195}
196
197template <typename DieType>
199 D = skipQualifiers(D);
200 return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
201 D.getTag() == dwarf::DW_TAG_array_type);
202}
203
204template <typename DieType>
206 DieType Inner,
207 StringRef Ptr) {
209 if (Word)
210 OS << ' ';
211 if (needsParens(Inner))
212 OS << '(';
213 OS << Ptr;
214 Word = false;
215 EndedWithTemplate = false;
216}
217
218template <typename DieType>
220 DieType D, std::string *OriginalFullName) {
221 Word = true;
222 if (!D) {
223 OS << "void";
224 return DieType();
225 }
226 DieType InnerDIE;
227 auto Inner = [&] { return InnerDIE = detail::resolveReferencedType(D); };
228 const dwarf::Tag T = D.getTag();
229 switch (T) {
230 case dwarf::DW_TAG_pointer_type: {
231 appendPointerLikeTypeBefore(D, Inner(), "*");
232 break;
233 }
234 case dwarf::DW_TAG_subroutine_type: {
236 if (Word) {
237 OS << ' ';
238 }
239 Word = false;
240 break;
241 }
242 case dwarf::DW_TAG_array_type: {
244 break;
245 }
246 case dwarf::DW_TAG_reference_type:
247 appendPointerLikeTypeBefore(D, Inner(), "&");
248 break;
249 case dwarf::DW_TAG_rvalue_reference_type:
250 appendPointerLikeTypeBefore(D, Inner(), "&&");
251 break;
252 case dwarf::DW_TAG_ptr_to_member_type: {
254 if (needsParens(InnerDIE))
255 OS << '(';
256 else if (Word)
257 OS << ' ';
258 if (DieType Cont =
259 detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
261 EndedWithTemplate = false;
262 OS << "::";
263 }
264 OS << "*";
265 Word = false;
266 break;
267 }
268 case dwarf::DW_TAG_LLVM_ptrauth_type:
270 break;
271 case dwarf::DW_TAG_const_type:
272 case dwarf::DW_TAG_volatile_type:
274 break;
275 case dwarf::DW_TAG_namespace: {
276 if (const char *Name = detail::toString(D.find(dwarf::DW_AT_name)))
277 OS << Name;
278 else
279 OS << "(anonymous namespace)";
280 break;
281 }
282 case dwarf::DW_TAG_unspecified_type: {
283 StringRef TypeName = D.getShortName();
284 if (TypeName == "decltype(nullptr)")
285 TypeName = "std::nullptr_t";
286 Word = true;
287 OS << TypeName;
288 EndedWithTemplate = false;
289 break;
290 }
291 /*
292 case DW_TAG_structure_type:
293 case DW_TAG_class_type:
294 case DW_TAG_enumeration_type:
295 case DW_TAG_base_type:
296 */
297 default: {
298 const char *NamePtr = detail::toString(D.find(dwarf::DW_AT_name));
299 if (!NamePtr) {
300 appendTypeTagName(D.getTag());
301 return DieType();
302 }
303 Word = true;
304 StringRef Name = NamePtr;
305 static constexpr StringRef MangledPrefix = "_STN|";
306 if (Name.consume_front(MangledPrefix)) {
307 auto Separator = Name.find('|');
308 assert(Separator != StringRef::npos);
309 StringRef BaseName = Name.substr(0, Separator);
310 StringRef TemplateArgs = Name.substr(Separator + 1);
311 if (OriginalFullName)
312 *OriginalFullName = (BaseName + TemplateArgs).str();
313 Name = BaseName;
314 } else
315 EndedWithTemplate = Name.ends_with(">");
316 OS << Name;
317 // This check would be insufficient for operator overloads like
318 // "operator>>" - but for now Clang doesn't try to simplify them, so this
319 // is OK. Add more nuanced operator overload handling here if/when needed.
320 if (Name.ends_with(">"))
321 break;
323 break;
324
326 OS << ' ';
327 OS << '>';
328 EndedWithTemplate = true;
329 Word = true;
330 break;
331 }
332 }
333 return InnerDIE;
334}
335
336template <typename DieType>
338 DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
339 if (!D)
340 return;
341 switch (D.getTag()) {
342 case dwarf::DW_TAG_subroutine_type: {
343 appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
344 false);
345 break;
346 }
347 case dwarf::DW_TAG_array_type: {
349 break;
350 }
351 case dwarf::DW_TAG_const_type:
352 case dwarf::DW_TAG_volatile_type:
354 break;
355 case dwarf::DW_TAG_ptr_to_member_type:
356 case dwarf::DW_TAG_reference_type:
357 case dwarf::DW_TAG_rvalue_reference_type:
358 case dwarf::DW_TAG_pointer_type: {
359 if (needsParens(Inner))
360 OS << ')';
362 /*SkipFirstParamIfArtificial=*/D.getTag() ==
363 dwarf::DW_TAG_ptr_to_member_type);
364 break;
365 }
366 case dwarf::DW_TAG_LLVM_ptrauth_type: {
367 auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
368 if (auto Form = D.find(Attr))
369 return *Form->getAsUnsignedConstant();
370 return 0;
371 };
373 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
374 optionsVec.push_back("isa-pointer");
375 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))
376 optionsVec.push_back("authenticates-null-values");
377 if (auto AuthenticationMode =
378 D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {
379 switch (*AuthenticationMode->getAsUnsignedConstant()) {
380 case 0:
381 case 1:
382 optionsVec.push_back("strip");
383 break;
384 case 2:
385 optionsVec.push_back("sign-and-strip");
386 break;
387 default:
388 // Default authentication policy
389 break;
390 }
391 }
392 std::string options;
393 for (const auto *option : optionsVec) {
394 if (options.size())
395 options += ",";
396 options += option;
397 }
398 if (options.size())
399 options = ", \"" + options + "\"";
400 std::string PtrauthString;
401 llvm::raw_string_ostream PtrauthStream(PtrauthString);
402 PtrauthStream
403 << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "
404 << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
405 << ", 0x0"
406 << utohexstr(
407 getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
408 true)
409 << options << ")";
410 OS << PtrauthStream.str();
411 break;
412 }
413 /*
414 case DW_TAG_structure_type:
415 case DW_TAG_class_type:
416 case DW_TAG_enumeration_type:
417 case DW_TAG_base_type:
418 case DW_TAG_namespace:
419 */
420 default:
421 break;
422 }
423}
424
425template <typename DieType>
427 if (D && scopedTAGs(D.getTag()))
428 appendScopes(D.getParent());
430}
431
432template <typename DieType>
434 if (D && scopedTAGs(D.getTag()))
435 appendScopes(D.getParent());
437}
438
439template <typename DieType>
440template <typename FormValueType>
441void DWARFTypePrinter<DieType>::appendCastedValue(
442 const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {
443 std::string ValStr;
444 if (IsUnsigned) {
445 std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
446 if (!UVal)
447 return;
448
449 ValStr = std::to_string(*UVal);
450 } else {
451 std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
452 if (!SVal)
453 return;
454
455 ValStr = std::to_string(*SVal);
456 }
457
458 OS << '(';
459 appendQualifiedName(Cast);
460 OS << ')';
461 OS << std::move(ValStr);
462}
463
464template <typename DieType>
466 bool *FirstParameter) {
467 bool FirstParameterValue = true;
468 bool IsTemplate = false;
469 if (!FirstParameter)
470 FirstParameter = &FirstParameterValue;
471 for (const DieType &C : D) {
472 auto Sep = [&] {
473 if (*FirstParameter)
474 OS << '<';
475 else
476 OS << ", ";
477 IsTemplate = true;
478 EndedWithTemplate = false;
479 *FirstParameter = false;
480 };
481 if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
482 IsTemplate = true;
483 appendTemplateParameters(C, FirstParameter);
484 }
485 if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
487 Sep();
488 if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
489 auto V = C.find(dwarf::DW_AT_const_value);
490 appendCastedValue(*V, T, /*IsUnsigned=*/false);
491 continue;
492 }
493
494 // /Maybe/ we could do pointer/reference type parameters, looking for the
495 // symbol in the ELF symbol table to get back to the variable...
496 // but probably not worth it.
497 if (T.getTag() == dwarf::DW_TAG_pointer_type ||
498 T.getTag() == dwarf::DW_TAG_reference_type)
499 continue;
500 const char *RawName = detail::toString(T.find(dwarf::DW_AT_name));
501 assert(RawName);
502 StringRef Name = RawName;
503 auto V = C.find(dwarf::DW_AT_const_value);
504 bool IsQualifiedChar = false;
505 if (Name == "bool") {
506 OS << (*V->getAsUnsignedConstant() ? "true" : "false");
507 } else if (Name == "short") {
508 OS << "(short)";
509 OS << std::to_string(*V->getAsSignedConstant());
510 } else if (Name == "unsigned short") {
511 OS << "(unsigned short)";
512 OS << std::to_string(*V->getAsSignedConstant());
513 } else if (Name == "int")
514 OS << std::to_string(*V->getAsSignedConstant());
515 else if (Name == "long") {
516 OS << std::to_string(*V->getAsSignedConstant());
517 OS << "L";
518 } else if (Name == "long long") {
519 OS << std::to_string(*V->getAsSignedConstant());
520 OS << "LL";
521 } else if (Name == "unsigned int") {
522 OS << std::to_string(*V->getAsUnsignedConstant());
523 OS << "U";
524 } else if (Name == "unsigned long") {
525 OS << std::to_string(*V->getAsUnsignedConstant());
526 OS << "UL";
527 } else if (Name == "unsigned long long") {
528 OS << std::to_string(*V->getAsUnsignedConstant());
529 OS << "ULL";
530 } else if (Name == "char" ||
531 (IsQualifiedChar =
532 (Name == "unsigned char" || Name == "signed char"))) {
533 // FIXME: check T's DW_AT_type to see if it's signed or not (since
534 // char signedness is implementation defined).
535 auto Val = *V->getAsSignedConstant();
536 // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
537 // (doesn't actually support different character types/widths, sign
538 // handling's not done, and doesn't correctly test if a character is
539 // printable or needs to use a numeric escape sequence instead)
540 if (IsQualifiedChar) {
541 OS << '(';
542 OS << Name;
543 OS << ')';
544 }
545 switch (Val) {
546 case '\\':
547 OS << "'\\\\'";
548 break;
549 case '\'':
550 OS << "'\\''";
551 break;
552 case '\a':
553 // TODO: K&R: the meaning of '\\a' is different in traditional C
554 OS << "'\\a'";
555 break;
556 case '\b':
557 OS << "'\\b'";
558 break;
559 case '\f':
560 OS << "'\\f'";
561 break;
562 case '\n':
563 OS << "'\\n'";
564 break;
565 case '\r':
566 OS << "'\\r'";
567 break;
568 case '\t':
569 OS << "'\\t'";
570 break;
571 case '\v':
572 OS << "'\\v'";
573 break;
574 default:
575 if ((Val & ~0xFFu) == ~0xFFu)
576 Val &= 0xFFu;
577 if (Val < 127 && Val >= 32) {
578 OS << "'";
579 OS << (char)Val;
580 OS << "'";
581 } else if (Val < 256)
582 OS << llvm::format("'\\x%02" PRIx64 "'", Val);
583 else if (Val <= 0xFFFF)
584 OS << llvm::format("'\\u%04" PRIx64 "'", Val);
585 else
586 OS << llvm::format("'\\U%08" PRIx64 "'", Val);
587 }
588 // FIXME: Handle _BitInt's larger than 64-bits which are emitted as
589 // block data.
590 } else if (Name.starts_with("_BitInt")) {
591 appendCastedValue(*V, T, /*IsUnsigned=*/false);
592 } else if (Name.starts_with("unsigned _BitInt")) {
593 appendCastedValue(*V, T, /*IsUnsigned=*/true);
594 }
595 continue;
596 }
597 if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
598 const char *RawName =
599 detail::toString(C.find(dwarf::DW_AT_GNU_template_name));
600 assert(RawName);
601 StringRef Name = RawName;
602 Sep();
603 OS << Name;
604 continue;
605 }
606 if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
607 continue;
608 Sep();
609
611 }
612 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
613 OS << '<';
614 EndedWithTemplate = false;
615 }
616 return IsTemplate;
617}
618
619template <typename DieType>
621 DieType D) {
622 bool R = appendTemplateParameters(D);
623 if (!R)
624 return;
625
627 OS << " ";
628 OS << ">";
629 EndedWithTemplate = true;
630 Word = true;
631}
632
633template <typename DieType>
635 DieType &C, DieType &V) {
636 (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
638 if (T) {
639 auto Tag = T.getTag();
640 if (Tag == dwarf::DW_TAG_const_type) {
641 C = T;
643 } else if (Tag == dwarf::DW_TAG_volatile_type) {
644 V = T;
646 }
647 }
648}
649
650template <typename DieType>
652 DieType C;
653 DieType V;
654 DieType T;
656 if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
658 static_cast<bool>(C), static_cast<bool>(V));
659 else
661}
662
663template <typename DieType>
665 DieType C;
666 DieType V;
667 DieType T;
669 bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
670 DieType A = T;
671 while (A && A.getTag() == dwarf::DW_TAG_array_type)
673 bool Leading =
674 (!A || (A.getTag() != dwarf::DW_TAG_pointer_type &&
675 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
676 !Subroutine;
677 if (Leading) {
678 if (C)
679 OS << "const ";
680 if (V)
681 OS << "volatile ";
682 }
684 if (!Leading && !Subroutine) {
685 Word = true;
686 if (C)
687 OS << "const";
688 if (V) {
689 if (C)
690 OS << ' ';
691 OS << "volatile";
692 }
693 }
694}
695
696template <typename DieType>
698 DieType D, std::string *OriginalFullName) {
699 // FIXME: We should have pretty printers per language. Currently we print
700 // everything as if it was C++ and fall back to the TAG type name.
701 DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
703}
704
705template <typename DieType>
707 DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
708 bool Volatile) {
709 DieType FirstParamIfArtificial;
710 OS << '(';
711 EndedWithTemplate = false;
712 bool First = true;
713 bool RealFirst = true;
714 for (DieType P : D) {
715 if (P.getTag() != dwarf::DW_TAG_formal_parameter &&
716 P.getTag() != dwarf::DW_TAG_unspecified_parameters)
717 return;
719 if (SkipFirstParamIfArtificial && RealFirst &&
720 P.find(dwarf::DW_AT_artificial)) {
721 FirstParamIfArtificial = T;
722 RealFirst = false;
723 continue;
724 }
725 if (!First) {
726 OS << ", ";
727 }
728 First = false;
729 if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
730 OS << "...";
731 else
733 }
734 EndedWithTemplate = false;
735 OS << ')';
736 if (FirstParamIfArtificial) {
737 if (DieType P = FirstParamIfArtificial) {
738 if (P.getTag() == dwarf::DW_TAG_pointer_type) {
739 auto CVStep = [&](DieType CV) {
740 if (DieType U = detail::resolveReferencedType(CV)) {
741 Const |= U.getTag() == dwarf::DW_TAG_const_type;
742 Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
743 return U;
744 }
745 return DieType();
746 };
747 if (DieType CV = CVStep(P)) {
748 CVStep(CV);
749 }
750 }
751 }
752 }
753
754 if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {
755 switch (*CC->getAsUnsignedConstant()) {
756 case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
757 OS << " __attribute__((stdcall))";
758 break;
759 case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
760 OS << " __attribute__((fastcall))";
761 break;
762 case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
763 OS << " __attribute__((thiscall))";
764 break;
765 case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
766 OS << " __attribute__((vectorcall))";
767 break;
768 case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
769 OS << " __attribute__((pascal))";
770 break;
771 case dwarf::CallingConvention::DW_CC_LLVM_Win64:
772 OS << " __attribute__((ms_abi))";
773 break;
774 case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
775 OS << " __attribute__((sysv_abi))";
776 break;
777 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
778 // AArch64VectorCall missing?
779 OS << " __attribute__((pcs(\"aapcs\")))";
780 break;
781 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
782 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
783 break;
784 case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
785 OS << " __attribute__((intel_ocl_bicc))";
786 break;
787 case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
788 // This isn't available as an attribute, but maybe we should still
789 // render it somehow? (Clang doesn't render it, but that's an issue
790 // for template names too - since then the DWARF names of templates
791 // instantiated with function types with these calling conventions won't
792 // have distinct names - so we'd need to fix that too)
793 break;
794 case dwarf::CallingConvention::DW_CC_LLVM_DeviceKernel:
795 OS << " __attribute__((device_kernel))";
796 break;
797 case dwarf::CallingConvention::DW_CC_LLVM_Swift:
798 // SwiftAsync missing
799 OS << " __attribute__((swiftcall))";
800 break;
801 case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
802 OS << " __attribute__((preserve_most))";
803 break;
804 case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
805 OS << " __attribute__((preserve_all))";
806 break;
807 case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
808 OS << " __attribute__((preserve_none))";
809 break;
810 case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
811 OS << " __attribute__((regcall))";
812 break;
813 case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
814 OS << " __attribute__((m68k_rtd))";
815 break;
816 }
817 }
818
819 if (Const)
820 OS << " const";
821 if (Volatile)
822 OS << " volatile";
823 if (D.find(dwarf::DW_AT_reference))
824 OS << " &";
825 if (D.find(dwarf::DW_AT_rvalue_reference))
826 OS << " &&";
827
829}
830
831template <typename DieType>
833 if (D.getTag() == dwarf::DW_TAG_compile_unit)
834 return;
835 if (D.getTag() == dwarf::DW_TAG_type_unit)
836 return;
837 if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
838 return;
839 if (D.getTag() == dwarf::DW_TAG_subprogram)
840 return;
841 if (D.getTag() == dwarf::DW_TAG_lexical_block)
842 return;
843 D = D.resolveTypeUnitReference();
844 if (DieType P = D.getParent())
847 OS << "::";
848}
849} // namespace llvm
850
851#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 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
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
static constexpr size_t npos
Definition StringRef.h:57
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:261
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:273
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
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
#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)