[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / include / llvm / Support / ScopedPrinter.h
blob88daedc8713b913bf1f0c842075982b415e0263c
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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_SUPPORT_SCOPEDPRINTER_H
10 #define LLVM_SUPPORT_SCOPEDPRINTER_H
12 #include "llvm/ADT/APSInt.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/DataTypes.h"
17 #include "llvm/Support/Endian.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include <algorithm>
21 namespace llvm {
23 template <typename T> struct EnumEntry {
24 StringRef Name;
25 // While Name suffices in most of the cases, in certain cases
26 // GNU style and LLVM style of ELFDumper do not
27 // display same string for same enum. The AltName if initialized appropriately
28 // will hold the string that GNU style emits.
29 // Example:
30 // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
31 // "Advanced Micro Devices X86-64" on GNU style
32 StringRef AltName;
33 T Value;
34 EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
35 EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
38 struct HexNumber {
39 // To avoid sign-extension we have to explicitly cast to the appropriate
40 // unsigned type. The overloads are here so that every type that is implicitly
41 // convertible to an integer (including enums and endian helpers) can be used
42 // without requiring type traits or call-site changes.
43 HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {}
44 HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {}
45 HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {}
46 HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {}
47 HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {}
48 HexNumber(signed long long Value)
49 : Value(static_cast<unsigned long long>(Value)) {}
50 HexNumber(unsigned char Value) : Value(Value) {}
51 HexNumber(unsigned short Value) : Value(Value) {}
52 HexNumber(unsigned int Value) : Value(Value) {}
53 HexNumber(unsigned long Value) : Value(Value) {}
54 HexNumber(unsigned long long Value) : Value(Value) {}
55 uint64_t Value;
58 raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value);
59 const std::string to_hexString(uint64_t Value, bool UpperCase = true);
61 template <class T> const std::string to_string(const T &Value) {
62 std::string number;
63 llvm::raw_string_ostream stream(number);
64 stream << Value;
65 return stream.str();
68 class ScopedPrinter {
69 public:
70 ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
72 void flush() { OS.flush(); }
74 void indent(int Levels = 1) { IndentLevel += Levels; }
76 void unindent(int Levels = 1) {
77 IndentLevel = std::max(0, IndentLevel - Levels);
80 void resetIndent() { IndentLevel = 0; }
82 int getIndentLevel() { return IndentLevel; }
84 void setPrefix(StringRef P) { Prefix = P; }
86 void printIndent() {
87 OS << Prefix;
88 for (int i = 0; i < IndentLevel; ++i)
89 OS << " ";
92 template <typename T> HexNumber hex(T Value) { return HexNumber(Value); }
94 template <typename T, typename TEnum>
95 void printEnum(StringRef Label, T Value,
96 ArrayRef<EnumEntry<TEnum>> EnumValues) {
97 StringRef Name;
98 bool Found = false;
99 for (const auto &EnumItem : EnumValues) {
100 if (EnumItem.Value == Value) {
101 Name = EnumItem.Name;
102 Found = true;
103 break;
107 if (Found) {
108 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
109 } else {
110 startLine() << Label << ": " << hex(Value) << "\n";
114 template <typename T, typename TFlag>
115 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
116 TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
117 TFlag EnumMask3 = {}) {
118 typedef EnumEntry<TFlag> FlagEntry;
119 typedef SmallVector<FlagEntry, 10> FlagVector;
120 FlagVector SetFlags;
122 for (const auto &Flag : Flags) {
123 if (Flag.Value == 0)
124 continue;
126 TFlag EnumMask{};
127 if (Flag.Value & EnumMask1)
128 EnumMask = EnumMask1;
129 else if (Flag.Value & EnumMask2)
130 EnumMask = EnumMask2;
131 else if (Flag.Value & EnumMask3)
132 EnumMask = EnumMask3;
133 bool IsEnum = (Flag.Value & EnumMask) != 0;
134 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
135 (IsEnum && (Value & EnumMask) == Flag.Value)) {
136 SetFlags.push_back(Flag);
140 llvm::sort(SetFlags, &flagName<TFlag>);
142 startLine() << Label << " [ (" << hex(Value) << ")\n";
143 for (const auto &Flag : SetFlags) {
144 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
146 startLine() << "]\n";
149 template <typename T> void printFlags(StringRef Label, T Value) {
150 startLine() << Label << " [ (" << hex(Value) << ")\n";
151 uint64_t Flag = 1;
152 uint64_t Curr = Value;
153 while (Curr > 0) {
154 if (Curr & 1)
155 startLine() << " " << hex(Flag) << "\n";
156 Curr >>= 1;
157 Flag <<= 1;
159 startLine() << "]\n";
162 void printNumber(StringRef Label, uint64_t Value) {
163 startLine() << Label << ": " << Value << "\n";
166 void printNumber(StringRef Label, uint32_t Value) {
167 startLine() << Label << ": " << Value << "\n";
170 void printNumber(StringRef Label, uint16_t Value) {
171 startLine() << Label << ": " << Value << "\n";
174 void printNumber(StringRef Label, uint8_t Value) {
175 startLine() << Label << ": " << unsigned(Value) << "\n";
178 void printNumber(StringRef Label, int64_t Value) {
179 startLine() << Label << ": " << Value << "\n";
182 void printNumber(StringRef Label, int32_t Value) {
183 startLine() << Label << ": " << Value << "\n";
186 void printNumber(StringRef Label, int16_t Value) {
187 startLine() << Label << ": " << Value << "\n";
190 void printNumber(StringRef Label, int8_t Value) {
191 startLine() << Label << ": " << int(Value) << "\n";
194 void printNumber(StringRef Label, const APSInt &Value) {
195 startLine() << Label << ": " << Value << "\n";
198 void printBoolean(StringRef Label, bool Value) {
199 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
202 template <typename... T> void printVersion(StringRef Label, T... Version) {
203 startLine() << Label << ": ";
204 printVersionInternal(Version...);
205 getOStream() << "\n";
208 template <typename T> void printList(StringRef Label, const T &List) {
209 startLine() << Label << ": [";
210 bool Comma = false;
211 for (const auto &Item : List) {
212 if (Comma)
213 OS << ", ";
214 OS << Item;
215 Comma = true;
217 OS << "]\n";
220 template <typename T, typename U>
221 void printList(StringRef Label, const T &List, const U &Printer) {
222 startLine() << Label << ": [";
223 bool Comma = false;
224 for (const auto &Item : List) {
225 if (Comma)
226 OS << ", ";
227 Printer(OS, Item);
228 Comma = true;
230 OS << "]\n";
233 template <typename T> void printHexList(StringRef Label, const T &List) {
234 startLine() << Label << ": [";
235 bool Comma = false;
236 for (const auto &Item : List) {
237 if (Comma)
238 OS << ", ";
239 OS << hex(Item);
240 Comma = true;
242 OS << "]\n";
245 template <typename T> void printHex(StringRef Label, T Value) {
246 startLine() << Label << ": " << hex(Value) << "\n";
249 template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
250 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
253 template <typename T>
254 void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
255 startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
258 void printString(StringRef Value) { startLine() << Value << "\n"; }
260 void printString(StringRef Label, StringRef Value) {
261 startLine() << Label << ": " << Value << "\n";
264 void printString(StringRef Label, const std::string &Value) {
265 printString(Label, StringRef(Value));
268 void printString(StringRef Label, const char* Value) {
269 printString(Label, StringRef(Value));
272 template <typename T>
273 void printNumber(StringRef Label, StringRef Str, T Value) {
274 startLine() << Label << ": " << Str << " (" << Value << ")\n";
277 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
278 printBinaryImpl(Label, Str, Value, false);
281 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
282 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
283 Value.size());
284 printBinaryImpl(Label, Str, V, false);
287 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
288 printBinaryImpl(Label, StringRef(), Value, false);
291 void printBinary(StringRef Label, ArrayRef<char> Value) {
292 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
293 Value.size());
294 printBinaryImpl(Label, StringRef(), V, false);
297 void printBinary(StringRef Label, StringRef Value) {
298 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
299 Value.size());
300 printBinaryImpl(Label, StringRef(), V, false);
303 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value,
304 uint32_t StartOffset) {
305 printBinaryImpl(Label, StringRef(), Value, true, StartOffset);
308 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
309 printBinaryImpl(Label, StringRef(), Value, true);
312 void printBinaryBlock(StringRef Label, StringRef Value) {
313 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
314 Value.size());
315 printBinaryImpl(Label, StringRef(), V, true);
318 template <typename T> void printObject(StringRef Label, const T &Value) {
319 startLine() << Label << ": " << Value << "\n";
322 raw_ostream &startLine() {
323 printIndent();
324 return OS;
327 raw_ostream &getOStream() { return OS; }
329 private:
330 template <typename T> void printVersionInternal(T Value) {
331 getOStream() << Value;
334 template <typename S, typename T, typename... TArgs>
335 void printVersionInternal(S Value, T Value2, TArgs... Args) {
336 getOStream() << Value << ".";
337 printVersionInternal(Value2, Args...);
340 template <typename T>
341 static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
342 return lhs.Name < rhs.Name;
345 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
346 bool Block, uint32_t StartOffset = 0);
348 raw_ostream &OS;
349 int IndentLevel;
350 StringRef Prefix;
353 template <>
354 inline void
355 ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
356 support::ulittle16_t Value) {
357 startLine() << Label << ": " << hex(Value) << "\n";
360 template<char Open, char Close>
361 struct DelimitedScope {
362 explicit DelimitedScope(ScopedPrinter &W) : W(W) {
363 W.startLine() << Open << '\n';
364 W.indent();
367 DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
368 W.startLine() << N;
369 if (!N.empty())
370 W.getOStream() << ' ';
371 W.getOStream() << Open << '\n';
372 W.indent();
375 ~DelimitedScope() {
376 W.unindent();
377 W.startLine() << Close << '\n';
380 ScopedPrinter &W;
383 using DictScope = DelimitedScope<'{', '}'>;
384 using ListScope = DelimitedScope<'[', ']'>;
386 } // namespace llvm
388 #endif