blob: 08aa519e8ef83c6e15cff6980a6a891fccb9a2bb [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;
23using namespace llvm::support;
24
25namespace llvm {
26
27template<typename T>
28struct EnumEntry {
29 StringRef Name;
30 T Value;
31};
32
33struct HexNumber {
34 // To avoid sign-extension we have to explicitly cast to the appropriate
35 // unsigned type. The overloads are here so that every type that is implicitly
36 // convertible to an integer (including enums and endian helpers) can be used
37 // without requiring type traits or call-site changes.
Matthias Braun7f472722015-10-17 00:08:45 +000038 HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) { }
39 HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) { }
40 HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) { }
41 HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) { }
42 HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) { }
43 HexNumber(signed long long Value) : Value(static_cast<unsigned long long>(Value)) { }
44 HexNumber(unsigned char Value) : Value(Value) { }
45 HexNumber(unsigned short Value) : Value(Value) { }
46 HexNumber(unsigned int Value) : Value(Value) { }
47 HexNumber(unsigned long Value) : Value(Value) { }
48 HexNumber(unsigned long long Value) : Value(Value) { }
Eric Christopher9cad53c2013-04-03 18:31:38 +000049 uint64_t Value;
50};
51
52raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value);
53
54class StreamWriter {
55public:
56 StreamWriter(raw_ostream &OS)
57 : OS(OS)
58 , IndentLevel(0) {
59 }
60
61 void flush() {
62 OS.flush();
63 }
64
65 void indent(int Levels = 1) {
66 IndentLevel += Levels;
67 }
68
69 void unindent(int Levels = 1) {
70 IndentLevel = std::max(0, IndentLevel - Levels);
71 }
72
73 void printIndent() {
74 for (int i = 0; i < IndentLevel; ++i)
75 OS << " ";
76 }
77
78 template<typename T>
79 HexNumber hex(T Value) {
80 return HexNumber(Value);
81 }
82
83 template<typename T, typename TEnum>
84 void printEnum(StringRef Label, T Value,
85 ArrayRef<EnumEntry<TEnum> > EnumValues) {
86 StringRef Name;
87 bool Found = false;
Simon Atanasyan883b44e2014-04-20 21:05:30 +000088 for (const auto &EnumItem : EnumValues) {
89 if (EnumItem.Value == Value) {
90 Name = EnumItem.Name;
Eric Christopher9cad53c2013-04-03 18:31:38 +000091 Found = true;
92 break;
93 }
94 }
95
96 if (Found) {
97 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
98 } else {
99 startLine() << Label << ": " << hex(Value) << "\n";
100 }
101 }
102
Simon Atanasyan67bdc792015-05-07 14:04:44 +0000103 template <typename T, typename TFlag>
104 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
Simon Atanasyan40e7eb12015-05-08 07:04:59 +0000105 TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
106 TFlag EnumMask3 = {}) {
Eric Christopher9cad53c2013-04-03 18:31:38 +0000107 typedef EnumEntry<TFlag> FlagEntry;
108 typedef SmallVector<FlagEntry, 10> FlagVector;
109 FlagVector SetFlags;
110
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000111 for (const auto &Flag : Flags) {
112 if (Flag.Value == 0)
Eric Christopher9cad53c2013-04-03 18:31:38 +0000113 continue;
114
Simon Atanasyan67bdc792015-05-07 14:04:44 +0000115 TFlag EnumMask{};
116 if (Flag.Value & EnumMask1)
117 EnumMask = EnumMask1;
118 else if (Flag.Value & EnumMask2)
119 EnumMask = EnumMask2;
Simon Atanasyan40e7eb12015-05-08 07:04:59 +0000120 else if (Flag.Value & EnumMask3)
121 EnumMask = EnumMask3;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000122 bool IsEnum = (Flag.Value & EnumMask) != 0;
123 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
124 (IsEnum && (Value & EnumMask) == Flag.Value)) {
125 SetFlags.push_back(Flag);
Eric Christopher9cad53c2013-04-03 18:31:38 +0000126 }
127 }
128
129 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
130
131 startLine() << Label << " [ (" << hex(Value) << ")\n";
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000132 for (const auto &Flag : SetFlags) {
133 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
Eric Christopher9cad53c2013-04-03 18:31:38 +0000134 }
135 startLine() << "]\n";
136 }
137
138 template<typename T>
139 void printFlags(StringRef Label, T Value) {
140 startLine() << Label << " [ (" << hex(Value) << ")\n";
141 uint64_t Flag = 1;
142 uint64_t Curr = Value;
143 while (Curr > 0) {
144 if (Curr & 1)
145 startLine() << " " << hex(Flag) << "\n";
146 Curr >>= 1;
147 Flag <<= 1;
148 }
149 startLine() << "]\n";
150 }
151
152 void printNumber(StringRef Label, uint64_t Value) {
153 startLine() << Label << ": " << Value << "\n";
154 }
155
156 void printNumber(StringRef Label, uint32_t Value) {
157 startLine() << Label << ": " << Value << "\n";
158 }
159
160 void printNumber(StringRef Label, uint16_t Value) {
161 startLine() << Label << ": " << Value << "\n";
162 }
163
164 void printNumber(StringRef Label, uint8_t Value) {
165 startLine() << Label << ": " << unsigned(Value) << "\n";
166 }
167
168 void printNumber(StringRef Label, int64_t Value) {
169 startLine() << Label << ": " << Value << "\n";
170 }
171
172 void printNumber(StringRef Label, int32_t Value) {
173 startLine() << Label << ": " << Value << "\n";
174 }
175
176 void printNumber(StringRef Label, int16_t Value) {
177 startLine() << Label << ": " << Value << "\n";
178 }
179
180 void printNumber(StringRef Label, int8_t Value) {
181 startLine() << Label << ": " << int(Value) << "\n";
182 }
183
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000184 void printNumber(StringRef Label, APSInt Value) {
185 startLine() << Label << ": " << Value << "\n";
186 }
187
Saleem Abdulrasool6ba36dc2014-06-04 15:47:11 +0000188 void printBoolean(StringRef Label, bool Value) {
189 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
190 }
191
Michael J. Spencer20546ff2015-07-09 22:32:24 +0000192 template <typename T>
193 void printList(StringRef Label, const T &List) {
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000194 startLine() << Label << ": [";
195 bool Comma = false;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000196 for (const auto &Item : List) {
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000197 if (Comma)
198 OS << ", ";
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000199 OS << Item;
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000200 Comma = true;
201 }
202 OS << "]\n";
203 }
204
Igor Kudrin496fb2f2015-10-14 12:11:50 +0000205 template <typename T>
206 void printHexList(StringRef Label, const T &List) {
207 startLine() << Label << ": [";
208 bool Comma = false;
209 for (const auto &Item : List) {
210 if (Comma)
211 OS << ", ";
212 OS << hex(Item);
213 Comma = true;
214 }
215 OS << "]\n";
216 }
217
Eric Christopher9cad53c2013-04-03 18:31:38 +0000218 template<typename T>
219 void printHex(StringRef Label, T Value) {
220 startLine() << Label << ": " << hex(Value) << "\n";
221 }
222
223 template<typename T>
224 void printHex(StringRef Label, StringRef Str, T Value) {
225 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
226 }
227
228 void printString(StringRef Label, StringRef Value) {
229 startLine() << Label << ": " << Value << "\n";
230 }
231
232 void printString(StringRef Label, const std::string &Value) {
233 startLine() << Label << ": " << Value << "\n";
234 }
235
236 template<typename T>
237 void printNumber(StringRef Label, StringRef Str, T Value) {
238 startLine() << Label << ": " << Str << " (" << Value << ")\n";
239 }
240
241 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
242 printBinaryImpl(Label, Str, Value, false);
243 }
244
245 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000246 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
247 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000248 printBinaryImpl(Label, Str, V, false);
249 }
250
251 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
252 printBinaryImpl(Label, StringRef(), Value, false);
253 }
254
255 void printBinary(StringRef Label, ArrayRef<char> Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000256 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
257 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000258 printBinaryImpl(Label, StringRef(), V, false);
259 }
260
261 void printBinary(StringRef Label, StringRef Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000262 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
263 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000264 printBinaryImpl(Label, StringRef(), V, false);
265 }
266
267 void printBinaryBlock(StringRef Label, StringRef 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, StringRef(), V, true);
271 }
272
273 raw_ostream& startLine() {
274 printIndent();
275 return OS;
276 }
277
278 raw_ostream& getOStream() {
279 return OS;
280 }
281
282private:
283 template<typename T>
284 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) {
285 return lhs.Name < rhs.Name;
286 }
287
288 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
289 bool Block);
290
291 raw_ostream &OS;
292 int IndentLevel;
293};
294
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000295template <>
296inline void StreamWriter::printHex<ulittle16_t>(StringRef Label,
297 ulittle16_t Value) {
298 startLine() << Label << ": " << hex(Value) << "\n";
299}
300
Eric Christopher9cad53c2013-04-03 18:31:38 +0000301struct DictScope {
302 DictScope(StreamWriter& W, StringRef N) : W(W) {
303 W.startLine() << N << " {\n";
304 W.indent();
305 }
306
307 ~DictScope() {
308 W.unindent();
309 W.startLine() << "}\n";
310 }
311
312 StreamWriter& W;
313};
314
315struct ListScope {
316 ListScope(StreamWriter& W, StringRef N) : W(W) {
317 W.startLine() << N << " [\n";
318 W.indent();
319 }
320
321 ~ListScope() {
322 W.unindent();
323 W.startLine() << "]\n";
324 }
325
326 StreamWriter& W;
327};
328
329} // namespace llvm
330
331#endif