blob: 9b0e5a6d39858c29a438a4c3b80b927f0ae8c7a7 [file] [log] [blame]
Eric Christopher9cad53c2013-04-03 18:31:38 +00001//===-- StreamWriter.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
Benjamin Kramera7c40ef2014-08-13 16:26:38 +000010#ifndef LLVM_TOOLS_LLVM_READOBJ_STREAMWRITER_H
11#define LLVM_TOOLS_LLVM_READOBJ_STREAMWRITER_H
Eric Christopher9cad53c2013-04-03 18:31:38 +000012
Reid Kleckner72e2ba72016-01-13 19:32:35 +000013#include "llvm/ADT/APSInt.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000014#include "llvm/ADT/ArrayRef.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000015#include "llvm/ADT/SmallVector.h"
Chandler Carruth07baed52014-01-13 08:04:33 +000016#include "llvm/ADT/StringRef.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000017#include "llvm/Support/DataTypes.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/raw_ostream.h"
20#include <algorithm>
21
22using namespace llvm;
Eric Christopher9cad53c2013-04-03 18:31:38 +000023
24namespace llvm {
25
26template<typename T>
27struct EnumEntry {
28 StringRef Name;
Hemant Kulkarnid8a985e2016-02-10 20:40:55 +000029 // While Name suffices in most of the cases, in certain cases
30 // GNU style and LLVM style of ELFDumper do not
31 // display same string for same enum. The AltName if initialized appropriately
32 // will hold the string that GNU style emits.
33 // Example:
34 // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
35 // "Advanced Micro Devices X86-64" on GNU style
36 StringRef AltName;
Eric Christopher9cad53c2013-04-03 18:31:38 +000037 T Value;
Hemant Kulkarnid8a985e2016-02-10 20:40:55 +000038 EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
39 EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
Eric Christopher9cad53c2013-04-03 18:31:38 +000040};
41
42struct HexNumber {
43 // To avoid sign-extension we have to explicitly cast to the appropriate
44 // unsigned type. The overloads are here so that every type that is implicitly
45 // convertible to an integer (including enums and endian helpers) can be used
46 // without requiring type traits or call-site changes.
Matthias Braun7f472722015-10-17 00:08:45 +000047 HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) { }
48 HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) { }
49 HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) { }
50 HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) { }
51 HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) { }
52 HexNumber(signed long long Value) : Value(static_cast<unsigned long long>(Value)) { }
53 HexNumber(unsigned char Value) : Value(Value) { }
54 HexNumber(unsigned short Value) : Value(Value) { }
55 HexNumber(unsigned int Value) : Value(Value) { }
56 HexNumber(unsigned long Value) : Value(Value) { }
57 HexNumber(unsigned long long Value) : Value(Value) { }
Eric Christopher9cad53c2013-04-03 18:31:38 +000058 uint64_t Value;
59};
60
61raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value);
Hemant Kulkarnid8a985e2016-02-10 20:40:55 +000062const std::string to_hexString(uint64_t Value, bool UpperCase = true);
Hemant Kulkarnic030f232016-03-15 17:25:31 +000063
64template <class T> const std::string to_string(const T &Value) {
65 std::string number;
66 llvm::raw_string_ostream stream(number);
67 stream << Value;
68 return stream.str();
69}
Eric Christopher9cad53c2013-04-03 18:31:38 +000070
71class StreamWriter {
72public:
73 StreamWriter(raw_ostream &OS)
74 : OS(OS)
75 , IndentLevel(0) {
76 }
77
78 void flush() {
79 OS.flush();
80 }
81
82 void indent(int Levels = 1) {
83 IndentLevel += Levels;
84 }
85
86 void unindent(int Levels = 1) {
87 IndentLevel = std::max(0, IndentLevel - Levels);
88 }
89
90 void printIndent() {
91 for (int i = 0; i < IndentLevel; ++i)
92 OS << " ";
93 }
94
95 template<typename T>
96 HexNumber hex(T Value) {
97 return HexNumber(Value);
98 }
99
100 template<typename T, typename TEnum>
101 void printEnum(StringRef Label, T Value,
102 ArrayRef<EnumEntry<TEnum> > EnumValues) {
103 StringRef Name;
104 bool Found = false;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000105 for (const auto &EnumItem : EnumValues) {
106 if (EnumItem.Value == Value) {
107 Name = EnumItem.Name;
Eric Christopher9cad53c2013-04-03 18:31:38 +0000108 Found = true;
109 break;
110 }
111 }
112
113 if (Found) {
114 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
115 } else {
116 startLine() << Label << ": " << hex(Value) << "\n";
117 }
118 }
119
Simon Atanasyan67bdc792015-05-07 14:04:44 +0000120 template <typename T, typename TFlag>
121 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
Simon Atanasyan40e7eb12015-05-08 07:04:59 +0000122 TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
123 TFlag EnumMask3 = {}) {
Eric Christopher9cad53c2013-04-03 18:31:38 +0000124 typedef EnumEntry<TFlag> FlagEntry;
125 typedef SmallVector<FlagEntry, 10> FlagVector;
126 FlagVector SetFlags;
127
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000128 for (const auto &Flag : Flags) {
129 if (Flag.Value == 0)
Eric Christopher9cad53c2013-04-03 18:31:38 +0000130 continue;
131
Simon Atanasyan67bdc792015-05-07 14:04:44 +0000132 TFlag EnumMask{};
133 if (Flag.Value & EnumMask1)
134 EnumMask = EnumMask1;
135 else if (Flag.Value & EnumMask2)
136 EnumMask = EnumMask2;
Simon Atanasyan40e7eb12015-05-08 07:04:59 +0000137 else if (Flag.Value & EnumMask3)
138 EnumMask = EnumMask3;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000139 bool IsEnum = (Flag.Value & EnumMask) != 0;
140 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
141 (IsEnum && (Value & EnumMask) == Flag.Value)) {
142 SetFlags.push_back(Flag);
Eric Christopher9cad53c2013-04-03 18:31:38 +0000143 }
144 }
145
146 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
147
148 startLine() << Label << " [ (" << hex(Value) << ")\n";
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000149 for (const auto &Flag : SetFlags) {
150 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
Eric Christopher9cad53c2013-04-03 18:31:38 +0000151 }
152 startLine() << "]\n";
153 }
154
155 template<typename T>
156 void printFlags(StringRef Label, T Value) {
157 startLine() << Label << " [ (" << hex(Value) << ")\n";
158 uint64_t Flag = 1;
159 uint64_t Curr = Value;
160 while (Curr > 0) {
161 if (Curr & 1)
162 startLine() << " " << hex(Flag) << "\n";
163 Curr >>= 1;
164 Flag <<= 1;
165 }
166 startLine() << "]\n";
167 }
168
169 void printNumber(StringRef Label, uint64_t Value) {
170 startLine() << Label << ": " << Value << "\n";
171 }
172
173 void printNumber(StringRef Label, uint32_t Value) {
174 startLine() << Label << ": " << Value << "\n";
175 }
176
177 void printNumber(StringRef Label, uint16_t Value) {
178 startLine() << Label << ": " << Value << "\n";
179 }
180
181 void printNumber(StringRef Label, uint8_t Value) {
182 startLine() << Label << ": " << unsigned(Value) << "\n";
183 }
184
185 void printNumber(StringRef Label, int64_t Value) {
186 startLine() << Label << ": " << Value << "\n";
187 }
188
189 void printNumber(StringRef Label, int32_t Value) {
190 startLine() << Label << ": " << Value << "\n";
191 }
192
193 void printNumber(StringRef Label, int16_t Value) {
194 startLine() << Label << ": " << Value << "\n";
195 }
196
197 void printNumber(StringRef Label, int8_t Value) {
198 startLine() << Label << ": " << int(Value) << "\n";
199 }
200
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000201 void printNumber(StringRef Label, APSInt Value) {
202 startLine() << Label << ": " << Value << "\n";
203 }
204
Saleem Abdulrasool6ba36dc2014-06-04 15:47:11 +0000205 void printBoolean(StringRef Label, bool Value) {
206 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
207 }
208
Michael J. Spencer20546ff2015-07-09 22:32:24 +0000209 template <typename T>
210 void printList(StringRef Label, const T &List) {
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000211 startLine() << Label << ": [";
212 bool Comma = false;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000213 for (const auto &Item : List) {
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000214 if (Comma)
215 OS << ", ";
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000216 OS << Item;
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000217 Comma = true;
218 }
219 OS << "]\n";
220 }
221
Igor Kudrin496fb2f2015-10-14 12:11:50 +0000222 template <typename T>
223 void printHexList(StringRef Label, const T &List) {
224 startLine() << Label << ": [";
225 bool Comma = false;
226 for (const auto &Item : List) {
227 if (Comma)
228 OS << ", ";
229 OS << hex(Item);
230 Comma = true;
231 }
232 OS << "]\n";
233 }
234
Eric Christopher9cad53c2013-04-03 18:31:38 +0000235 template<typename T>
236 void printHex(StringRef Label, T Value) {
237 startLine() << Label << ": " << hex(Value) << "\n";
238 }
239
240 template<typename T>
241 void printHex(StringRef Label, StringRef Str, T Value) {
242 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
243 }
244
Reid Kleckner2893fd12016-01-14 17:51:54 +0000245 template <typename T>
246 void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
247 startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
248 }
249
Eric Christopher9cad53c2013-04-03 18:31:38 +0000250 void printString(StringRef Label, StringRef Value) {
251 startLine() << Label << ": " << Value << "\n";
252 }
253
254 void printString(StringRef Label, const std::string &Value) {
255 startLine() << Label << ": " << Value << "\n";
256 }
257
258 template<typename T>
259 void printNumber(StringRef Label, StringRef Str, T Value) {
260 startLine() << Label << ": " << Str << " (" << Value << ")\n";
261 }
262
263 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
264 printBinaryImpl(Label, Str, Value, false);
265 }
266
267 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000268 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
269 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000270 printBinaryImpl(Label, Str, V, false);
271 }
272
273 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
274 printBinaryImpl(Label, StringRef(), Value, false);
275 }
276
277 void printBinary(StringRef Label, ArrayRef<char> Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000278 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
279 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000280 printBinaryImpl(Label, StringRef(), V, false);
281 }
282
283 void printBinary(StringRef Label, StringRef Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000284 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
285 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000286 printBinaryImpl(Label, StringRef(), V, false);
287 }
288
289 void printBinaryBlock(StringRef Label, StringRef Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000290 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
291 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000292 printBinaryImpl(Label, StringRef(), V, true);
293 }
294
295 raw_ostream& startLine() {
296 printIndent();
297 return OS;
298 }
299
300 raw_ostream& getOStream() {
301 return OS;
302 }
303
304private:
305 template<typename T>
306 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) {
307 return lhs.Name < rhs.Name;
308 }
309
310 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
311 bool Block);
312
313 raw_ostream &OS;
314 int IndentLevel;
315};
316
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000317template <>
Reid Kleckner6b3faef2016-01-13 23:44:57 +0000318inline void
319StreamWriter::printHex<support::ulittle16_t>(StringRef Label,
320 support::ulittle16_t Value) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000321 startLine() << Label << ": " << hex(Value) << "\n";
322}
323
Eric Christopher9cad53c2013-04-03 18:31:38 +0000324struct DictScope {
325 DictScope(StreamWriter& W, StringRef N) : W(W) {
326 W.startLine() << N << " {\n";
327 W.indent();
328 }
329
330 ~DictScope() {
331 W.unindent();
332 W.startLine() << "}\n";
333 }
334
335 StreamWriter& W;
336};
337
338struct ListScope {
339 ListScope(StreamWriter& W, StringRef N) : W(W) {
340 W.startLine() << N << " [\n";
341 W.indent();
342 }
343
344 ~ListScope() {
345 W.unindent();
346 W.startLine() << "]\n";
347 }
348
349 StreamWriter& W;
350};
351
352} // namespace llvm
353
354#endif