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