Home | History | Annotate | Download | only in llvm-readobj
      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.
     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     auto V = makeArrayRef(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     auto V = makeArrayRef(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     auto V = makeArrayRef(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     auto V = makeArrayRef(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