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