1 //===-- ScopedPrinter.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_SUPPORT_SCOPEDPRINTER_H 10 #define LLVM_SUPPORT_SCOPEDPRINTER_H 11 12 #include "llvm/ADT/APSInt.h" 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/DataTypes.h" 18 #include "llvm/Support/Endian.h" 19 #include "llvm/Support/JSON.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 namespace llvm { 23 24 template <typename T> struct EnumEntry { 25 StringRef Name; 26 // While Name suffices in most of the cases, in certain cases 27 // GNU style and LLVM style of ELFDumper do not 28 // display same string for same enum. The AltName if initialized appropriately 29 // will hold the string that GNU style emits. 30 // Example: 31 // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to 32 // "Advanced Micro Devices X86-64" on GNU style 33 StringRef AltName; 34 T Value; 35 constexpr EnumEntry(StringRef N, StringRef A, T V) 36 : Name(N), AltName(A), Value(V) {} 37 constexpr EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {} 38 }; 39 40 struct HexNumber { 41 // To avoid sign-extension we have to explicitly cast to the appropriate 42 // unsigned type. The overloads are here so that every type that is implicitly 43 // convertible to an integer (including enums and endian helpers) can be used 44 // without requiring type traits or call-site changes. 45 HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {} 46 HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {} 47 HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {} 48 HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {} 49 HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {} 50 HexNumber(signed long long Value) 51 : Value(static_cast<unsigned long long>(Value)) {} 52 HexNumber(unsigned char Value) : Value(Value) {} 53 HexNumber(unsigned short Value) : Value(Value) {} 54 HexNumber(unsigned int Value) : Value(Value) {} 55 HexNumber(unsigned long Value) : Value(Value) {} 56 HexNumber(unsigned long long Value) : Value(Value) {} 57 uint64_t Value; 58 }; 59 60 struct FlagEntry { 61 FlagEntry(StringRef Name, char Value) 62 : Name(Name), Value(static_cast<unsigned char>(Value)) {} 63 FlagEntry(StringRef Name, signed char Value) 64 : Name(Name), Value(static_cast<unsigned char>(Value)) {} 65 FlagEntry(StringRef Name, signed short Value) 66 : Name(Name), Value(static_cast<unsigned short>(Value)) {} 67 FlagEntry(StringRef Name, signed int Value) 68 : Name(Name), Value(static_cast<unsigned int>(Value)) {} 69 FlagEntry(StringRef Name, signed long Value) 70 : Name(Name), Value(static_cast<unsigned long>(Value)) {} 71 FlagEntry(StringRef Name, signed long long Value) 72 : Name(Name), Value(static_cast<unsigned long long>(Value)) {} 73 FlagEntry(StringRef Name, unsigned char Value) : Name(Name), Value(Value) {} 74 FlagEntry(StringRef Name, unsigned short Value) : Name(Name), Value(Value) {} 75 FlagEntry(StringRef Name, unsigned int Value) : Name(Name), Value(Value) {} 76 FlagEntry(StringRef Name, unsigned long Value) : Name(Name), Value(Value) {} 77 FlagEntry(StringRef Name, unsigned long long Value) 78 : Name(Name), Value(Value) {} 79 StringRef Name; 80 uint64_t Value; 81 }; 82 83 raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value); 84 std::string to_hexString(uint64_t Value, bool UpperCase = true); 85 86 template <class T> std::string to_string(const T &Value) { 87 std::string number; 88 raw_string_ostream stream(number); 89 stream << Value; 90 return stream.str(); 91 } 92 93 template <typename T, typename TEnum> 94 std::string enumToString(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) { 95 for (const EnumEntry<TEnum> &EnumItem : EnumValues) 96 if (EnumItem.Value == Value) 97 return std::string(EnumItem.AltName); 98 return to_hexString(Value, false); 99 } 100 101 class ScopedPrinter { 102 public: 103 enum class ScopedPrinterKind { 104 Base, 105 JSON, 106 }; 107 108 ScopedPrinter(raw_ostream &OS, 109 ScopedPrinterKind Kind = ScopedPrinterKind::Base) 110 : OS(OS), IndentLevel(0), Kind(Kind) {} 111 112 ScopedPrinterKind getKind() const { return Kind; } 113 114 static bool classof(const ScopedPrinter *SP) { 115 return SP->getKind() == ScopedPrinterKind::Base; 116 } 117 118 virtual ~ScopedPrinter() = default; 119 120 void flush() { OS.flush(); } 121 122 void indent(int Levels = 1) { IndentLevel += Levels; } 123 124 void unindent(int Levels = 1) { 125 IndentLevel = IndentLevel > Levels ? IndentLevel - Levels : 0; 126 } 127 128 void resetIndent() { IndentLevel = 0; } 129 130 int getIndentLevel() { return IndentLevel; } 131 132 void setPrefix(StringRef P) { Prefix = P; } 133 134 void printIndent() { 135 OS << Prefix; 136 for (int i = 0; i < IndentLevel; ++i) 137 OS << " "; 138 } 139 140 template <typename T> HexNumber hex(T Value) { return HexNumber(Value); } 141 142 template <typename T, typename TEnum> 143 void printEnum(StringRef Label, T Value, 144 ArrayRef<EnumEntry<TEnum>> EnumValues) { 145 StringRef Name; 146 bool Found = false; 147 for (const auto &EnumItem : EnumValues) { 148 if (EnumItem.Value == Value) { 149 Name = EnumItem.Name; 150 Found = true; 151 break; 152 } 153 } 154 155 if (Found) 156 printHex(Label, Name, Value); 157 else 158 printHex(Label, Value); 159 } 160 161 template <typename T, typename TFlag> 162 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags, 163 TFlag EnumMask1 = {}, TFlag EnumMask2 = {}, 164 TFlag EnumMask3 = {}) { 165 SmallVector<FlagEntry, 10> SetFlags; 166 167 for (const auto &Flag : Flags) { 168 if (Flag.Value == 0) 169 continue; 170 171 TFlag EnumMask{}; 172 if (Flag.Value & EnumMask1) 173 EnumMask = EnumMask1; 174 else if (Flag.Value & EnumMask2) 175 EnumMask = EnumMask2; 176 else if (Flag.Value & EnumMask3) 177 EnumMask = EnumMask3; 178 bool IsEnum = (Flag.Value & EnumMask) != 0; 179 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 180 (IsEnum && (Value & EnumMask) == Flag.Value)) { 181 SetFlags.emplace_back(Flag.Name, Flag.Value); 182 } 183 } 184 185 llvm::sort(SetFlags, &flagName); 186 printFlagsImpl(Label, hex(Value), SetFlags); 187 } 188 189 template <typename T> void printFlags(StringRef Label, T Value) { 190 SmallVector<HexNumber, 10> SetFlags; 191 uint64_t Flag = 1; 192 uint64_t Curr = Value; 193 while (Curr > 0) { 194 if (Curr & 1) 195 SetFlags.emplace_back(Flag); 196 Curr >>= 1; 197 Flag <<= 1; 198 } 199 printFlagsImpl(Label, hex(Value), SetFlags); 200 } 201 202 virtual void printNumber(StringRef Label, uint64_t Value) { 203 startLine() << Label << ": " << Value << "\n"; 204 } 205 206 virtual void printNumber(StringRef Label, uint32_t Value) { 207 startLine() << Label << ": " << Value << "\n"; 208 } 209 210 virtual void printNumber(StringRef Label, uint16_t Value) { 211 startLine() << Label << ": " << Value << "\n"; 212 } 213 214 virtual void printNumber(StringRef Label, uint8_t Value) { 215 startLine() << Label << ": " << unsigned(Value) << "\n"; 216 } 217 218 virtual void printNumber(StringRef Label, int64_t Value) { 219 startLine() << Label << ": " << Value << "\n"; 220 } 221 222 virtual void printNumber(StringRef Label, int32_t Value) { 223 startLine() << Label << ": " << Value << "\n"; 224 } 225 226 virtual void printNumber(StringRef Label, int16_t Value) { 227 startLine() << Label << ": " << Value << "\n"; 228 } 229 230 virtual void printNumber(StringRef Label, int8_t Value) { 231 startLine() << Label << ": " << int(Value) << "\n"; 232 } 233 234 virtual void printNumber(StringRef Label, const APSInt &Value) { 235 startLine() << Label << ": " << Value << "\n"; 236 } 237 238 template <typename T> 239 void printNumber(StringRef Label, StringRef Str, T Value) { 240 printNumberImpl(Label, Str, to_string(Value)); 241 } 242 243 virtual void printBoolean(StringRef Label, bool Value) { 244 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; 245 } 246 247 template <typename... T> void printVersion(StringRef Label, T... Version) { 248 startLine() << Label << ": "; 249 printVersionInternal(Version...); 250 getOStream() << "\n"; 251 } 252 253 template <typename T> 254 void printList(StringRef Label, const ArrayRef<T> List) { 255 SmallVector<std::string, 10> StringList; 256 for (const auto &Item : List) 257 StringList.emplace_back(to_string(Item)); 258 printList(Label, StringList); 259 } 260 261 virtual void printList(StringRef Label, const ArrayRef<bool> List) { 262 printListImpl(Label, List); 263 } 264 265 virtual void printList(StringRef Label, const ArrayRef<std::string> List) { 266 printListImpl(Label, List); 267 } 268 269 virtual void printList(StringRef Label, const ArrayRef<uint64_t> List) { 270 printListImpl(Label, List); 271 } 272 273 virtual void printList(StringRef Label, const ArrayRef<uint32_t> List) { 274 printListImpl(Label, List); 275 } 276 277 virtual void printList(StringRef Label, const ArrayRef<uint16_t> List) { 278 printListImpl(Label, List); 279 } 280 281 virtual void printList(StringRef Label, const ArrayRef<uint8_t> List) { 282 SmallVector<unsigned> NumberList; 283 for (const uint8_t &Item : List) 284 NumberList.emplace_back(Item); 285 printListImpl(Label, NumberList); 286 } 287 288 virtual void printList(StringRef Label, const ArrayRef<int64_t> List) { 289 printListImpl(Label, List); 290 } 291 292 virtual void printList(StringRef Label, const ArrayRef<int32_t> List) { 293 printListImpl(Label, List); 294 } 295 296 virtual void printList(StringRef Label, const ArrayRef<int16_t> List) { 297 printListImpl(Label, List); 298 } 299 300 virtual void printList(StringRef Label, const ArrayRef<int8_t> List) { 301 SmallVector<int> NumberList; 302 for (const int8_t &Item : List) 303 NumberList.emplace_back(Item); 304 printListImpl(Label, NumberList); 305 } 306 307 virtual void printList(StringRef Label, const ArrayRef<APSInt> List) { 308 printListImpl(Label, List); 309 } 310 311 template <typename T, typename U> 312 void printList(StringRef Label, const T &List, const U &Printer) { 313 startLine() << Label << ": ["; 314 ListSeparator LS; 315 for (const auto &Item : List) { 316 OS << LS; 317 Printer(OS, Item); 318 } 319 OS << "]\n"; 320 } 321 322 template <typename T> void printHexList(StringRef Label, const T &List) { 323 SmallVector<HexNumber> HexList; 324 for (const auto &Item : List) 325 HexList.emplace_back(Item); 326 printHexListImpl(Label, HexList); 327 } 328 329 template <typename T> void printHex(StringRef Label, T Value) { 330 printHexImpl(Label, hex(Value)); 331 } 332 333 template <typename T> void printHex(StringRef Label, StringRef Str, T Value) { 334 printHexImpl(Label, Str, hex(Value)); 335 } 336 337 template <typename T> 338 void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) { 339 printSymbolOffsetImpl(Label, Symbol, hex(Value)); 340 } 341 342 virtual void printString(StringRef Value) { startLine() << Value << "\n"; } 343 344 virtual void printString(StringRef Label, StringRef Value) { 345 startLine() << Label << ": " << Value << "\n"; 346 } 347 348 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 349 printBinaryImpl(Label, Str, Value, false); 350 } 351 352 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 353 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 354 Value.size()); 355 printBinaryImpl(Label, Str, V, false); 356 } 357 358 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 359 printBinaryImpl(Label, StringRef(), Value, false); 360 } 361 362 void printBinary(StringRef Label, ArrayRef<char> Value) { 363 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 364 Value.size()); 365 printBinaryImpl(Label, StringRef(), V, false); 366 } 367 368 void printBinary(StringRef Label, StringRef Value) { 369 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 370 Value.size()); 371 printBinaryImpl(Label, StringRef(), V, false); 372 } 373 374 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value, 375 uint32_t StartOffset) { 376 printBinaryImpl(Label, StringRef(), Value, true, StartOffset); 377 } 378 379 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) { 380 printBinaryImpl(Label, StringRef(), Value, true); 381 } 382 383 void printBinaryBlock(StringRef Label, StringRef Value) { 384 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 385 Value.size()); 386 printBinaryImpl(Label, StringRef(), V, true); 387 } 388 389 template <typename T> void printObject(StringRef Label, const T &Value) { 390 printString(Label, to_string(Value)); 391 } 392 393 virtual void objectBegin() { scopedBegin('{'); } 394 395 virtual void objectBegin(StringRef Label) { scopedBegin(Label, '{'); } 396 397 virtual void objectEnd() { scopedEnd('}'); } 398 399 virtual void arrayBegin() { scopedBegin('['); } 400 401 virtual void arrayBegin(StringRef Label) { scopedBegin(Label, '['); } 402 403 virtual void arrayEnd() { scopedEnd(']'); } 404 405 virtual raw_ostream &startLine() { 406 printIndent(); 407 return OS; 408 } 409 410 virtual raw_ostream &getOStream() { return OS; } 411 412 private: 413 template <typename T> void printVersionInternal(T Value) { 414 getOStream() << Value; 415 } 416 417 template <typename S, typename T, typename... TArgs> 418 void printVersionInternal(S Value, T Value2, TArgs... Args) { 419 getOStream() << Value << "."; 420 printVersionInternal(Value2, Args...); 421 } 422 423 static bool flagName(const FlagEntry &LHS, const FlagEntry &RHS) { 424 return LHS.Name < RHS.Name; 425 } 426 427 virtual void printBinaryImpl(StringRef Label, StringRef Str, 428 ArrayRef<uint8_t> Value, bool Block, 429 uint32_t StartOffset = 0); 430 431 virtual void printFlagsImpl(StringRef Label, HexNumber Value, 432 ArrayRef<FlagEntry> Flags) { 433 startLine() << Label << " [ (" << Value << ")\n"; 434 for (const auto &Flag : Flags) 435 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; 436 startLine() << "]\n"; 437 } 438 439 virtual void printFlagsImpl(StringRef Label, HexNumber Value, 440 ArrayRef<HexNumber> Flags) { 441 startLine() << Label << " [ (" << Value << ")\n"; 442 for (const auto &Flag : Flags) 443 startLine() << " " << Flag << '\n'; 444 startLine() << "]\n"; 445 } 446 447 template <typename T> void printListImpl(StringRef Label, const T List) { 448 startLine() << Label << ": ["; 449 ListSeparator LS; 450 for (const auto &Item : List) 451 OS << LS << Item; 452 OS << "]\n"; 453 } 454 455 virtual void printHexListImpl(StringRef Label, 456 const ArrayRef<HexNumber> List) { 457 startLine() << Label << ": ["; 458 ListSeparator LS; 459 for (const auto &Item : List) 460 OS << LS << hex(Item); 461 OS << "]\n"; 462 } 463 464 virtual void printHexImpl(StringRef Label, HexNumber Value) { 465 startLine() << Label << ": " << Value << "\n"; 466 } 467 468 virtual void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) { 469 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 470 } 471 472 virtual void printSymbolOffsetImpl(StringRef Label, StringRef Symbol, 473 HexNumber Value) { 474 startLine() << Label << ": " << Symbol << '+' << Value << '\n'; 475 } 476 477 virtual void printNumberImpl(StringRef Label, StringRef Str, 478 StringRef Value) { 479 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 480 } 481 482 void scopedBegin(char Symbol) { 483 startLine() << Symbol << '\n'; 484 indent(); 485 } 486 487 void scopedBegin(StringRef Label, char Symbol) { 488 startLine() << Label; 489 if (!Label.empty()) 490 OS << ' '; 491 OS << Symbol << '\n'; 492 indent(); 493 } 494 495 void scopedEnd(char Symbol) { 496 unindent(); 497 startLine() << Symbol << '\n'; 498 } 499 500 raw_ostream &OS; 501 int IndentLevel; 502 StringRef Prefix; 503 ScopedPrinterKind Kind; 504 }; 505 506 template <> 507 inline void 508 ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label, 509 support::ulittle16_t Value) { 510 startLine() << Label << ": " << hex(Value) << "\n"; 511 } 512 513 struct DelimitedScope; 514 515 class JSONScopedPrinter : public ScopedPrinter { 516 private: 517 enum class Scope { 518 Array, 519 Object, 520 }; 521 522 enum class ScopeKind { 523 NoAttribute, 524 Attribute, 525 NestedAttribute, 526 }; 527 528 struct ScopeContext { 529 Scope Context; 530 ScopeKind Kind; 531 ScopeContext(Scope Context, ScopeKind Kind = ScopeKind::NoAttribute) 532 : Context(Context), Kind(Kind) {} 533 }; 534 535 SmallVector<ScopeContext, 8> ScopeHistory; 536 json::OStream JOS; 537 std::unique_ptr<DelimitedScope> OuterScope; 538 539 public: 540 JSONScopedPrinter(raw_ostream &OS, bool PrettyPrint = false, 541 std::unique_ptr<DelimitedScope> &&OuterScope = 542 std::unique_ptr<DelimitedScope>{}); 543 544 static bool classof(const ScopedPrinter *SP) { 545 return SP->getKind() == ScopedPrinter::ScopedPrinterKind::JSON; 546 } 547 548 void printNumber(StringRef Label, uint64_t Value) override { 549 JOS.attribute(Label, Value); 550 } 551 552 void printNumber(StringRef Label, uint32_t Value) override { 553 JOS.attribute(Label, Value); 554 } 555 556 void printNumber(StringRef Label, uint16_t Value) override { 557 JOS.attribute(Label, Value); 558 } 559 560 void printNumber(StringRef Label, uint8_t Value) override { 561 JOS.attribute(Label, Value); 562 } 563 564 void printNumber(StringRef Label, int64_t Value) override { 565 JOS.attribute(Label, Value); 566 } 567 568 void printNumber(StringRef Label, int32_t Value) override { 569 JOS.attribute(Label, Value); 570 } 571 572 void printNumber(StringRef Label, int16_t Value) override { 573 JOS.attribute(Label, Value); 574 } 575 576 void printNumber(StringRef Label, int8_t Value) override { 577 JOS.attribute(Label, Value); 578 } 579 580 void printNumber(StringRef Label, const APSInt &Value) override { 581 JOS.attributeBegin(Label); 582 printAPSInt(Value); 583 JOS.attributeEnd(); 584 } 585 586 void printBoolean(StringRef Label, bool Value) override { 587 JOS.attribute(Label, Value); 588 } 589 590 void printList(StringRef Label, const ArrayRef<bool> List) override { 591 printListImpl(Label, List); 592 } 593 594 void printList(StringRef Label, const ArrayRef<std::string> List) override { 595 printListImpl(Label, List); 596 } 597 598 void printList(StringRef Label, const ArrayRef<uint64_t> List) override { 599 printListImpl(Label, List); 600 } 601 602 void printList(StringRef Label, const ArrayRef<uint32_t> List) override { 603 printListImpl(Label, List); 604 } 605 606 void printList(StringRef Label, const ArrayRef<uint16_t> List) override { 607 printListImpl(Label, List); 608 } 609 610 void printList(StringRef Label, const ArrayRef<uint8_t> List) override { 611 printListImpl(Label, List); 612 } 613 614 void printList(StringRef Label, const ArrayRef<int64_t> List) override { 615 printListImpl(Label, List); 616 } 617 618 void printList(StringRef Label, const ArrayRef<int32_t> List) override { 619 printListImpl(Label, List); 620 } 621 622 void printList(StringRef Label, const ArrayRef<int16_t> List) override { 623 printListImpl(Label, List); 624 } 625 626 void printList(StringRef Label, const ArrayRef<int8_t> List) override { 627 printListImpl(Label, List); 628 } 629 630 void printList(StringRef Label, const ArrayRef<APSInt> List) override { 631 JOS.attributeArray(Label, [&]() { 632 for (const APSInt &Item : List) { 633 printAPSInt(Item); 634 } 635 }); 636 } 637 638 void printString(StringRef Value) override { JOS.value(Value); } 639 640 void printString(StringRef Label, StringRef Value) override { 641 JOS.attribute(Label, Value); 642 } 643 644 void objectBegin() override { 645 scopedBegin({Scope::Object, ScopeKind::NoAttribute}); 646 } 647 648 void objectBegin(StringRef Label) override { 649 scopedBegin(Label, Scope::Object); 650 } 651 652 void objectEnd() override { scopedEnd(); } 653 654 void arrayBegin() override { 655 scopedBegin({Scope::Array, ScopeKind::NoAttribute}); 656 } 657 658 void arrayBegin(StringRef Label) override { 659 scopedBegin(Label, Scope::Array); 660 } 661 662 void arrayEnd() override { scopedEnd(); } 663 664 private: 665 // Output HexNumbers as decimals so that they're easier to parse. 666 uint64_t hexNumberToInt(HexNumber Hex) { return Hex.Value; } 667 668 void printAPSInt(const APSInt &Value) { 669 JOS.rawValueBegin() << Value; 670 JOS.rawValueEnd(); 671 } 672 673 void printFlagsImpl(StringRef Label, HexNumber Value, 674 ArrayRef<FlagEntry> Flags) override { 675 JOS.attributeObject(Label, [&]() { 676 JOS.attribute("RawFlags", hexNumberToInt(Value)); 677 JOS.attributeArray("Flags", [&]() { 678 for (const FlagEntry &Flag : Flags) { 679 JOS.objectBegin(); 680 JOS.attribute("Name", Flag.Name); 681 JOS.attribute("Value", Flag.Value); 682 JOS.objectEnd(); 683 } 684 }); 685 }); 686 } 687 688 void printFlagsImpl(StringRef Label, HexNumber Value, 689 ArrayRef<HexNumber> Flags) override { 690 JOS.attributeObject(Label, [&]() { 691 JOS.attribute("RawFlags", hexNumberToInt(Value)); 692 JOS.attributeArray("Flags", [&]() { 693 for (const HexNumber &Flag : Flags) { 694 JOS.value(Flag.Value); 695 } 696 }); 697 }); 698 } 699 700 template <typename T> void printListImpl(StringRef Label, const T &List) { 701 JOS.attributeArray(Label, [&]() { 702 for (const auto &Item : List) 703 JOS.value(Item); 704 }); 705 } 706 707 void printHexListImpl(StringRef Label, 708 const ArrayRef<HexNumber> List) override { 709 JOS.attributeArray(Label, [&]() { 710 for (const HexNumber &Item : List) { 711 JOS.value(hexNumberToInt(Item)); 712 } 713 }); 714 } 715 716 void printHexImpl(StringRef Label, HexNumber Value) override { 717 JOS.attribute(Label, hexNumberToInt(Value)); 718 } 719 720 void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) override { 721 JOS.attributeObject(Label, [&]() { 722 JOS.attribute("Value", Str); 723 JOS.attribute("RawValue", hexNumberToInt(Value)); 724 }); 725 } 726 727 void printSymbolOffsetImpl(StringRef Label, StringRef Symbol, 728 HexNumber Value) override { 729 JOS.attributeObject(Label, [&]() { 730 JOS.attribute("SymName", Symbol); 731 JOS.attribute("Offset", hexNumberToInt(Value)); 732 }); 733 } 734 735 void printNumberImpl(StringRef Label, StringRef Str, 736 StringRef Value) override { 737 JOS.attributeObject(Label, [&]() { 738 JOS.attribute("Value", Str); 739 JOS.attributeBegin("RawValue"); 740 JOS.rawValueBegin() << Value; 741 JOS.rawValueEnd(); 742 JOS.attributeEnd(); 743 }); 744 } 745 746 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 747 bool Block, uint32_t StartOffset = 0) override { 748 JOS.attributeObject(Label, [&]() { 749 if (!Str.empty()) 750 JOS.attribute("Value", Str); 751 JOS.attribute("Offset", StartOffset); 752 JOS.attributeArray("Bytes", [&]() { 753 for (uint8_t Val : Value) 754 JOS.value(Val); 755 }); 756 }); 757 } 758 759 void scopedBegin(ScopeContext ScopeCtx) { 760 if (ScopeCtx.Context == Scope::Object) 761 JOS.objectBegin(); 762 else if (ScopeCtx.Context == Scope::Array) 763 JOS.arrayBegin(); 764 ScopeHistory.push_back(ScopeCtx); 765 } 766 767 void scopedBegin(StringRef Label, Scope Ctx) { 768 ScopeKind Kind = ScopeKind::Attribute; 769 if (ScopeHistory.empty() || ScopeHistory.back().Context != Scope::Object) { 770 JOS.objectBegin(); 771 Kind = ScopeKind::NestedAttribute; 772 } 773 JOS.attributeBegin(Label); 774 scopedBegin({Ctx, Kind}); 775 } 776 777 void scopedEnd() { 778 ScopeContext ScopeCtx = ScopeHistory.back(); 779 if (ScopeCtx.Context == Scope::Object) 780 JOS.objectEnd(); 781 else if (ScopeCtx.Context == Scope::Array) 782 JOS.arrayEnd(); 783 if (ScopeCtx.Kind == ScopeKind::Attribute || 784 ScopeCtx.Kind == ScopeKind::NestedAttribute) 785 JOS.attributeEnd(); 786 if (ScopeCtx.Kind == ScopeKind::NestedAttribute) 787 JOS.objectEnd(); 788 ScopeHistory.pop_back(); 789 } 790 }; 791 792 struct DelimitedScope { 793 DelimitedScope(ScopedPrinter &W) : W(&W) {} 794 DelimitedScope() : W(nullptr) {} 795 virtual ~DelimitedScope() = default; 796 virtual void setPrinter(ScopedPrinter &W) = 0; 797 ScopedPrinter *W; 798 }; 799 800 struct DictScope : DelimitedScope { 801 explicit DictScope() = default; 802 explicit DictScope(ScopedPrinter &W) : DelimitedScope(W) { W.objectBegin(); } 803 804 DictScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) { 805 W.objectBegin(N); 806 } 807 808 void setPrinter(ScopedPrinter &W) override { 809 this->W = &W; 810 W.objectBegin(); 811 } 812 813 ~DictScope() { 814 if (W) 815 W->objectEnd(); 816 } 817 }; 818 819 struct ListScope : DelimitedScope { 820 explicit ListScope() = default; 821 explicit ListScope(ScopedPrinter &W) : DelimitedScope(W) { W.arrayBegin(); } 822 823 ListScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) { 824 W.arrayBegin(N); 825 } 826 827 void setPrinter(ScopedPrinter &W) override { 828 this->W = &W; 829 W.arrayBegin(); 830 } 831 832 ~ListScope() { 833 if (W) 834 W->arrayEnd(); 835 } 836 }; 837 838 } // namespace llvm 839 840 #endif 841