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_TOOLS_LLVM_READOBJ_STREAMWRITER_H 11 #define LLVM_TOOLS_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. HexNumberHexNumber37 HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) { } HexNumberHexNumber38 HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) { } HexNumberHexNumber39 HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) { } HexNumberHexNumber40 HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) { } HexNumberHexNumber41 HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) { } HexNumberHexNumber42 HexNumber(signed long long Value) : Value(static_cast<unsigned long long>(Value)) { } HexNumberHexNumber43 HexNumber(unsigned char Value) : Value(Value) { } HexNumberHexNumber44 HexNumber(unsigned short Value) : Value(Value) { } HexNumberHexNumber45 HexNumber(unsigned int Value) : Value(Value) { } HexNumberHexNumber46 HexNumber(unsigned long Value) : Value(Value) { } HexNumberHexNumber47 HexNumber(unsigned long long Value) : Value(Value) { } 48 uint64_t Value; 49 }; 50 51 raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value); 52 53 class StreamWriter { 54 public: StreamWriter(raw_ostream & OS)55 StreamWriter(raw_ostream &OS) 56 : OS(OS) 57 , IndentLevel(0) { 58 } 59 flush()60 void flush() { 61 OS.flush(); 62 } 63 64 void indent(int Levels = 1) { 65 IndentLevel += Levels; 66 } 67 68 void unindent(int Levels = 1) { 69 IndentLevel = std::max(0, IndentLevel - Levels); 70 } 71 printIndent()72 void printIndent() { 73 for (int i = 0; i < IndentLevel; ++i) 74 OS << " "; 75 } 76 77 template<typename T> hex(T Value)78 HexNumber hex(T Value) { 79 return HexNumber(Value); 80 } 81 82 template<typename T, typename TEnum> printEnum(StringRef Label,T Value,ArrayRef<EnumEntry<TEnum>> EnumValues)83 void printEnum(StringRef Label, T Value, 84 ArrayRef<EnumEntry<TEnum> > EnumValues) { 85 StringRef Name; 86 bool Found = false; 87 for (const auto &EnumItem : EnumValues) { 88 if (EnumItem.Value == Value) { 89 Name = EnumItem.Name; 90 Found = true; 91 break; 92 } 93 } 94 95 if (Found) { 96 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n"; 97 } else { 98 startLine() << Label << ": " << hex(Value) << "\n"; 99 } 100 } 101 102 template <typename T, typename TFlag> 103 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags, 104 TFlag EnumMask1 = {}, TFlag EnumMask2 = {}, 105 TFlag EnumMask3 = {}) { 106 typedef EnumEntry<TFlag> FlagEntry; 107 typedef SmallVector<FlagEntry, 10> FlagVector; 108 FlagVector SetFlags; 109 110 for (const auto &Flag : Flags) { 111 if (Flag.Value == 0) 112 continue; 113 114 TFlag EnumMask{}; 115 if (Flag.Value & EnumMask1) 116 EnumMask = EnumMask1; 117 else if (Flag.Value & EnumMask2) 118 EnumMask = EnumMask2; 119 else if (Flag.Value & EnumMask3) 120 EnumMask = EnumMask3; 121 bool IsEnum = (Flag.Value & EnumMask) != 0; 122 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 123 (IsEnum && (Value & EnumMask) == Flag.Value)) { 124 SetFlags.push_back(Flag); 125 } 126 } 127 128 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); 129 130 startLine() << Label << " [ (" << hex(Value) << ")\n"; 131 for (const auto &Flag : SetFlags) { 132 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; 133 } 134 startLine() << "]\n"; 135 } 136 137 template<typename T> printFlags(StringRef Label,T Value)138 void printFlags(StringRef Label, T Value) { 139 startLine() << Label << " [ (" << hex(Value) << ")\n"; 140 uint64_t Flag = 1; 141 uint64_t Curr = Value; 142 while (Curr > 0) { 143 if (Curr & 1) 144 startLine() << " " << hex(Flag) << "\n"; 145 Curr >>= 1; 146 Flag <<= 1; 147 } 148 startLine() << "]\n"; 149 } 150 printNumber(StringRef Label,uint64_t Value)151 void printNumber(StringRef Label, uint64_t Value) { 152 startLine() << Label << ": " << Value << "\n"; 153 } 154 printNumber(StringRef Label,uint32_t Value)155 void printNumber(StringRef Label, uint32_t Value) { 156 startLine() << Label << ": " << Value << "\n"; 157 } 158 printNumber(StringRef Label,uint16_t Value)159 void printNumber(StringRef Label, uint16_t Value) { 160 startLine() << Label << ": " << Value << "\n"; 161 } 162 printNumber(StringRef Label,uint8_t Value)163 void printNumber(StringRef Label, uint8_t Value) { 164 startLine() << Label << ": " << unsigned(Value) << "\n"; 165 } 166 printNumber(StringRef Label,int64_t Value)167 void printNumber(StringRef Label, int64_t Value) { 168 startLine() << Label << ": " << Value << "\n"; 169 } 170 printNumber(StringRef Label,int32_t Value)171 void printNumber(StringRef Label, int32_t Value) { 172 startLine() << Label << ": " << Value << "\n"; 173 } 174 printNumber(StringRef Label,int16_t Value)175 void printNumber(StringRef Label, int16_t Value) { 176 startLine() << Label << ": " << Value << "\n"; 177 } 178 printNumber(StringRef Label,int8_t Value)179 void printNumber(StringRef Label, int8_t Value) { 180 startLine() << Label << ": " << int(Value) << "\n"; 181 } 182 printBoolean(StringRef Label,bool Value)183 void printBoolean(StringRef Label, bool Value) { 184 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; 185 } 186 187 template <typename T> printList(StringRef Label,const T & List)188 void printList(StringRef Label, const T &List) { 189 startLine() << Label << ": ["; 190 bool Comma = false; 191 for (const auto &Item : List) { 192 if (Comma) 193 OS << ", "; 194 OS << Item; 195 Comma = true; 196 } 197 OS << "]\n"; 198 } 199 200 template <typename T> printHexList(StringRef Label,const T & List)201 void printHexList(StringRef Label, const T &List) { 202 startLine() << Label << ": ["; 203 bool Comma = false; 204 for (const auto &Item : List) { 205 if (Comma) 206 OS << ", "; 207 OS << hex(Item); 208 Comma = true; 209 } 210 OS << "]\n"; 211 } 212 213 template<typename T> printHex(StringRef Label,T Value)214 void printHex(StringRef Label, T Value) { 215 startLine() << Label << ": " << hex(Value) << "\n"; 216 } 217 218 template<typename T> printHex(StringRef Label,StringRef Str,T Value)219 void printHex(StringRef Label, StringRef Str, T Value) { 220 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 221 } 222 printString(StringRef Label,StringRef Value)223 void printString(StringRef Label, StringRef Value) { 224 startLine() << Label << ": " << Value << "\n"; 225 } 226 printString(StringRef Label,const std::string & Value)227 void printString(StringRef Label, const std::string &Value) { 228 startLine() << Label << ": " << Value << "\n"; 229 } 230 231 template<typename T> printNumber(StringRef Label,StringRef Str,T Value)232 void printNumber(StringRef Label, StringRef Str, T Value) { 233 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 234 } 235 printBinary(StringRef Label,StringRef Str,ArrayRef<uint8_t> Value)236 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 237 printBinaryImpl(Label, Str, Value, false); 238 } 239 printBinary(StringRef Label,StringRef Str,ArrayRef<char> Value)240 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 241 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 242 Value.size()); 243 printBinaryImpl(Label, Str, V, false); 244 } 245 printBinary(StringRef Label,ArrayRef<uint8_t> Value)246 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 247 printBinaryImpl(Label, StringRef(), Value, false); 248 } 249 printBinary(StringRef Label,ArrayRef<char> Value)250 void printBinary(StringRef Label, ArrayRef<char> Value) { 251 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 252 Value.size()); 253 printBinaryImpl(Label, StringRef(), V, false); 254 } 255 printBinary(StringRef Label,StringRef Value)256 void printBinary(StringRef Label, StringRef Value) { 257 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 258 Value.size()); 259 printBinaryImpl(Label, StringRef(), V, false); 260 } 261 printBinaryBlock(StringRef Label,StringRef Value)262 void printBinaryBlock(StringRef Label, StringRef Value) { 263 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 264 Value.size()); 265 printBinaryImpl(Label, StringRef(), V, true); 266 } 267 startLine()268 raw_ostream& startLine() { 269 printIndent(); 270 return OS; 271 } 272 getOStream()273 raw_ostream& getOStream() { 274 return OS; 275 } 276 277 private: 278 template<typename T> flagName(const EnumEntry<T> & lhs,const EnumEntry<T> & rhs)279 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) { 280 return lhs.Name < rhs.Name; 281 } 282 283 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 284 bool Block); 285 286 raw_ostream &OS; 287 int IndentLevel; 288 }; 289 290 struct DictScope { DictScopeDictScope291 DictScope(StreamWriter& W, StringRef N) : W(W) { 292 W.startLine() << N << " {\n"; 293 W.indent(); 294 } 295 ~DictScopeDictScope296 ~DictScope() { 297 W.unindent(); 298 W.startLine() << "}\n"; 299 } 300 301 StreamWriter& W; 302 }; 303 304 struct ListScope { ListScopeListScope305 ListScope(StreamWriter& W, StringRef N) : W(W) { 306 W.startLine() << N << " [\n"; 307 W.indent(); 308 } 309 ~ListScopeListScope310 ~ListScope() { 311 W.unindent(); 312 W.startLine() << "]\n"; 313 } 314 315 StreamWriter& W; 316 }; 317 318 } // namespace llvm 319 320 #endif 321