Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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 printStringEscaped(StringRef Label, StringRef Value) { |
||
348 | printStringEscapedImpl(Label, Value); |
||
349 | } |
||
350 | |||
351 | void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { |
||
352 | printBinaryImpl(Label, Str, Value, false); |
||
353 | } |
||
354 | |||
355 | void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { |
||
356 | auto V = |
||
357 | ArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), Value.size()); |
||
358 | printBinaryImpl(Label, Str, V, false); |
||
359 | } |
||
360 | |||
361 | void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { |
||
362 | printBinaryImpl(Label, StringRef(), Value, false); |
||
363 | } |
||
364 | |||
365 | void printBinary(StringRef Label, ArrayRef<char> Value) { |
||
366 | auto V = |
||
367 | ArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), Value.size()); |
||
368 | printBinaryImpl(Label, StringRef(), V, false); |
||
369 | } |
||
370 | |||
371 | void printBinary(StringRef Label, StringRef Value) { |
||
372 | auto V = |
||
373 | ArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), Value.size()); |
||
374 | printBinaryImpl(Label, StringRef(), V, false); |
||
375 | } |
||
376 | |||
377 | void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value, |
||
378 | uint32_t StartOffset) { |
||
379 | printBinaryImpl(Label, StringRef(), Value, true, StartOffset); |
||
380 | } |
||
381 | |||
382 | void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) { |
||
383 | printBinaryImpl(Label, StringRef(), Value, true); |
||
384 | } |
||
385 | |||
386 | void printBinaryBlock(StringRef Label, StringRef Value) { |
||
387 | auto V = |
||
388 | ArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), Value.size()); |
||
389 | printBinaryImpl(Label, StringRef(), V, true); |
||
390 | } |
||
391 | |||
392 | template <typename T> void printObject(StringRef Label, const T &Value) { |
||
393 | printString(Label, to_string(Value)); |
||
394 | } |
||
395 | |||
396 | virtual void objectBegin() { scopedBegin('{'); } |
||
397 | |||
398 | virtual void objectBegin(StringRef Label) { scopedBegin(Label, '{'); } |
||
399 | |||
400 | virtual void objectEnd() { scopedEnd('}'); } |
||
401 | |||
402 | virtual void arrayBegin() { scopedBegin('['); } |
||
403 | |||
404 | virtual void arrayBegin(StringRef Label) { scopedBegin(Label, '['); } |
||
405 | |||
406 | virtual void arrayEnd() { scopedEnd(']'); } |
||
407 | |||
408 | virtual raw_ostream &startLine() { |
||
409 | printIndent(); |
||
410 | return OS; |
||
411 | } |
||
412 | |||
413 | virtual raw_ostream &getOStream() { return OS; } |
||
414 | |||
415 | private: |
||
416 | template <typename T> void printVersionInternal(T Value) { |
||
417 | getOStream() << Value; |
||
418 | } |
||
419 | |||
420 | template <typename S, typename T, typename... TArgs> |
||
421 | void printVersionInternal(S Value, T Value2, TArgs... Args) { |
||
422 | getOStream() << Value << "."; |
||
423 | printVersionInternal(Value2, Args...); |
||
424 | } |
||
425 | |||
426 | static bool flagName(const FlagEntry &LHS, const FlagEntry &RHS) { |
||
427 | return LHS.Name < RHS.Name; |
||
428 | } |
||
429 | |||
430 | virtual void printBinaryImpl(StringRef Label, StringRef Str, |
||
431 | ArrayRef<uint8_t> Value, bool Block, |
||
432 | uint32_t StartOffset = 0); |
||
433 | |||
434 | virtual void printFlagsImpl(StringRef Label, HexNumber Value, |
||
435 | ArrayRef<FlagEntry> Flags) { |
||
436 | startLine() << Label << " [ (" << Value << ")\n"; |
||
437 | for (const auto &Flag : Flags) |
||
438 | startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; |
||
439 | startLine() << "]\n"; |
||
440 | } |
||
441 | |||
442 | virtual void printFlagsImpl(StringRef Label, HexNumber Value, |
||
443 | ArrayRef<HexNumber> Flags) { |
||
444 | startLine() << Label << " [ (" << Value << ")\n"; |
||
445 | for (const auto &Flag : Flags) |
||
446 | startLine() << " " << Flag << '\n'; |
||
447 | startLine() << "]\n"; |
||
448 | } |
||
449 | |||
450 | template <typename T> void printListImpl(StringRef Label, const T List) { |
||
451 | startLine() << Label << ": ["; |
||
452 | ListSeparator LS; |
||
453 | for (const auto &Item : List) |
||
454 | OS << LS << Item; |
||
455 | OS << "]\n"; |
||
456 | } |
||
457 | |||
458 | virtual void printHexListImpl(StringRef Label, |
||
459 | const ArrayRef<HexNumber> List) { |
||
460 | startLine() << Label << ": ["; |
||
461 | ListSeparator LS; |
||
462 | for (const auto &Item : List) |
||
463 | OS << LS << hex(Item); |
||
464 | OS << "]\n"; |
||
465 | } |
||
466 | |||
467 | virtual void printHexImpl(StringRef Label, HexNumber Value) { |
||
468 | startLine() << Label << ": " << Value << "\n"; |
||
469 | } |
||
470 | |||
471 | virtual void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) { |
||
472 | startLine() << Label << ": " << Str << " (" << Value << ")\n"; |
||
473 | } |
||
474 | |||
475 | virtual void printSymbolOffsetImpl(StringRef Label, StringRef Symbol, |
||
476 | HexNumber Value) { |
||
477 | startLine() << Label << ": " << Symbol << '+' << Value << '\n'; |
||
478 | } |
||
479 | |||
480 | virtual void printNumberImpl(StringRef Label, StringRef Str, |
||
481 | StringRef Value) { |
||
482 | startLine() << Label << ": " << Str << " (" << Value << ")\n"; |
||
483 | } |
||
484 | |||
485 | virtual void printStringEscapedImpl(StringRef Label, StringRef Value) { |
||
486 | startLine() << Label << ": "; |
||
487 | OS.write_escaped(Value); |
||
488 | OS << '\n'; |
||
489 | } |
||
490 | |||
491 | void scopedBegin(char Symbol) { |
||
492 | startLine() << Symbol << '\n'; |
||
493 | indent(); |
||
494 | } |
||
495 | |||
496 | void scopedBegin(StringRef Label, char Symbol) { |
||
497 | startLine() << Label; |
||
498 | if (!Label.empty()) |
||
499 | OS << ' '; |
||
500 | OS << Symbol << '\n'; |
||
501 | indent(); |
||
502 | } |
||
503 | |||
504 | void scopedEnd(char Symbol) { |
||
505 | unindent(); |
||
506 | startLine() << Symbol << '\n'; |
||
507 | } |
||
508 | |||
509 | raw_ostream &OS; |
||
510 | int IndentLevel = 0; |
||
511 | StringRef Prefix; |
||
512 | ScopedPrinterKind Kind; |
||
513 | }; |
||
514 | |||
515 | template <> |
||
516 | inline void |
||
517 | ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label, |
||
518 | support::ulittle16_t Value) { |
||
519 | startLine() << Label << ": " << hex(Value) << "\n"; |
||
520 | } |
||
521 | |||
522 | struct DelimitedScope; |
||
523 | |||
524 | class JSONScopedPrinter : public ScopedPrinter { |
||
525 | private: |
||
526 | enum class Scope { |
||
527 | Array, |
||
528 | Object, |
||
529 | }; |
||
530 | |||
531 | enum class ScopeKind { |
||
532 | NoAttribute, |
||
533 | Attribute, |
||
534 | NestedAttribute, |
||
535 | }; |
||
536 | |||
537 | struct ScopeContext { |
||
538 | Scope Context; |
||
539 | ScopeKind Kind; |
||
540 | ScopeContext(Scope Context, ScopeKind Kind = ScopeKind::NoAttribute) |
||
541 | : Context(Context), Kind(Kind) {} |
||
542 | }; |
||
543 | |||
544 | SmallVector<ScopeContext, 8> ScopeHistory; |
||
545 | json::OStream JOS; |
||
546 | std::unique_ptr<DelimitedScope> OuterScope; |
||
547 | |||
548 | public: |
||
549 | JSONScopedPrinter(raw_ostream &OS, bool PrettyPrint = false, |
||
550 | std::unique_ptr<DelimitedScope> &&OuterScope = |
||
551 | std::unique_ptr<DelimitedScope>{}); |
||
552 | |||
553 | static bool classof(const ScopedPrinter *SP) { |
||
554 | return SP->getKind() == ScopedPrinter::ScopedPrinterKind::JSON; |
||
555 | } |
||
556 | |||
557 | void printNumber(StringRef Label, uint64_t Value) override { |
||
558 | JOS.attribute(Label, Value); |
||
559 | } |
||
560 | |||
561 | void printNumber(StringRef Label, uint32_t Value) override { |
||
562 | JOS.attribute(Label, Value); |
||
563 | } |
||
564 | |||
565 | void printNumber(StringRef Label, uint16_t Value) override { |
||
566 | JOS.attribute(Label, Value); |
||
567 | } |
||
568 | |||
569 | void printNumber(StringRef Label, uint8_t Value) override { |
||
570 | JOS.attribute(Label, Value); |
||
571 | } |
||
572 | |||
573 | void printNumber(StringRef Label, int64_t Value) override { |
||
574 | JOS.attribute(Label, Value); |
||
575 | } |
||
576 | |||
577 | void printNumber(StringRef Label, int32_t Value) override { |
||
578 | JOS.attribute(Label, Value); |
||
579 | } |
||
580 | |||
581 | void printNumber(StringRef Label, int16_t Value) override { |
||
582 | JOS.attribute(Label, Value); |
||
583 | } |
||
584 | |||
585 | void printNumber(StringRef Label, int8_t Value) override { |
||
586 | JOS.attribute(Label, Value); |
||
587 | } |
||
588 | |||
589 | void printNumber(StringRef Label, const APSInt &Value) override { |
||
590 | JOS.attributeBegin(Label); |
||
591 | printAPSInt(Value); |
||
592 | JOS.attributeEnd(); |
||
593 | } |
||
594 | |||
595 | void printBoolean(StringRef Label, bool Value) override { |
||
596 | JOS.attribute(Label, Value); |
||
597 | } |
||
598 | |||
599 | void printList(StringRef Label, const ArrayRef<bool> List) override { |
||
600 | printListImpl(Label, List); |
||
601 | } |
||
602 | |||
603 | void printList(StringRef Label, const ArrayRef<std::string> List) override { |
||
604 | printListImpl(Label, List); |
||
605 | } |
||
606 | |||
607 | void printList(StringRef Label, const ArrayRef<uint64_t> List) override { |
||
608 | printListImpl(Label, List); |
||
609 | } |
||
610 | |||
611 | void printList(StringRef Label, const ArrayRef<uint32_t> List) override { |
||
612 | printListImpl(Label, List); |
||
613 | } |
||
614 | |||
615 | void printList(StringRef Label, const ArrayRef<uint16_t> List) override { |
||
616 | printListImpl(Label, List); |
||
617 | } |
||
618 | |||
619 | void printList(StringRef Label, const ArrayRef<uint8_t> List) override { |
||
620 | printListImpl(Label, List); |
||
621 | } |
||
622 | |||
623 | void printList(StringRef Label, const ArrayRef<int64_t> List) override { |
||
624 | printListImpl(Label, List); |
||
625 | } |
||
626 | |||
627 | void printList(StringRef Label, const ArrayRef<int32_t> List) override { |
||
628 | printListImpl(Label, List); |
||
629 | } |
||
630 | |||
631 | void printList(StringRef Label, const ArrayRef<int16_t> List) override { |
||
632 | printListImpl(Label, List); |
||
633 | } |
||
634 | |||
635 | void printList(StringRef Label, const ArrayRef<int8_t> List) override { |
||
636 | printListImpl(Label, List); |
||
637 | } |
||
638 | |||
639 | void printList(StringRef Label, const ArrayRef<APSInt> List) override { |
||
640 | JOS.attributeArray(Label, [&]() { |
||
641 | for (const APSInt &Item : List) { |
||
642 | printAPSInt(Item); |
||
643 | } |
||
644 | }); |
||
645 | } |
||
646 | |||
647 | void printString(StringRef Value) override { JOS.value(Value); } |
||
648 | |||
649 | void printString(StringRef Label, StringRef Value) override { |
||
650 | JOS.attribute(Label, Value); |
||
651 | } |
||
652 | |||
653 | void objectBegin() override { |
||
654 | scopedBegin({Scope::Object, ScopeKind::NoAttribute}); |
||
655 | } |
||
656 | |||
657 | void objectBegin(StringRef Label) override { |
||
658 | scopedBegin(Label, Scope::Object); |
||
659 | } |
||
660 | |||
661 | void objectEnd() override { scopedEnd(); } |
||
662 | |||
663 | void arrayBegin() override { |
||
664 | scopedBegin({Scope::Array, ScopeKind::NoAttribute}); |
||
665 | } |
||
666 | |||
667 | void arrayBegin(StringRef Label) override { |
||
668 | scopedBegin(Label, Scope::Array); |
||
669 | } |
||
670 | |||
671 | void arrayEnd() override { scopedEnd(); } |
||
672 | |||
673 | private: |
||
674 | // Output HexNumbers as decimals so that they're easier to parse. |
||
675 | uint64_t hexNumberToInt(HexNumber Hex) { return Hex.Value; } |
||
676 | |||
677 | void printAPSInt(const APSInt &Value) { |
||
678 | JOS.rawValueBegin() << Value; |
||
679 | JOS.rawValueEnd(); |
||
680 | } |
||
681 | |||
682 | void printFlagsImpl(StringRef Label, HexNumber Value, |
||
683 | ArrayRef<FlagEntry> Flags) override { |
||
684 | JOS.attributeObject(Label, [&]() { |
||
685 | JOS.attribute("RawFlags", hexNumberToInt(Value)); |
||
686 | JOS.attributeArray("Flags", [&]() { |
||
687 | for (const FlagEntry &Flag : Flags) { |
||
688 | JOS.objectBegin(); |
||
689 | JOS.attribute("Name", Flag.Name); |
||
690 | JOS.attribute("Value", Flag.Value); |
||
691 | JOS.objectEnd(); |
||
692 | } |
||
693 | }); |
||
694 | }); |
||
695 | } |
||
696 | |||
697 | void printFlagsImpl(StringRef Label, HexNumber Value, |
||
698 | ArrayRef<HexNumber> Flags) override { |
||
699 | JOS.attributeObject(Label, [&]() { |
||
700 | JOS.attribute("RawFlags", hexNumberToInt(Value)); |
||
701 | JOS.attributeArray("Flags", [&]() { |
||
702 | for (const HexNumber &Flag : Flags) { |
||
703 | JOS.value(Flag.Value); |
||
704 | } |
||
705 | }); |
||
706 | }); |
||
707 | } |
||
708 | |||
709 | template <typename T> void printListImpl(StringRef Label, const T &List) { |
||
710 | JOS.attributeArray(Label, [&]() { |
||
711 | for (const auto &Item : List) |
||
712 | JOS.value(Item); |
||
713 | }); |
||
714 | } |
||
715 | |||
716 | void printHexListImpl(StringRef Label, |
||
717 | const ArrayRef<HexNumber> List) override { |
||
718 | JOS.attributeArray(Label, [&]() { |
||
719 | for (const HexNumber &Item : List) { |
||
720 | JOS.value(hexNumberToInt(Item)); |
||
721 | } |
||
722 | }); |
||
723 | } |
||
724 | |||
725 | void printHexImpl(StringRef Label, HexNumber Value) override { |
||
726 | JOS.attribute(Label, hexNumberToInt(Value)); |
||
727 | } |
||
728 | |||
729 | void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) override { |
||
730 | JOS.attributeObject(Label, [&]() { |
||
731 | JOS.attribute("Value", Str); |
||
732 | JOS.attribute("RawValue", hexNumberToInt(Value)); |
||
733 | }); |
||
734 | } |
||
735 | |||
736 | void printSymbolOffsetImpl(StringRef Label, StringRef Symbol, |
||
737 | HexNumber Value) override { |
||
738 | JOS.attributeObject(Label, [&]() { |
||
739 | JOS.attribute("SymName", Symbol); |
||
740 | JOS.attribute("Offset", hexNumberToInt(Value)); |
||
741 | }); |
||
742 | } |
||
743 | |||
744 | void printNumberImpl(StringRef Label, StringRef Str, |
||
745 | StringRef Value) override { |
||
746 | JOS.attributeObject(Label, [&]() { |
||
747 | JOS.attribute("Value", Str); |
||
748 | JOS.attributeBegin("RawValue"); |
||
749 | JOS.rawValueBegin() << Value; |
||
750 | JOS.rawValueEnd(); |
||
751 | JOS.attributeEnd(); |
||
752 | }); |
||
753 | } |
||
754 | |||
755 | void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, |
||
756 | bool Block, uint32_t StartOffset = 0) override { |
||
757 | JOS.attributeObject(Label, [&]() { |
||
758 | if (!Str.empty()) |
||
759 | JOS.attribute("Value", Str); |
||
760 | JOS.attribute("Offset", StartOffset); |
||
761 | JOS.attributeArray("Bytes", [&]() { |
||
762 | for (uint8_t Val : Value) |
||
763 | JOS.value(Val); |
||
764 | }); |
||
765 | }); |
||
766 | } |
||
767 | |||
768 | void scopedBegin(ScopeContext ScopeCtx) { |
||
769 | if (ScopeCtx.Context == Scope::Object) |
||
770 | JOS.objectBegin(); |
||
771 | else if (ScopeCtx.Context == Scope::Array) |
||
772 | JOS.arrayBegin(); |
||
773 | ScopeHistory.push_back(ScopeCtx); |
||
774 | } |
||
775 | |||
776 | void scopedBegin(StringRef Label, Scope Ctx) { |
||
777 | ScopeKind Kind = ScopeKind::Attribute; |
||
778 | if (ScopeHistory.empty() || ScopeHistory.back().Context != Scope::Object) { |
||
779 | JOS.objectBegin(); |
||
780 | Kind = ScopeKind::NestedAttribute; |
||
781 | } |
||
782 | JOS.attributeBegin(Label); |
||
783 | scopedBegin({Ctx, Kind}); |
||
784 | } |
||
785 | |||
786 | void scopedEnd() { |
||
787 | ScopeContext ScopeCtx = ScopeHistory.back(); |
||
788 | if (ScopeCtx.Context == Scope::Object) |
||
789 | JOS.objectEnd(); |
||
790 | else if (ScopeCtx.Context == Scope::Array) |
||
791 | JOS.arrayEnd(); |
||
792 | if (ScopeCtx.Kind == ScopeKind::Attribute || |
||
793 | ScopeCtx.Kind == ScopeKind::NestedAttribute) |
||
794 | JOS.attributeEnd(); |
||
795 | if (ScopeCtx.Kind == ScopeKind::NestedAttribute) |
||
796 | JOS.objectEnd(); |
||
797 | ScopeHistory.pop_back(); |
||
798 | } |
||
799 | }; |
||
800 | |||
801 | struct DelimitedScope { |
||
802 | DelimitedScope(ScopedPrinter &W) : W(&W) {} |
||
803 | DelimitedScope() : W(nullptr) {} |
||
804 | virtual ~DelimitedScope() = default; |
||
805 | virtual void setPrinter(ScopedPrinter &W) = 0; |
||
806 | ScopedPrinter *W; |
||
807 | }; |
||
808 | |||
809 | struct DictScope : DelimitedScope { |
||
810 | explicit DictScope() = default; |
||
811 | explicit DictScope(ScopedPrinter &W) : DelimitedScope(W) { W.objectBegin(); } |
||
812 | |||
813 | DictScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) { |
||
814 | W.objectBegin(N); |
||
815 | } |
||
816 | |||
817 | void setPrinter(ScopedPrinter &W) override { |
||
818 | this->W = &W; |
||
819 | W.objectBegin(); |
||
820 | } |
||
821 | |||
822 | ~DictScope() { |
||
823 | if (W) |
||
824 | W->objectEnd(); |
||
825 | } |
||
826 | }; |
||
827 | |||
828 | struct ListScope : DelimitedScope { |
||
829 | explicit ListScope() = default; |
||
830 | explicit ListScope(ScopedPrinter &W) : DelimitedScope(W) { W.arrayBegin(); } |
||
831 | |||
832 | ListScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) { |
||
833 | W.arrayBegin(N); |
||
834 | } |
||
835 | |||
836 | void setPrinter(ScopedPrinter &W) override { |
||
837 | this->W = &W; |
||
838 | W.arrayBegin(); |
||
839 | } |
||
840 | |||
841 | ~ListScope() { |
||
842 | if (W) |
||
843 | W->arrayEnd(); |
||
844 | } |
||
845 | }; |
||
846 | |||
847 | } // namespace llvm |
||
848 | |||
849 | #endif |