1 //===-- 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 10 #ifndef LLVM_READOBJ_STREAMWRITER_H 11 #define LLVM_READOBJ_STREAMWRITER_H 12 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" 19 #include <algorithm> 20 21 using namespace llvm; 22 using namespace llvm::support; 23 24 namespace llvm { 25 26 template<typename T> 27 struct EnumEntry { 28 StringRef Name; 29 T Value; 30 }; 31 32 struct 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 48 raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value); 49 50 class StreamWriter { 51 public: 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; 84 for (const auto &EnumItem : EnumValues) { 85 if (EnumItem.Value == Value) { 86 Name = EnumItem.Name; 87 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 99 template<typename T, typename TFlag> 100 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag> > Flags, 101 TFlag EnumMask = TFlag(0)) { 102 typedef EnumEntry<TFlag> FlagEntry; 103 typedef SmallVector<FlagEntry, 10> FlagVector; 104 FlagVector SetFlags; 105 106 for (const auto &Flag : Flags) { 107 if (Flag.Value == 0) 108 continue; 109 110 bool IsEnum = (Flag.Value & EnumMask) != 0; 111 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 112 (IsEnum && (Value & EnumMask) == Flag.Value)) { 113 SetFlags.push_back(Flag); 114 } 115 } 116 117 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); 118 119 startLine() << Label << " [ (" << hex(Value) << ")\n"; 120 for (const auto &Flag : SetFlags) { 121 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; 122 } 123 startLine() << "]\n"; 124 } 125 126 template<typename T> 127 void printFlags(StringRef Label, T Value) { 128 startLine() << Label << " [ (" << hex(Value) << ")\n"; 129 uint64_t Flag = 1; 130 uint64_t Curr = Value; 131 while (Curr > 0) { 132 if (Curr & 1) 133 startLine() << " " << hex(Flag) << "\n"; 134 Curr >>= 1; 135 Flag <<= 1; 136 } 137 startLine() << "]\n"; 138 } 139 140 void printNumber(StringRef Label, uint64_t Value) { 141 startLine() << Label << ": " << Value << "\n"; 142 } 143 144 void printNumber(StringRef Label, uint32_t Value) { 145 startLine() << Label << ": " << Value << "\n"; 146 } 147 148 void printNumber(StringRef Label, uint16_t Value) { 149 startLine() << Label << ": " << Value << "\n"; 150 } 151 152 void printNumber(StringRef Label, uint8_t Value) { 153 startLine() << Label << ": " << unsigned(Value) << "\n"; 154 } 155 156 void printNumber(StringRef Label, int64_t Value) { 157 startLine() << Label << ": " << Value << "\n"; 158 } 159 160 void printNumber(StringRef Label, int32_t Value) { 161 startLine() << Label << ": " << Value << "\n"; 162 } 163 164 void printNumber(StringRef Label, int16_t Value) { 165 startLine() << Label << ": " << Value << "\n"; 166 } 167 168 void printNumber(StringRef Label, int8_t Value) { 169 startLine() << Label << ": " << int(Value) << "\n"; 170 } 171 172 void printBoolean(StringRef Label, bool Value) { 173 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; 174 } 175 176 template <typename T_> 177 void printList(StringRef Label, const SmallVectorImpl<T_> &List) { 178 startLine() << Label << ": ["; 179 bool Comma = false; 180 for (const auto &Item : List) { 181 if (Comma) 182 OS << ", "; 183 OS << Item; 184 Comma = true; 185 } 186 OS << "]\n"; 187 } 188 189 template<typename T> 190 void printHex(StringRef Label, T Value) { 191 startLine() << Label << ": " << hex(Value) << "\n"; 192 } 193 194 template<typename T> 195 void printHex(StringRef Label, StringRef Str, T Value) { 196 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 197 } 198 199 void printString(StringRef Label, StringRef Value) { 200 startLine() << Label << ": " << Value << "\n"; 201 } 202 203 void printString(StringRef Label, const std::string &Value) { 204 startLine() << Label << ": " << Value << "\n"; 205 } 206 207 template<typename T> 208 void printNumber(StringRef Label, StringRef Str, T Value) { 209 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 210 } 211 212 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 213 printBinaryImpl(Label, Str, Value, false); 214 } 215 216 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 217 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 218 Value.size()); 219 printBinaryImpl(Label, Str, V, false); 220 } 221 222 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 223 printBinaryImpl(Label, StringRef(), Value, false); 224 } 225 226 void printBinary(StringRef Label, ArrayRef<char> Value) { 227 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 228 Value.size()); 229 printBinaryImpl(Label, StringRef(), V, false); 230 } 231 232 void printBinary(StringRef Label, StringRef Value) { 233 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 234 Value.size()); 235 printBinaryImpl(Label, StringRef(), V, false); 236 } 237 238 void printBinaryBlock(StringRef Label, StringRef Value) { 239 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 240 Value.size()); 241 printBinaryImpl(Label, StringRef(), V, true); 242 } 243 244 raw_ostream& startLine() { 245 printIndent(); 246 return OS; 247 } 248 249 raw_ostream& getOStream() { 250 return OS; 251 } 252 253 private: 254 template<typename T> 255 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) { 256 return lhs.Name < rhs.Name; 257 } 258 259 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 260 bool Block); 261 262 raw_ostream &OS; 263 int IndentLevel; 264 }; 265 266 struct DictScope { 267 DictScope(StreamWriter& W, StringRef N) : W(W) { 268 W.startLine() << N << " {\n"; 269 W.indent(); 270 } 271 272 ~DictScope() { 273 W.unindent(); 274 W.startLine() << "}\n"; 275 } 276 277 StreamWriter& W; 278 }; 279 280 struct ListScope { 281 ListScope(StreamWriter& W, StringRef N) : W(W) { 282 W.startLine() << N << " [\n"; 283 W.indent(); 284 } 285 286 ~ListScope() { 287 W.unindent(); 288 W.startLine() << "]\n"; 289 } 290 291 StreamWriter& W; 292 }; 293 294 } // namespace llvm 295 296 #endif 297