1 //===-- ScopedPrinter.h ----------------------------------------*- C++ -*--===//
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
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"
23 template <typename T
> struct EnumEntry
{
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.
30 // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
31 // "Advanced Micro Devices X86-64" on GNU style
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
) {}
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
) {}
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
) {
63 llvm::raw_string_ostream
stream(number
);
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
; }
88 for (int i
= 0; i
< IndentLevel
; ++i
)
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
) {
99 for (const auto &EnumItem
: EnumValues
) {
100 if (EnumItem
.Value
== Value
) {
101 Name
= EnumItem
.Name
;
108 startLine() << Label
<< ": " << Name
<< " (" << hex(Value
) << ")\n";
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
;
122 for (const auto &Flag
: Flags
) {
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";
152 uint64_t Curr
= Value
;
155 startLine() << " " << hex(Flag
) << "\n";
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
<< ": [";
211 for (const auto &Item
: List
) {
220 template <typename T
, typename U
>
221 void printList(StringRef Label
, const T
&List
, const U
&Printer
) {
222 startLine() << Label
<< ": [";
224 for (const auto &Item
: List
) {
233 template <typename T
> void printHexList(StringRef Label
, const T
&List
) {
234 startLine() << Label
<< ": [";
236 for (const auto &Item
: List
) {
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()),
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()),
294 printBinaryImpl(Label
, StringRef(), V
, false);
297 void printBinary(StringRef Label
, StringRef Value
) {
298 auto V
= makeArrayRef(reinterpret_cast<const uint8_t *>(Value
.data()),
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()),
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() {
327 raw_ostream
&getOStream() { return OS
; }
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);
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';
367 DelimitedScope(ScopedPrinter
&W
, StringRef N
) : W(W
) {
370 W
.getOStream() << ' ';
371 W
.getOStream() << Open
<< '\n';
377 W
.startLine() << Close
<< '\n';
383 using DictScope
= DelimitedScope
<'{', '}'>;
384 using ListScope
= DelimitedScope
<'[', ']'>;