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