1 //===-- ScopedPrinter.h ---------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_SUPPORT_SCOPEDPRINTER_H 11 #define LLVM_SUPPORT_SCOPEDPRINTER_H 12 13 #include "llvm/ADT/APSInt.h" 14 #include "llvm/ADT/ArrayRef.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/DataTypes.h" 18 #include "llvm/Support/Endian.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include <algorithm> 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 EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {} 36 EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {} 37 }; 38 39 struct HexNumber { 40 // To avoid sign-extension we have to explicitly cast to the appropriate 41 // unsigned type. The overloads are here so that every type that is implicitly 42 // convertible to an integer (including enums and endian helpers) can be used 43 // without requiring type traits or call-site changes. 44 HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {} 45 HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {} 46 HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {} 47 HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {} 48 HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {} 49 HexNumber(signed long long Value) 50 : Value(static_cast<unsigned long long>(Value)) {} 51 HexNumber(unsigned char Value) : Value(Value) {} 52 HexNumber(unsigned short Value) : Value(Value) {} 53 HexNumber(unsigned int Value) : Value(Value) {} 54 HexNumber(unsigned long Value) : Value(Value) {} 55 HexNumber(unsigned long long Value) : Value(Value) {} 56 uint64_t Value; 57 }; 58 59 raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value); 60 const std::string to_hexString(uint64_t Value, bool UpperCase = true); 61 62 template <class T> const std::string to_string(const T &Value) { 63 std::string number; 64 llvm::raw_string_ostream stream(number); 65 stream << Value; 66 return stream.str(); 67 } 68 69 class ScopedPrinter { 70 public: 71 ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {} 72 73 void flush() { OS.flush(); } 74 75 void indent(int Levels = 1) { IndentLevel += Levels; } 76 77 void unindent(int Levels = 1) { 78 IndentLevel = std::max(0, IndentLevel - Levels); 79 } 80 81 void resetIndent() { IndentLevel = 0; } 82 83 void setPrefix(StringRef P) { Prefix = P; } 84 85 void printIndent() { 86 OS << Prefix; 87 for (int i = 0; i < IndentLevel; ++i) 88 OS << " "; 89 } 90 91 template <typename T> HexNumber hex(T Value) { return HexNumber(Value); } 92 93 template <typename T, typename TEnum> 94 void printEnum(StringRef Label, T Value, 95 ArrayRef<EnumEntry<TEnum>> EnumValues) { 96 StringRef Name; 97 bool Found = false; 98 for (const auto &EnumItem : EnumValues) { 99 if (EnumItem.Value == Value) { 100 Name = EnumItem.Name; 101 Found = true; 102 break; 103 } 104 } 105 106 if (Found) { 107 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n"; 108 } else { 109 startLine() << Label << ": " << hex(Value) << "\n"; 110 } 111 } 112 113 template <typename T, typename TFlag> 114 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags, 115 TFlag EnumMask1 = {}, TFlag EnumMask2 = {}, 116 TFlag EnumMask3 = {}) { 117 typedef EnumEntry<TFlag> FlagEntry; 118 typedef SmallVector<FlagEntry, 10> FlagVector; 119 FlagVector SetFlags; 120 121 for (const auto &Flag : Flags) { 122 if (Flag.Value == 0) 123 continue; 124 125 TFlag EnumMask{}; 126 if (Flag.Value & EnumMask1) 127 EnumMask = EnumMask1; 128 else if (Flag.Value & EnumMask2) 129 EnumMask = EnumMask2; 130 else if (Flag.Value & EnumMask3) 131 EnumMask = EnumMask3; 132 bool IsEnum = (Flag.Value & EnumMask) != 0; 133 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 134 (IsEnum && (Value & EnumMask) == Flag.Value)) { 135 SetFlags.push_back(Flag); 136 } 137 } 138 139 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); 140 141 startLine() << Label << " [ (" << hex(Value) << ")\n"; 142 for (const auto &Flag : SetFlags) { 143 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; 144 } 145 startLine() << "]\n"; 146 } 147 148 template <typename T> void printFlags(StringRef Label, T Value) { 149 startLine() << Label << " [ (" << hex(Value) << ")\n"; 150 uint64_t Flag = 1; 151 uint64_t Curr = Value; 152 while (Curr > 0) { 153 if (Curr & 1) 154 startLine() << " " << hex(Flag) << "\n"; 155 Curr >>= 1; 156 Flag <<= 1; 157 } 158 startLine() << "]\n"; 159 } 160 161 void printNumber(StringRef Label, uint64_t Value) { 162 startLine() << Label << ": " << Value << "\n"; 163 } 164 165 void printNumber(StringRef Label, uint32_t Value) { 166 startLine() << Label << ": " << Value << "\n"; 167 } 168 169 void printNumber(StringRef Label, uint16_t Value) { 170 startLine() << Label << ": " << Value << "\n"; 171 } 172 173 void printNumber(StringRef Label, uint8_t Value) { 174 startLine() << Label << ": " << unsigned(Value) << "\n"; 175 } 176 177 void printNumber(StringRef Label, int64_t Value) { 178 startLine() << Label << ": " << Value << "\n"; 179 } 180 181 void printNumber(StringRef Label, int32_t Value) { 182 startLine() << Label << ": " << Value << "\n"; 183 } 184 185 void printNumber(StringRef Label, int16_t Value) { 186 startLine() << Label << ": " << Value << "\n"; 187 } 188 189 void printNumber(StringRef Label, int8_t Value) { 190 startLine() << Label << ": " << int(Value) << "\n"; 191 } 192 193 void printNumber(StringRef Label, const APSInt &Value) { 194 startLine() << Label << ": " << Value << "\n"; 195 } 196 197 void printBoolean(StringRef Label, bool Value) { 198 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; 199 } 200 201 template <typename... T> void printVersion(StringRef Label, T... Version) { 202 startLine() << Label << ": "; 203 printVersionInternal(Version...); 204 getOStream() << "\n"; 205 } 206 207 template <typename T> void printList(StringRef Label, const T &List) { 208 startLine() << Label << ": ["; 209 bool Comma = false; 210 for (const auto &Item : List) { 211 if (Comma) 212 OS << ", "; 213 OS << Item; 214 Comma = true; 215 } 216 OS << "]\n"; 217 } 218 219 template <typename T, typename U> 220 void printList(StringRef Label, const T &List, const U &Printer) { 221 startLine() << Label << ": ["; 222 bool Comma = false; 223 for (const auto &Item : List) { 224 if (Comma) 225 OS << ", "; 226 Printer(OS, Item); 227 Comma = true; 228 } 229 OS << "]\n"; 230 } 231 232 template <typename T> void printHexList(StringRef Label, const T &List) { 233 startLine() << Label << ": ["; 234 bool Comma = false; 235 for (const auto &Item : List) { 236 if (Comma) 237 OS << ", "; 238 OS << hex(Item); 239 Comma = true; 240 } 241 OS << "]\n"; 242 } 243 244 template <typename T> void printHex(StringRef Label, T Value) { 245 startLine() << Label << ": " << hex(Value) << "\n"; 246 } 247 248 template <typename T> void printHex(StringRef Label, StringRef Str, T Value) { 249 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 250 } 251 252 template <typename T> 253 void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) { 254 startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n'; 255 } 256 257 void printString(StringRef Value) { startLine() << Value << "\n"; } 258 259 void printString(StringRef Label, StringRef Value) { 260 startLine() << Label << ": " << Value << "\n"; 261 } 262 263 void printString(StringRef Label, const std::string &Value) { 264 startLine() << Label << ": " << Value << "\n"; 265 } 266 267 template <typename T> 268 void printNumber(StringRef Label, StringRef Str, T Value) { 269 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 270 } 271 272 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 273 printBinaryImpl(Label, Str, Value, false); 274 } 275 276 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 277 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 278 Value.size()); 279 printBinaryImpl(Label, Str, V, false); 280 } 281 282 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 283 printBinaryImpl(Label, StringRef(), Value, false); 284 } 285 286 void printBinary(StringRef Label, ArrayRef<char> Value) { 287 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 288 Value.size()); 289 printBinaryImpl(Label, StringRef(), V, false); 290 } 291 292 void printBinary(StringRef Label, StringRef Value) { 293 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 294 Value.size()); 295 printBinaryImpl(Label, StringRef(), V, false); 296 } 297 298 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) { 299 printBinaryImpl(Label, StringRef(), Value, true); 300 } 301 302 void printBinaryBlock(StringRef Label, StringRef Value) { 303 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), 304 Value.size()); 305 printBinaryImpl(Label, StringRef(), V, true); 306 } 307 308 template <typename T> void printObject(StringRef Label, const T &Value) { 309 startLine() << Label << ": " << Value << "\n"; 310 } 311 312 raw_ostream &startLine() { 313 printIndent(); 314 return OS; 315 } 316 317 raw_ostream &getOStream() { return OS; } 318 319 private: 320 template <typename T> void printVersionInternal(T Value) { 321 getOStream() << Value; 322 } 323 324 template <typename S, typename T, typename... TArgs> 325 void printVersionInternal(S Value, T Value2, TArgs... Args) { 326 getOStream() << Value << "."; 327 printVersionInternal(Value2, Args...); 328 } 329 330 template <typename T> 331 static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) { 332 return lhs.Name < rhs.Name; 333 } 334 335 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 336 bool Block); 337 338 raw_ostream &OS; 339 int IndentLevel; 340 StringRef Prefix; 341 }; 342 343 template <> 344 inline void 345 ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label, 346 support::ulittle16_t Value) { 347 startLine() << Label << ": " << hex(Value) << "\n"; 348 } 349 350 template<char Open, char Close> 351 struct DelimitedScope { 352 explicit DelimitedScope(ScopedPrinter &W) : W(W) { 353 W.startLine() << Open << '\n'; 354 W.indent(); 355 } 356 357 DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) { 358 W.startLine() << N; 359 if (!N.empty()) 360 W.getOStream() << ' '; 361 W.getOStream() << Open << '\n'; 362 W.indent(); 363 } 364 365 ~DelimitedScope() { 366 W.unindent(); 367 W.startLine() << Close << '\n'; 368 } 369 370 ScopedPrinter &W; 371 }; 372 373 using DictScope = DelimitedScope<'{', '}'>; 374 using ListScope = DelimitedScope<'[', ']'>; 375 376 } // namespace llvm 377 378 #endif 379