ScopedPrinter.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. #ifndef LLVM_SUPPORT_SCOPEDPRINTER_H
  9. #define LLVM_SUPPORT_SCOPEDPRINTER_H
  10. #include "llvm/ADT/APSInt.h"
  11. #include "llvm/ADT/ArrayRef.h"
  12. #include "llvm/ADT/SmallVector.h"
  13. #include "llvm/ADT/StringExtras.h"
  14. #include "llvm/ADT/StringRef.h"
  15. #include "llvm/Support/DataTypes.h"
  16. #include "llvm/Support/Endian.h"
  17. #include "llvm/Support/raw_ostream.h"
  18. #include <algorithm>
  19. namespace llvm {
  20. template <typename T> struct EnumEntry {
  21. StringRef Name;
  22. // While Name suffices in most of the cases, in certain cases
  23. // GNU style and LLVM style of ELFDumper do not
  24. // display same string for same enum. The AltName if initialized appropriately
  25. // will hold the string that GNU style emits.
  26. // Example:
  27. // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
  28. // "Advanced Micro Devices X86-64" on GNU style
  29. StringRef AltName;
  30. T Value;
  31. EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
  32. EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
  33. };
  34. struct HexNumber {
  35. // To avoid sign-extension we have to explicitly cast to the appropriate
  36. // unsigned type. The overloads are here so that every type that is implicitly
  37. // convertible to an integer (including enums and endian helpers) can be used
  38. // without requiring type traits or call-site changes.
  39. HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {}
  40. HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {}
  41. HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {}
  42. HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {}
  43. HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {}
  44. HexNumber(signed long long Value)
  45. : Value(static_cast<unsigned long long>(Value)) {}
  46. HexNumber(unsigned char Value) : Value(Value) {}
  47. HexNumber(unsigned short Value) : Value(Value) {}
  48. HexNumber(unsigned int Value) : Value(Value) {}
  49. HexNumber(unsigned long Value) : Value(Value) {}
  50. HexNumber(unsigned long long Value) : Value(Value) {}
  51. uint64_t Value;
  52. };
  53. raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value);
  54. std::string to_hexString(uint64_t Value, bool UpperCase = true);
  55. template <class T> std::string to_string(const T &Value) {
  56. std::string number;
  57. llvm::raw_string_ostream stream(number);
  58. stream << Value;
  59. return stream.str();
  60. }
  61. class ScopedPrinter {
  62. public:
  63. ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
  64. void flush() { OS.flush(); }
  65. void indent(int Levels = 1) { IndentLevel += Levels; }
  66. void unindent(int Levels = 1) {
  67. IndentLevel = std::max(0, IndentLevel - Levels);
  68. }
  69. void resetIndent() { IndentLevel = 0; }
  70. int getIndentLevel() { return IndentLevel; }
  71. void setPrefix(StringRef P) { Prefix = P; }
  72. void printIndent() {
  73. OS << Prefix;
  74. for (int i = 0; i < IndentLevel; ++i)
  75. OS << " ";
  76. }
  77. template <typename T> HexNumber hex(T Value) { return HexNumber(Value); }
  78. template <typename T, typename TEnum>
  79. void printEnum(StringRef Label, T Value,
  80. ArrayRef<EnumEntry<TEnum>> EnumValues) {
  81. StringRef Name;
  82. bool Found = false;
  83. for (const auto &EnumItem : EnumValues) {
  84. if (EnumItem.Value == Value) {
  85. Name = EnumItem.Name;
  86. Found = true;
  87. break;
  88. }
  89. }
  90. if (Found) {
  91. startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
  92. } else {
  93. startLine() << Label << ": " << hex(Value) << "\n";
  94. }
  95. }
  96. template <typename T, typename TFlag>
  97. void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
  98. TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
  99. TFlag EnumMask3 = {}) {
  100. typedef EnumEntry<TFlag> FlagEntry;
  101. typedef SmallVector<FlagEntry, 10> FlagVector;
  102. FlagVector SetFlags;
  103. for (const auto &Flag : Flags) {
  104. if (Flag.Value == 0)
  105. continue;
  106. TFlag EnumMask{};
  107. if (Flag.Value & EnumMask1)
  108. EnumMask = EnumMask1;
  109. else if (Flag.Value & EnumMask2)
  110. EnumMask = EnumMask2;
  111. else if (Flag.Value & EnumMask3)
  112. EnumMask = EnumMask3;
  113. bool IsEnum = (Flag.Value & EnumMask) != 0;
  114. if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
  115. (IsEnum && (Value & EnumMask) == Flag.Value)) {
  116. SetFlags.push_back(Flag);
  117. }
  118. }
  119. llvm::sort(SetFlags, &flagName<TFlag>);
  120. startLine() << Label << " [ (" << hex(Value) << ")\n";
  121. for (const auto &Flag : SetFlags) {
  122. startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
  123. }
  124. startLine() << "]\n";
  125. }
  126. template <typename T> void printFlags(StringRef Label, T Value) {
  127. startLine() << Label << " [ (" << hex(Value) << ")\n";
  128. uint64_t Flag = 1;
  129. uint64_t Curr = Value;
  130. while (Curr > 0) {
  131. if (Curr & 1)
  132. startLine() << " " << hex(Flag) << "\n";
  133. Curr >>= 1;
  134. Flag <<= 1;
  135. }
  136. startLine() << "]\n";
  137. }
  138. void printNumber(StringRef Label, uint64_t Value) {
  139. startLine() << Label << ": " << Value << "\n";
  140. }
  141. void printNumber(StringRef Label, uint32_t Value) {
  142. startLine() << Label << ": " << Value << "\n";
  143. }
  144. void printNumber(StringRef Label, uint16_t Value) {
  145. startLine() << Label << ": " << Value << "\n";
  146. }
  147. void printNumber(StringRef Label, uint8_t Value) {
  148. startLine() << Label << ": " << unsigned(Value) << "\n";
  149. }
  150. void printNumber(StringRef Label, int64_t Value) {
  151. startLine() << Label << ": " << Value << "\n";
  152. }
  153. void printNumber(StringRef Label, int32_t Value) {
  154. startLine() << Label << ": " << Value << "\n";
  155. }
  156. void printNumber(StringRef Label, int16_t Value) {
  157. startLine() << Label << ": " << Value << "\n";
  158. }
  159. void printNumber(StringRef Label, int8_t Value) {
  160. startLine() << Label << ": " << int(Value) << "\n";
  161. }
  162. void printNumber(StringRef Label, const APSInt &Value) {
  163. startLine() << Label << ": " << Value << "\n";
  164. }
  165. void printBoolean(StringRef Label, bool Value) {
  166. startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
  167. }
  168. template <typename... T> void printVersion(StringRef Label, T... Version) {
  169. startLine() << Label << ": ";
  170. printVersionInternal(Version...);
  171. getOStream() << "\n";
  172. }
  173. template <typename T> void printList(StringRef Label, const T &List) {
  174. startLine() << Label << ": [";
  175. ListSeparator LS;
  176. for (const auto &Item : List)
  177. OS << LS << Item;
  178. OS << "]\n";
  179. }
  180. template <typename T, typename U>
  181. void printList(StringRef Label, const T &List, const U &Printer) {
  182. startLine() << Label << ": [";
  183. ListSeparator LS;
  184. for (const auto &Item : List) {
  185. OS << LS;
  186. Printer(OS, Item);
  187. }
  188. OS << "]\n";
  189. }
  190. template <typename T> void printHexList(StringRef Label, const T &List) {
  191. startLine() << Label << ": [";
  192. ListSeparator LS;
  193. for (const auto &Item : List)
  194. OS << LS << hex(Item);
  195. OS << "]\n";
  196. }
  197. template <typename T> void printHex(StringRef Label, T Value) {
  198. startLine() << Label << ": " << hex(Value) << "\n";
  199. }
  200. template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
  201. startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
  202. }
  203. template <typename T>
  204. void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
  205. startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
  206. }
  207. void printString(StringRef Value) { startLine() << Value << "\n"; }
  208. void printString(StringRef Label, StringRef Value) {
  209. startLine() << Label << ": " << Value << "\n";
  210. }
  211. void printString(StringRef Label, const std::string &Value) {
  212. printString(Label, StringRef(Value));
  213. }
  214. void printString(StringRef Label, const char* Value) {
  215. printString(Label, StringRef(Value));
  216. }
  217. template <typename T>
  218. void printNumber(StringRef Label, StringRef Str, T Value) {
  219. startLine() << Label << ": " << Str << " (" << Value << ")\n";
  220. }
  221. void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
  222. printBinaryImpl(Label, Str, Value, false);
  223. }
  224. void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
  225. auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
  226. Value.size());
  227. printBinaryImpl(Label, Str, V, false);
  228. }
  229. void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
  230. printBinaryImpl(Label, StringRef(), Value, false);
  231. }
  232. void printBinary(StringRef Label, ArrayRef<char> Value) {
  233. auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
  234. Value.size());
  235. printBinaryImpl(Label, StringRef(), V, false);
  236. }
  237. void printBinary(StringRef Label, StringRef Value) {
  238. auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
  239. Value.size());
  240. printBinaryImpl(Label, StringRef(), V, false);
  241. }
  242. void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value,
  243. uint32_t StartOffset) {
  244. printBinaryImpl(Label, StringRef(), Value, true, StartOffset);
  245. }
  246. void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
  247. printBinaryImpl(Label, StringRef(), Value, true);
  248. }
  249. void printBinaryBlock(StringRef Label, StringRef Value) {
  250. auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
  251. Value.size());
  252. printBinaryImpl(Label, StringRef(), V, true);
  253. }
  254. template <typename T> void printObject(StringRef Label, const T &Value) {
  255. startLine() << Label << ": " << Value << "\n";
  256. }
  257. raw_ostream &startLine() {
  258. printIndent();
  259. return OS;
  260. }
  261. raw_ostream &getOStream() { return OS; }
  262. private:
  263. template <typename T> void printVersionInternal(T Value) {
  264. getOStream() << Value;
  265. }
  266. template <typename S, typename T, typename... TArgs>
  267. void printVersionInternal(S Value, T Value2, TArgs... Args) {
  268. getOStream() << Value << ".";
  269. printVersionInternal(Value2, Args...);
  270. }
  271. template <typename T>
  272. static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
  273. return lhs.Name < rhs.Name;
  274. }
  275. void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
  276. bool Block, uint32_t StartOffset = 0);
  277. raw_ostream &OS;
  278. int IndentLevel;
  279. StringRef Prefix;
  280. };
  281. template <>
  282. inline void
  283. ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
  284. support::ulittle16_t Value) {
  285. startLine() << Label << ": " << hex(Value) << "\n";
  286. }
  287. template<char Open, char Close>
  288. struct DelimitedScope {
  289. explicit DelimitedScope(ScopedPrinter &W) : W(W) {
  290. W.startLine() << Open << '\n';
  291. W.indent();
  292. }
  293. DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
  294. W.startLine() << N;
  295. if (!N.empty())
  296. W.getOStream() << ' ';
  297. W.getOStream() << Open << '\n';
  298. W.indent();
  299. }
  300. ~DelimitedScope() {
  301. W.unindent();
  302. W.startLine() << Close << '\n';
  303. }
  304. ScopedPrinter &W;
  305. };
  306. using DictScope = DelimitedScope<'{', '}'>;
  307. using ListScope = DelimitedScope<'[', ']'>;
  308. } // namespace llvm
  309. #endif