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