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/StringRef.h" 15 #include "llvm/ADT/SmallVector.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 (size_t i = 0; i < EnumValues.size(); ++i) { 85 if (EnumValues[i].Value == Value) { 86 Name = EnumValues[i].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 (typename ArrayRef<FlagEntry>::const_iterator I = Flags.begin(), 107 E = Flags.end(); I != E; ++I) { 108 if (I->Value == 0) 109 continue; 110 111 bool IsEnum = (I->Value & EnumMask) != 0; 112 if ((!IsEnum && (Value & I->Value) == I->Value) || 113 (IsEnum && (Value & EnumMask) == I->Value)) { 114 SetFlags.push_back(*I); 115 } 116 } 117 118 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); 119 120 startLine() << Label << " [ (" << hex(Value) << ")\n"; 121 for (typename FlagVector::const_iterator I = SetFlags.begin(), 122 E = SetFlags.end(); 123 I != E; ++I) { 124 startLine() << " " << I->Name << " (" << hex(I->Value) << ")\n"; 125 } 126 startLine() << "]\n"; 127 } 128 129 template<typename T> 130 void printFlags(StringRef Label, T Value) { 131 startLine() << Label << " [ (" << hex(Value) << ")\n"; 132 uint64_t Flag = 1; 133 uint64_t Curr = Value; 134 while (Curr > 0) { 135 if (Curr & 1) 136 startLine() << " " << hex(Flag) << "\n"; 137 Curr >>= 1; 138 Flag <<= 1; 139 } 140 startLine() << "]\n"; 141 } 142 143 void printNumber(StringRef Label, uint64_t Value) { 144 startLine() << Label << ": " << Value << "\n"; 145 } 146 147 void printNumber(StringRef Label, uint32_t Value) { 148 startLine() << Label << ": " << Value << "\n"; 149 } 150 151 void printNumber(StringRef Label, uint16_t Value) { 152 startLine() << Label << ": " << Value << "\n"; 153 } 154 155 void printNumber(StringRef Label, uint8_t Value) { 156 startLine() << Label << ": " << unsigned(Value) << "\n"; 157 } 158 159 void printNumber(StringRef Label, int64_t Value) { 160 startLine() << Label << ": " << Value << "\n"; 161 } 162 163 void printNumber(StringRef Label, int32_t Value) { 164 startLine() << Label << ": " << Value << "\n"; 165 } 166 167 void printNumber(StringRef Label, int16_t Value) { 168 startLine() << Label << ": " << Value << "\n"; 169 } 170 171 void printNumber(StringRef Label, int8_t Value) { 172 startLine() << Label << ": " << int(Value) << "\n"; 173 } 174 175 template<typename T> 176 void printHex(StringRef Label, T Value) { 177 startLine() << Label << ": " << hex(Value) << "\n"; 178 } 179 180 template<typename T> 181 void printHex(StringRef Label, StringRef Str, T Value) { 182 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 183 } 184 185 void printString(StringRef Label, StringRef Value) { 186 startLine() << Label << ": " << Value << "\n"; 187 } 188 189 void printString(StringRef Label, const std::string &Value) { 190 startLine() << Label << ": " << Value << "\n"; 191 } 192 193 template<typename T> 194 void printNumber(StringRef Label, StringRef Str, T Value) { 195 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 196 } 197 198 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 199 printBinaryImpl(Label, Str, Value, false); 200 } 201 202 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 203 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 204 Value.size()); 205 printBinaryImpl(Label, Str, V, false); 206 } 207 208 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 209 printBinaryImpl(Label, StringRef(), Value, false); 210 } 211 212 void printBinary(StringRef Label, ArrayRef<char> Value) { 213 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 214 Value.size()); 215 printBinaryImpl(Label, StringRef(), V, false); 216 } 217 218 void printBinary(StringRef Label, StringRef Value) { 219 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 220 Value.size()); 221 printBinaryImpl(Label, StringRef(), V, false); 222 } 223 224 void printBinaryBlock(StringRef Label, StringRef Value) { 225 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 226 Value.size()); 227 printBinaryImpl(Label, StringRef(), V, true); 228 } 229 230 raw_ostream& startLine() { 231 printIndent(); 232 return OS; 233 } 234 235 raw_ostream& getOStream() { 236 return OS; 237 } 238 239 private: 240 template<typename T> 241 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) { 242 return lhs.Name < rhs.Name; 243 } 244 245 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 246 bool Block); 247 248 raw_ostream &OS; 249 int IndentLevel; 250 }; 251 252 struct DictScope { 253 DictScope(StreamWriter& W, StringRef N) : W(W) { 254 W.startLine() << N << " {\n"; 255 W.indent(); 256 } 257 258 ~DictScope() { 259 W.unindent(); 260 W.startLine() << "}\n"; 261 } 262 263 StreamWriter& W; 264 }; 265 266 struct ListScope { 267 ListScope(StreamWriter& W, StringRef N) : W(W) { 268 W.startLine() << N << " [\n"; 269 W.indent(); 270 } 271 272 ~ListScope() { 273 W.unindent(); 274 W.startLine() << "]\n"; 275 } 276 277 StreamWriter& W; 278 }; 279 280 } // namespace llvm 281 282 #endif 283