120
|
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) {
|
134
|
264 printString(Label, StringRef(Value));
|
|
265 }
|
|
266
|
|
267 void printString(StringRef Label, const char* Value) {
|
|
268 printString(Label, StringRef(Value));
|
120
|
269 }
|
|
270
|
|
271 template <typename T>
|
|
272 void printNumber(StringRef Label, StringRef Str, T Value) {
|
|
273 startLine() << Label << ": " << Str << " (" << Value << ")\n";
|
|
274 }
|
|
275
|
|
276 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
|
|
277 printBinaryImpl(Label, Str, Value, false);
|
|
278 }
|
|
279
|
|
280 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
|
|
281 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
282 Value.size());
|
|
283 printBinaryImpl(Label, Str, V, false);
|
|
284 }
|
|
285
|
|
286 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
|
|
287 printBinaryImpl(Label, StringRef(), Value, false);
|
|
288 }
|
|
289
|
|
290 void printBinary(StringRef Label, ArrayRef<char> Value) {
|
|
291 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
292 Value.size());
|
|
293 printBinaryImpl(Label, StringRef(), V, false);
|
|
294 }
|
|
295
|
|
296 void printBinary(StringRef Label, StringRef Value) {
|
|
297 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
298 Value.size());
|
|
299 printBinaryImpl(Label, StringRef(), V, false);
|
|
300 }
|
|
301
|
121
|
302 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value,
|
|
303 uint32_t StartOffset) {
|
|
304 printBinaryImpl(Label, StringRef(), Value, true, StartOffset);
|
|
305 }
|
|
306
|
120
|
307 void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
|
|
308 printBinaryImpl(Label, StringRef(), Value, true);
|
|
309 }
|
|
310
|
|
311 void printBinaryBlock(StringRef Label, StringRef Value) {
|
|
312 auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
313 Value.size());
|
|
314 printBinaryImpl(Label, StringRef(), V, true);
|
|
315 }
|
|
316
|
|
317 template <typename T> void printObject(StringRef Label, const T &Value) {
|
|
318 startLine() << Label << ": " << Value << "\n";
|
|
319 }
|
|
320
|
|
321 raw_ostream &startLine() {
|
|
322 printIndent();
|
|
323 return OS;
|
|
324 }
|
|
325
|
|
326 raw_ostream &getOStream() { return OS; }
|
|
327
|
|
328 private:
|
|
329 template <typename T> void printVersionInternal(T Value) {
|
|
330 getOStream() << Value;
|
|
331 }
|
|
332
|
|
333 template <typename S, typename T, typename... TArgs>
|
|
334 void printVersionInternal(S Value, T Value2, TArgs... Args) {
|
|
335 getOStream() << Value << ".";
|
|
336 printVersionInternal(Value2, Args...);
|
|
337 }
|
|
338
|
|
339 template <typename T>
|
|
340 static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
|
|
341 return lhs.Name < rhs.Name;
|
|
342 }
|
|
343
|
|
344 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
|
121
|
345 bool Block, uint32_t StartOffset = 0);
|
120
|
346
|
|
347 raw_ostream &OS;
|
|
348 int IndentLevel;
|
|
349 StringRef Prefix;
|
|
350 };
|
|
351
|
|
352 template <>
|
|
353 inline void
|
|
354 ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
|
|
355 support::ulittle16_t Value) {
|
|
356 startLine() << Label << ": " << hex(Value) << "\n";
|
|
357 }
|
|
358
|
|
359 template<char Open, char Close>
|
|
360 struct DelimitedScope {
|
|
361 explicit DelimitedScope(ScopedPrinter &W) : W(W) {
|
|
362 W.startLine() << Open << '\n';
|
|
363 W.indent();
|
|
364 }
|
|
365
|
|
366 DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
|
|
367 W.startLine() << N;
|
|
368 if (!N.empty())
|
|
369 W.getOStream() << ' ';
|
|
370 W.getOStream() << Open << '\n';
|
|
371 W.indent();
|
|
372 }
|
|
373
|
|
374 ~DelimitedScope() {
|
|
375 W.unindent();
|
|
376 W.startLine() << Close << '\n';
|
|
377 }
|
|
378
|
|
379 ScopedPrinter &W;
|
|
380 };
|
|
381
|
|
382 using DictScope = DelimitedScope<'{', '}'>;
|
|
383 using ListScope = DelimitedScope<'[', ']'>;
|
|
384
|
|
385 } // namespace llvm
|
|
386
|
|
387 #endif
|