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 |