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(int8_t Value) : Value(static_cast<uint8_t >(Value)) { } HexNumberHexNumber38 HexNumber(int16_t Value) : Value(static_cast<uint16_t>(Value)) { } HexNumberHexNumber39 HexNumber(int32_t Value) : Value(static_cast<uint32_t>(Value)) { } HexNumberHexNumber40 HexNumber(int64_t Value) : Value(static_cast<uint64_t>(Value)) { } HexNumberHexNumber41 HexNumber(uint8_t Value) : Value(Value) { } HexNumberHexNumber42 HexNumber(uint16_t Value) : Value(Value) { } HexNumberHexNumber43 HexNumber(uint32_t Value) : Value(Value) { } HexNumberHexNumber44 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: StreamWriter(raw_ostream & OS)52 StreamWriter(raw_ostream &OS) 53 : OS(OS) 54 , IndentLevel(0) { 55 } 56 flush()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 printIndent()69 void printIndent() { 70 for (int i = 0; i < IndentLevel; ++i) 71 OS << " "; 72 } 73 74 template<typename T> hex(T Value)75 HexNumber hex(T Value) { 76 return HexNumber(Value); 77 } 78 79 template<typename T, typename TEnum> printEnum(StringRef Label,T Value,ArrayRef<EnumEntry<TEnum>> EnumValues)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> printFlags(StringRef Label,T Value)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 printNumber(StringRef Label,uint64_t Value)140 void printNumber(StringRef Label, uint64_t Value) { 141 startLine() << Label << ": " << Value << "\n"; 142 } 143 printNumber(StringRef Label,uint32_t Value)144 void printNumber(StringRef Label, uint32_t Value) { 145 startLine() << Label << ": " << Value << "\n"; 146 } 147 printNumber(StringRef Label,uint16_t Value)148 void printNumber(StringRef Label, uint16_t Value) { 149 startLine() << Label << ": " << Value << "\n"; 150 } 151 printNumber(StringRef Label,uint8_t Value)152 void printNumber(StringRef Label, uint8_t Value) { 153 startLine() << Label << ": " << unsigned(Value) << "\n"; 154 } 155 printNumber(StringRef Label,int64_t Value)156 void printNumber(StringRef Label, int64_t Value) { 157 startLine() << Label << ": " << Value << "\n"; 158 } 159 printNumber(StringRef Label,int32_t Value)160 void printNumber(StringRef Label, int32_t Value) { 161 startLine() << Label << ": " << Value << "\n"; 162 } 163 printNumber(StringRef Label,int16_t Value)164 void printNumber(StringRef Label, int16_t Value) { 165 startLine() << Label << ": " << Value << "\n"; 166 } 167 printNumber(StringRef Label,int8_t Value)168 void printNumber(StringRef Label, int8_t Value) { 169 startLine() << Label << ": " << int(Value) << "\n"; 170 } 171 printBoolean(StringRef Label,bool Value)172 void printBoolean(StringRef Label, bool Value) { 173 startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; 174 } 175 176 template <typename T_> printList(StringRef Label,const SmallVectorImpl<T_> & List)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> printHex(StringRef Label,T Value)190 void printHex(StringRef Label, T Value) { 191 startLine() << Label << ": " << hex(Value) << "\n"; 192 } 193 194 template<typename T> printHex(StringRef Label,StringRef Str,T Value)195 void printHex(StringRef Label, StringRef Str, T Value) { 196 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 197 } 198 printString(StringRef Label,StringRef Value)199 void printString(StringRef Label, StringRef Value) { 200 startLine() << Label << ": " << Value << "\n"; 201 } 202 printString(StringRef Label,const std::string & Value)203 void printString(StringRef Label, const std::string &Value) { 204 startLine() << Label << ": " << Value << "\n"; 205 } 206 207 template<typename T> printNumber(StringRef Label,StringRef Str,T Value)208 void printNumber(StringRef Label, StringRef Str, T Value) { 209 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 210 } 211 printBinary(StringRef Label,StringRef Str,ArrayRef<uint8_t> Value)212 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 213 printBinaryImpl(Label, Str, Value, false); 214 } 215 printBinary(StringRef Label,StringRef Str,ArrayRef<char> Value)216 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 217 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 218 Value.size()); 219 printBinaryImpl(Label, Str, V, false); 220 } 221 printBinary(StringRef Label,ArrayRef<uint8_t> Value)222 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 223 printBinaryImpl(Label, StringRef(), Value, false); 224 } 225 printBinary(StringRef Label,ArrayRef<char> Value)226 void printBinary(StringRef Label, ArrayRef<char> Value) { 227 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 228 Value.size()); 229 printBinaryImpl(Label, StringRef(), V, false); 230 } 231 printBinary(StringRef Label,StringRef Value)232 void printBinary(StringRef Label, StringRef Value) { 233 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 234 Value.size()); 235 printBinaryImpl(Label, StringRef(), V, false); 236 } 237 printBinaryBlock(StringRef Label,StringRef Value)238 void printBinaryBlock(StringRef Label, StringRef Value) { 239 auto V = makeArrayRef(reinterpret_cast<const uint8_t*>(Value.data()), 240 Value.size()); 241 printBinaryImpl(Label, StringRef(), V, true); 242 } 243 startLine()244 raw_ostream& startLine() { 245 printIndent(); 246 return OS; 247 } 248 getOStream()249 raw_ostream& getOStream() { 250 return OS; 251 } 252 253 private: 254 template<typename T> flagName(const EnumEntry<T> & lhs,const EnumEntry<T> & rhs)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 { DictScopeDictScope267 DictScope(StreamWriter& W, StringRef N) : W(W) { 268 W.startLine() << N << " {\n"; 269 W.indent(); 270 } 271 ~DictScopeDictScope272 ~DictScope() { 273 W.unindent(); 274 W.startLine() << "}\n"; 275 } 276 277 StreamWriter& W; 278 }; 279 280 struct ListScope { ListScopeListScope281 ListScope(StreamWriter& W, StringRef N) : W(W) { 282 W.startLine() << N << " [\n"; 283 W.indent(); 284 } 285 ~ListScopeListScope286 ~ListScope() { 287 W.unindent(); 288 W.startLine() << "]\n"; 289 } 290 291 StreamWriter& W; 292 }; 293 294 } // namespace llvm 295 296 #endif 297