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 
85 template <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 
92 template <typename T, typename TEnum>
93 std::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 
100 class ScopedPrinter {
101 public:
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, uint64_t Value) {
202     startLine() << Label << ": " << Value << "\n";
203   }
204 
205   virtual void printNumber(StringRef Label, uint32_t Value) {
206     startLine() << Label << ": " << Value << "\n";
207   }
208 
209   virtual void printNumber(StringRef Label, uint16_t Value) {
210     startLine() << Label << ": " << Value << "\n";
211   }
212 
213   virtual void printNumber(StringRef Label, uint8_t Value) {
214     startLine() << Label << ": " << unsigned(Value) << "\n";
215   }
216 
217   virtual void printNumber(StringRef Label, int64_t Value) {
218     startLine() << Label << ": " << Value << "\n";
219   }
220 
221   virtual void printNumber(StringRef Label, int32_t Value) {
222     startLine() << Label << ": " << Value << "\n";
223   }
224 
225   virtual void printNumber(StringRef Label, int16_t Value) {
226     startLine() << Label << ": " << Value << "\n";
227   }
228 
229   virtual void printNumber(StringRef Label, int8_t Value) {
230     startLine() << Label << ": " << int(Value) << "\n";
231   }
232 
233   virtual void printNumber(StringRef Label, const APSInt &Value) {
234     startLine() << Label << ": " << Value << "\n";
235   }
236 
237   template <typename T>
238   void printNumber(StringRef Label, StringRef Str, T Value) {
239     printNumberImpl(Label, Str, to_string(Value));
240   }
241 
242   virtual void printBoolean(StringRef Label, bool Value) {
243     startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
244   }
245 
246   template <typename... T> void printVersion(StringRef Label, T... Version) {
247     startLine() << Label << ": ";
248     printVersionInternal(Version...);
249     getOStream() << "\n";
250   }
251 
252   template <typename T>
253   void printList(StringRef Label, const ArrayRef<T> List) {
254     SmallVector<std::string, 10> StringList;
255     for (const auto &Item : List)
256       StringList.emplace_back(to_string(Item));
257     printList(Label, StringList);
258   }
259 
260   virtual void printList(StringRef Label, const ArrayRef<bool> List) {
261     printListImpl(Label, List);
262   }
263 
264   virtual void printList(StringRef Label, const ArrayRef<std::string> List) {
265     printListImpl(Label, List);
266   }
267 
268   virtual void printList(StringRef Label, const ArrayRef<uint64_t> List) {
269     printListImpl(Label, List);
270   }
271 
272   virtual void printList(StringRef Label, const ArrayRef<uint32_t> List) {
273     printListImpl(Label, List);
274   }
275 
276   virtual void printList(StringRef Label, const ArrayRef<uint16_t> List) {
277     printListImpl(Label, List);
278   }
279 
280   virtual void printList(StringRef Label, const ArrayRef<uint8_t> List) {
281     SmallVector<unsigned> NumberList;
282     for (const uint8_t &Item : List)
283       NumberList.emplace_back(Item);
284     printListImpl(Label, NumberList);
285   }
286 
287   virtual void printList(StringRef Label, const ArrayRef<int64_t> List) {
288     printListImpl(Label, List);
289   }
290 
291   virtual void printList(StringRef Label, const ArrayRef<int32_t> List) {
292     printListImpl(Label, List);
293   }
294 
295   virtual void printList(StringRef Label, const ArrayRef<int16_t> List) {
296     printListImpl(Label, List);
297   }
298 
299   virtual void printList(StringRef Label, const ArrayRef<int8_t> List) {
300     SmallVector<int> NumberList;
301     for (const int8_t &Item : List)
302       NumberList.emplace_back(Item);
303     printListImpl(Label, NumberList);
304   }
305 
306   virtual void printList(StringRef Label, const ArrayRef<APSInt> List) {
307     printListImpl(Label, List);
308   }
309 
310   template <typename T, typename U>
311   void printList(StringRef Label, const T &List, const U &Printer) {
312     startLine() << Label << ": [";
313     ListSeparator LS;
314     for (const auto &Item : List) {
315       OS << LS;
316       Printer(OS, Item);
317     }
318     OS << "]\n";
319   }
320 
321   template <typename T> void printHexList(StringRef Label, const T &List) {
322     SmallVector<HexNumber> HexList;
323     for (const auto &Item : List)
324       HexList.emplace_back(Item);
325     printHexListImpl(Label, HexList);
326   }
327 
328   template <typename T> void printHex(StringRef Label, T Value) {
329     printHexImpl(Label, hex(Value));
330   }
331 
332   template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
333     printHexImpl(Label, Str, hex(Value));
334   }
335 
336   template <typename T>
337   void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
338     printSymbolOffsetImpl(Label, Symbol, hex(Value));
339   }
340 
341   virtual void printString(StringRef Value) { startLine() << Value << "\n"; }
342 
343   virtual void printString(StringRef Label, StringRef Value) {
344     startLine() << Label << ": " << Value << "\n";
345   }
346 
347   void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
348     printBinaryImpl(Label, Str, Value, false);
349   }
350 
351   void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
352     auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
353                           Value.size());
354     printBinaryImpl(Label, Str, V, false);
355   }
356 
357   void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
358     printBinaryImpl(Label, StringRef(), Value, false);
359   }
360 
361   void printBinary(StringRef Label, ArrayRef<char> Value) {
362     auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
363                           Value.size());
364     printBinaryImpl(Label, StringRef(), V, false);
365   }
366 
367   void printBinary(StringRef Label, StringRef Value) {
368     auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
369                           Value.size());
370     printBinaryImpl(Label, StringRef(), V, false);
371   }
372 
373   void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value,
374                         uint32_t StartOffset) {
375     printBinaryImpl(Label, StringRef(), Value, true, StartOffset);
376   }
377 
378   void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
379     printBinaryImpl(Label, StringRef(), Value, true);
380   }
381 
382   void printBinaryBlock(StringRef Label, StringRef Value) {
383     auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
384                           Value.size());
385     printBinaryImpl(Label, StringRef(), V, true);
386   }
387 
388   template <typename T> void printObject(StringRef Label, const T &Value) {
389     printString(Label, to_string(Value));
390   }
391 
392   virtual void objectBegin() { scopedBegin('{'); }
393 
394   virtual void objectBegin(StringRef Label) { scopedBegin(Label, '{'); }
395 
396   virtual void objectEnd() { scopedEnd('}'); }
397 
398   virtual void arrayBegin() { scopedBegin('['); }
399 
400   virtual void arrayBegin(StringRef Label) { scopedBegin(Label, '['); }
401 
402   virtual void arrayEnd() { scopedEnd(']'); }
403 
404   virtual raw_ostream &startLine() {
405     printIndent();
406     return OS;
407   }
408 
409   virtual raw_ostream &getOStream() { return OS; }
410 
411 private:
412   template <typename T> void printVersionInternal(T Value) {
413     getOStream() << Value;
414   }
415 
416   template <typename S, typename T, typename... TArgs>
417   void printVersionInternal(S Value, T Value2, TArgs... Args) {
418     getOStream() << Value << ".";
419     printVersionInternal(Value2, Args...);
420   }
421 
422   static bool flagName(const FlagEntry &LHS, const FlagEntry &RHS) {
423     return LHS.Name < RHS.Name;
424   }
425 
426   virtual void printBinaryImpl(StringRef Label, StringRef Str,
427                                ArrayRef<uint8_t> Value, bool Block,
428                                uint32_t StartOffset = 0);
429 
430   virtual void printFlagsImpl(StringRef Label, HexNumber Value,
431                               ArrayRef<FlagEntry> Flags) {
432     startLine() << Label << " [ (" << Value << ")\n";
433     for (const auto &Flag : Flags)
434       startLine() << "  " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
435     startLine() << "]\n";
436   }
437 
438   virtual void printFlagsImpl(StringRef Label, HexNumber Value,
439                               ArrayRef<HexNumber> Flags) {
440     startLine() << Label << " [ (" << Value << ")\n";
441     for (const auto &Flag : Flags)
442       startLine() << "  " << Flag << '\n';
443     startLine() << "]\n";
444   }
445 
446   template <typename T> void printListImpl(StringRef Label, const T List) {
447     startLine() << Label << ": [";
448     ListSeparator LS;
449     for (const auto &Item : List)
450       OS << LS << Item;
451     OS << "]\n";
452   }
453 
454   virtual void printHexListImpl(StringRef Label,
455                                 const ArrayRef<HexNumber> List) {
456     startLine() << Label << ": [";
457     ListSeparator LS;
458     for (const auto &Item : List)
459       OS << LS << hex(Item);
460     OS << "]\n";
461   }
462 
463   virtual void printHexImpl(StringRef Label, HexNumber Value) {
464     startLine() << Label << ": " << Value << "\n";
465   }
466 
467   virtual void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) {
468     startLine() << Label << ": " << Str << " (" << Value << ")\n";
469   }
470 
471   virtual void printSymbolOffsetImpl(StringRef Label, StringRef Symbol,
472                                      HexNumber Value) {
473     startLine() << Label << ": " << Symbol << '+' << Value << '\n';
474   }
475 
476   virtual void printNumberImpl(StringRef Label, StringRef Str,
477                                StringRef Value) {
478     startLine() << Label << ": " << Str << " (" << Value << ")\n";
479   }
480 
481   void scopedBegin(char Symbol) {
482     startLine() << Symbol << '\n';
483     indent();
484   }
485 
486   void scopedBegin(StringRef Label, char Symbol) {
487     startLine() << Label;
488     if (!Label.empty())
489       OS << ' ';
490     OS << Symbol << '\n';
491     indent();
492   }
493 
494   void scopedEnd(char Symbol) {
495     unindent();
496     startLine() << Symbol << '\n';
497   }
498 
499   raw_ostream &OS;
500   int IndentLevel = 0;
501   StringRef Prefix;
502   ScopedPrinterKind Kind;
503 };
504 
505 template <>
506 inline void
507 ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
508                                               support::ulittle16_t Value) {
509   startLine() << Label << ": " << hex(Value) << "\n";
510 }
511 
512 struct DelimitedScope;
513 
514 class JSONScopedPrinter : public ScopedPrinter {
515 private:
516   enum class Scope {
517     Array,
518     Object,
519   };
520 
521   enum class ScopeKind {
522     NoAttribute,
523     Attribute,
524     NestedAttribute,
525   };
526 
527   struct ScopeContext {
528     Scope Context;
529     ScopeKind Kind;
530     ScopeContext(Scope Context, ScopeKind Kind = ScopeKind::NoAttribute)
531         : Context(Context), Kind(Kind) {}
532   };
533 
534   SmallVector<ScopeContext, 8> ScopeHistory;
535   json::OStream JOS;
536   std::unique_ptr<DelimitedScope> OuterScope;
537 
538 public:
539   JSONScopedPrinter(raw_ostream &OS, bool PrettyPrint = false,
540                     std::unique_ptr<DelimitedScope> &&OuterScope =
541                         std::unique_ptr<DelimitedScope>{});
542 
543   static bool classof(const ScopedPrinter *SP) {
544     return SP->getKind() == ScopedPrinter::ScopedPrinterKind::JSON;
545   }
546 
547   void printNumber(StringRef Label, uint64_t Value) override {
548     JOS.attribute(Label, Value);
549   }
550 
551   void printNumber(StringRef Label, uint32_t Value) override {
552     JOS.attribute(Label, Value);
553   }
554 
555   void printNumber(StringRef Label, uint16_t Value) override {
556     JOS.attribute(Label, Value);
557   }
558 
559   void printNumber(StringRef Label, uint8_t Value) override {
560     JOS.attribute(Label, Value);
561   }
562 
563   void printNumber(StringRef Label, int64_t Value) override {
564     JOS.attribute(Label, Value);
565   }
566 
567   void printNumber(StringRef Label, int32_t Value) override {
568     JOS.attribute(Label, Value);
569   }
570 
571   void printNumber(StringRef Label, int16_t Value) override {
572     JOS.attribute(Label, Value);
573   }
574 
575   void printNumber(StringRef Label, int8_t Value) override {
576     JOS.attribute(Label, Value);
577   }
578 
579   void printNumber(StringRef Label, const APSInt &Value) override {
580     JOS.attributeBegin(Label);
581     printAPSInt(Value);
582     JOS.attributeEnd();
583   }
584 
585   void printBoolean(StringRef Label, bool Value) override {
586     JOS.attribute(Label, Value);
587   }
588 
589   void printList(StringRef Label, const ArrayRef<bool> List) override {
590     printListImpl(Label, List);
591   }
592 
593   void printList(StringRef Label, const ArrayRef<std::string> List) override {
594     printListImpl(Label, List);
595   }
596 
597   void printList(StringRef Label, const ArrayRef<uint64_t> List) override {
598     printListImpl(Label, List);
599   }
600 
601   void printList(StringRef Label, const ArrayRef<uint32_t> List) override {
602     printListImpl(Label, List);
603   }
604 
605   void printList(StringRef Label, const ArrayRef<uint16_t> List) override {
606     printListImpl(Label, List);
607   }
608 
609   void printList(StringRef Label, const ArrayRef<uint8_t> List) override {
610     printListImpl(Label, List);
611   }
612 
613   void printList(StringRef Label, const ArrayRef<int64_t> List) override {
614     printListImpl(Label, List);
615   }
616 
617   void printList(StringRef Label, const ArrayRef<int32_t> List) override {
618     printListImpl(Label, List);
619   }
620 
621   void printList(StringRef Label, const ArrayRef<int16_t> List) override {
622     printListImpl(Label, List);
623   }
624 
625   void printList(StringRef Label, const ArrayRef<int8_t> List) override {
626     printListImpl(Label, List);
627   }
628 
629   void printList(StringRef Label, const ArrayRef<APSInt> List) override {
630     JOS.attributeArray(Label, [&]() {
631       for (const APSInt &Item : List) {
632         printAPSInt(Item);
633       }
634     });
635   }
636 
637   void printString(StringRef Value) override { JOS.value(Value); }
638 
639   void printString(StringRef Label, StringRef Value) override {
640     JOS.attribute(Label, Value);
641   }
642 
643   void objectBegin() override {
644     scopedBegin({Scope::Object, ScopeKind::NoAttribute});
645   }
646 
647   void objectBegin(StringRef Label) override {
648     scopedBegin(Label, Scope::Object);
649   }
650 
651   void objectEnd() override { scopedEnd(); }
652 
653   void arrayBegin() override {
654     scopedBegin({Scope::Array, ScopeKind::NoAttribute});
655   }
656 
657   void arrayBegin(StringRef Label) override {
658     scopedBegin(Label, Scope::Array);
659   }
660 
661   void arrayEnd() override { scopedEnd(); }
662 
663 private:
664   // Output HexNumbers as decimals so that they're easier to parse.
665   uint64_t hexNumberToInt(HexNumber Hex) { return Hex.Value; }
666 
667   void printAPSInt(const APSInt &Value) {
668     JOS.rawValueBegin() << Value;
669     JOS.rawValueEnd();
670   }
671 
672   void printFlagsImpl(StringRef Label, HexNumber Value,
673                       ArrayRef<FlagEntry> Flags) override {
674     JOS.attributeObject(Label, [&]() {
675       JOS.attribute("RawFlags", hexNumberToInt(Value));
676       JOS.attributeArray("Flags", [&]() {
677         for (const FlagEntry &Flag : Flags) {
678           JOS.objectBegin();
679           JOS.attribute("Name", Flag.Name);
680           JOS.attribute("Value", Flag.Value);
681           JOS.objectEnd();
682         }
683       });
684     });
685   }
686 
687   void printFlagsImpl(StringRef Label, HexNumber Value,
688                       ArrayRef<HexNumber> Flags) override {
689     JOS.attributeObject(Label, [&]() {
690       JOS.attribute("RawFlags", hexNumberToInt(Value));
691       JOS.attributeArray("Flags", [&]() {
692         for (const HexNumber &Flag : Flags) {
693           JOS.value(Flag.Value);
694         }
695       });
696     });
697   }
698 
699   template <typename T> void printListImpl(StringRef Label, const T &List) {
700     JOS.attributeArray(Label, [&]() {
701       for (const auto &Item : List)
702         JOS.value(Item);
703     });
704   }
705 
706   void printHexListImpl(StringRef Label,
707                         const ArrayRef<HexNumber> List) override {
708     JOS.attributeArray(Label, [&]() {
709       for (const HexNumber &Item : List) {
710         JOS.value(hexNumberToInt(Item));
711       }
712     });
713   }
714 
715   void printHexImpl(StringRef Label, HexNumber Value) override {
716     JOS.attribute(Label, hexNumberToInt(Value));
717   }
718 
719   void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) override {
720     JOS.attributeObject(Label, [&]() {
721       JOS.attribute("Value", Str);
722       JOS.attribute("RawValue", hexNumberToInt(Value));
723     });
724   }
725 
726   void printSymbolOffsetImpl(StringRef Label, StringRef Symbol,
727                              HexNumber Value) override {
728     JOS.attributeObject(Label, [&]() {
729       JOS.attribute("SymName", Symbol);
730       JOS.attribute("Offset", hexNumberToInt(Value));
731     });
732   }
733 
734   void printNumberImpl(StringRef Label, StringRef Str,
735                        StringRef Value) override {
736     JOS.attributeObject(Label, [&]() {
737       JOS.attribute("Value", Str);
738       JOS.attributeBegin("RawValue");
739       JOS.rawValueBegin() << Value;
740       JOS.rawValueEnd();
741       JOS.attributeEnd();
742     });
743   }
744 
745   void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
746                        bool Block, uint32_t StartOffset = 0) override {
747     JOS.attributeObject(Label, [&]() {
748       if (!Str.empty())
749         JOS.attribute("Value", Str);
750       JOS.attribute("Offset", StartOffset);
751       JOS.attributeArray("Bytes", [&]() {
752         for (uint8_t Val : Value)
753           JOS.value(Val);
754       });
755     });
756   }
757 
758   void scopedBegin(ScopeContext ScopeCtx) {
759     if (ScopeCtx.Context == Scope::Object)
760       JOS.objectBegin();
761     else if (ScopeCtx.Context == Scope::Array)
762       JOS.arrayBegin();
763     ScopeHistory.push_back(ScopeCtx);
764   }
765 
766   void scopedBegin(StringRef Label, Scope Ctx) {
767     ScopeKind Kind = ScopeKind::Attribute;
768     if (ScopeHistory.empty() || ScopeHistory.back().Context != Scope::Object) {
769       JOS.objectBegin();
770       Kind = ScopeKind::NestedAttribute;
771     }
772     JOS.attributeBegin(Label);
773     scopedBegin({Ctx, Kind});
774   }
775 
776   void scopedEnd() {
777     ScopeContext ScopeCtx = ScopeHistory.back();
778     if (ScopeCtx.Context == Scope::Object)
779       JOS.objectEnd();
780     else if (ScopeCtx.Context == Scope::Array)
781       JOS.arrayEnd();
782     if (ScopeCtx.Kind == ScopeKind::Attribute ||
783         ScopeCtx.Kind == ScopeKind::NestedAttribute)
784       JOS.attributeEnd();
785     if (ScopeCtx.Kind == ScopeKind::NestedAttribute)
786       JOS.objectEnd();
787     ScopeHistory.pop_back();
788   }
789 };
790 
791 struct DelimitedScope {
792   DelimitedScope(ScopedPrinter &W) : W(&W) {}
793   DelimitedScope() : W(nullptr) {}
794   virtual ~DelimitedScope() = default;
795   virtual void setPrinter(ScopedPrinter &W) = 0;
796   ScopedPrinter *W;
797 };
798 
799 struct DictScope : DelimitedScope {
800   explicit DictScope() = default;
801   explicit DictScope(ScopedPrinter &W) : DelimitedScope(W) { W.objectBegin(); }
802 
803   DictScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) {
804     W.objectBegin(N);
805   }
806 
807   void setPrinter(ScopedPrinter &W) override {
808     this->W = &W;
809     W.objectBegin();
810   }
811 
812   ~DictScope() {
813     if (W)
814       W->objectEnd();
815   }
816 };
817 
818 struct ListScope : DelimitedScope {
819   explicit ListScope() = default;
820   explicit ListScope(ScopedPrinter &W) : DelimitedScope(W) { W.arrayBegin(); }
821 
822   ListScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) {
823     W.arrayBegin(N);
824   }
825 
826   void setPrinter(ScopedPrinter &W) override {
827     this->W = &W;
828     W.arrayBegin();
829   }
830 
831   ~ListScope() {
832     if (W)
833       W->arrayEnd();
834   }
835 };
836 
837 } // namespace llvm
838 
839 #endif
840