blob: 9e88edc5a1ef350fc7b8e604a4d3fac22fa28afc [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
13#include "llvm/ADT/ArrayRef.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000014#include "llvm/ADT/SmallVector.h"
Chandler Carruth07baed52014-01-13 08:04:33 +000015#include "llvm/ADT/StringRef.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000016#include "llvm/Support/DataTypes.h"
17#include "llvm/Support/Endian.h"
18#include "llvm/Support/raw_ostream.h"
19#include <algorithm>
20
21using namespace llvm;
22using namespace llvm::support;
23
24namespace llvm {
25
26template<typename T>
27struct EnumEntry {
28 StringRef Name;
29 T Value;
30};
31
32struct HexNumber {
33 // To avoid sign-extension we have to explicitly cast to the appropriate
34 // unsigned type. The overloads are here so that every type that is implicitly
35 // convertible to an integer (including enums and endian helpers) can be used
36 // without requiring type traits or call-site changes.
37 HexNumber(int8_t Value) : Value(static_cast<uint8_t >(Value)) { }
38 HexNumber(int16_t Value) : Value(static_cast<uint16_t>(Value)) { }
39 HexNumber(int32_t Value) : Value(static_cast<uint32_t>(Value)) { }
40 HexNumber(int64_t Value) : Value(static_cast<uint64_t>(Value)) { }
41 HexNumber(uint8_t Value) : Value(Value) { }
42 HexNumber(uint16_t Value) : Value(Value) { }
43 HexNumber(uint32_t Value) : Value(Value) { }
44 HexNumber(uint64_t Value) : Value(Value) { }
45 uint64_t Value;
46};
47
48raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value);
49
50class StreamWriter {
51public:
52 StreamWriter(raw_ostream &OS)
53 : OS(OS)
54 , IndentLevel(0) {
55 }
56
57 void flush() {
58 OS.flush();
59 }
60
61 void indent(int Levels = 1) {
62 IndentLevel += Levels;
63 }
64
65 void unindent(int Levels = 1) {
66 IndentLevel = std::max(0, IndentLevel - Levels);
67 }
68
69 void printIndent() {
70 for (int i = 0; i < IndentLevel; ++i)
71 OS << " ";
72 }
73
74 template<typename T>
75 HexNumber hex(T Value) {
76 return HexNumber(Value);
77 }
78
79 template<typename T, typename TEnum>
80 void printEnum(StringRef Label, T Value,
81 ArrayRef<EnumEntry<TEnum> > EnumValues) {
82 StringRef Name;
83 bool Found = false;
Simon Atanasyan883b44e2014-04-20 21:05:30 +000084 for (const auto &EnumItem : EnumValues) {
85 if (EnumItem.Value == Value) {
86 Name = EnumItem.Name;
Eric Christopher9cad53c2013-04-03 18:31:38 +000087 Found = true;
88 break;
89 }
90 }
91
92 if (Found) {
93 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
94 } else {
95 startLine() << Label << ": " << hex(Value) << "\n";
96 }
97 }
98
Simon Atanasyan67bdc792015-05-07 14:04:44 +000099 template <typename T, typename TFlag>
100 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
Simon Atanasyan40e7eb12015-05-08 07:04:59 +0000101 TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
102 TFlag EnumMask3 = {}) {
Eric Christopher9cad53c2013-04-03 18:31:38 +0000103 typedef EnumEntry<TFlag> FlagEntry;
104 typedef SmallVector<FlagEntry, 10> FlagVector;
105 FlagVector SetFlags;
106
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000107 for (const auto &Flag : Flags) {
108 if (Flag.Value == 0)
Eric Christopher9cad53c2013-04-03 18:31:38 +0000109 continue;
110
Simon Atanasyan67bdc792015-05-07 14:04:44 +0000111 TFlag EnumMask{};
112 if (Flag.Value & EnumMask1)
113 EnumMask = EnumMask1;
114 else if (Flag.Value & EnumMask2)
115 EnumMask = EnumMask2;
Simon Atanasyan40e7eb12015-05-08 07:04:59 +0000116 else if (Flag.Value & EnumMask3)
117 EnumMask = EnumMask3;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000118 bool IsEnum = (Flag.Value & EnumMask) != 0;
119 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
120 (IsEnum && (Value & EnumMask) == Flag.Value)) {
121 SetFlags.push_back(Flag);
Eric Christopher9cad53c2013-04-03 18:31:38 +0000122 }
123 }
124
125 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
126
127 startLine() << Label << " [ (" << hex(Value) << ")\n";
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000128 for (const auto &Flag : SetFlags) {
129 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
Eric Christopher9cad53c2013-04-03 18:31:38 +0000130 }
131 startLine() << "]\n";
132 }
133
134 template<typename T>
135 void printFlags(StringRef Label, T Value) {
136 startLine() << Label << " [ (" << hex(Value) << ")\n";
137 uint64_t Flag = 1;
138 uint64_t Curr = Value;
139 while (Curr > 0) {
140 if (Curr & 1)
141 startLine() << " " << hex(Flag) << "\n";
142 Curr >>= 1;
143 Flag <<= 1;
144 }
145 startLine() << "]\n";
146 }
147
148 void printNumber(StringRef Label, uint64_t Value) {
149 startLine() << Label << ": " << Value << "\n";
150 }
151
152 void printNumber(StringRef Label, uint32_t Value) {
153 startLine() << Label << ": " << Value << "\n";
154 }
155
156 void printNumber(StringRef Label, uint16_t Value) {
157 startLine() << Label << ": " << Value << "\n";
158 }
159
160 void printNumber(StringRef Label, uint8_t Value) {
161 startLine() << Label << ": " << unsigned(Value) << "\n";
162 }
163
164 void printNumber(StringRef Label, int64_t Value) {
165 startLine() << Label << ": " << Value << "\n";
166 }
167
168 void printNumber(StringRef Label, int32_t Value) {
169 startLine() << Label << ": " << Value << "\n";
170 }
171
172 void printNumber(StringRef Label, int16_t Value) {
173 startLine() << Label << ": " << Value << "\n";
174 }
175
176 void printNumber(StringRef Label, int8_t Value) {
177 startLine() << Label << ": " << int(Value) << "\n";
178 }
179
Saleem Abdulrasool6ba36dc2014-06-04 15:47:11 +0000180 void printBoolean(StringRef Label, bool Value) {
181 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
182 }
183
Michael J. Spencer20546ff2015-07-09 22:32:24 +0000184 template <typename T>
185 void printList(StringRef Label, const T &List) {
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000186 startLine() << Label << ": [";
187 bool Comma = false;
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000188 for (const auto &Item : List) {
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000189 if (Comma)
190 OS << ", ";
Simon Atanasyan883b44e2014-04-20 21:05:30 +0000191 OS << Item;
Saleem Abdulrasool15d16d82014-01-30 04:46:33 +0000192 Comma = true;
193 }
194 OS << "]\n";
195 }
196
Igor Kudrin496fb2f2015-10-14 12:11:50 +0000197 template <typename T>
198 void printHexList(StringRef Label, const T &List) {
199 startLine() << Label << ": [";
200 bool Comma = false;
201 for (const auto &Item : List) {
202 if (Comma)
203 OS << ", ";
204 OS << hex(Item);
205 Comma = true;
206 }
207 OS << "]\n";
208 }
209
Eric Christopher9cad53c2013-04-03 18:31:38 +0000210 template<typename T>
211 void printHex(StringRef Label, T Value) {
212 startLine() << Label << ": " << hex(Value) << "\n";
213 }
214
215 template<typename T>
216 void printHex(StringRef Label, StringRef Str, T Value) {
217 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
218 }
219
220 void printString(StringRef Label, StringRef Value) {
221 startLine() << Label << ": " << Value << "\n";
222 }
223
224 void printString(StringRef Label, const std::string &Value) {
225 startLine() << Label << ": " << Value << "\n";
226 }
227
228 template<typename T>
229 void printNumber(StringRef Label, StringRef Str, T Value) {
230 startLine() << Label << ": " << Str << " (" << Value << ")\n";
231 }
232
233 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
234 printBinaryImpl(Label, Str, Value, false);
235 }
236
237 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000238 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
239 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000240 printBinaryImpl(Label, Str, V, false);
241 }
242
243 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
244 printBinaryImpl(Label, StringRef(), Value, false);
245 }
246
247 void printBinary(StringRef Label, ArrayRef<char> Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000248 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
249 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000250 printBinaryImpl(Label, StringRef(), V, false);
251 }
252
253 void printBinary(StringRef Label, StringRef Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000254 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
255 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000256 printBinaryImpl(Label, StringRef(), V, false);
257 }
258
259 void printBinaryBlock(StringRef Label, StringRef Value) {
Craig Toppere1d12942014-08-27 05:25:25 +0000260 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()),
261 Value.size());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000262 printBinaryImpl(Label, StringRef(), V, true);
263 }
264
265 raw_ostream& startLine() {
266 printIndent();
267 return OS;
268 }
269
270 raw_ostream& getOStream() {
271 return OS;
272 }
273
274private:
275 template<typename T>
276 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) {
277 return lhs.Name < rhs.Name;
278 }
279
280 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
281 bool Block);
282
283 raw_ostream &OS;
284 int IndentLevel;
285};
286
287struct DictScope {
288 DictScope(StreamWriter& W, StringRef N) : W(W) {
289 W.startLine() << N << " {\n";
290 W.indent();
291 }
292
293 ~DictScope() {
294 W.unindent();
295 W.startLine() << "}\n";
296 }
297
298 StreamWriter& W;
299};
300
301struct ListScope {
302 ListScope(StreamWriter& W, StringRef N) : W(W) {
303 W.startLine() << N << " [\n";
304 W.indent();
305 }
306
307 ~ListScope() {
308 W.unindent();
309 W.startLine() << "]\n";
310 }
311
312 StreamWriter& W;
313};
314
315} // namespace llvm
316
317#endif