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