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