Home | History | Annotate | Download | only in Support
      1 //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===//
      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 // This file implements format providers for many common LLVM types, for example
     11 // allowing precision and width specifiers for scalar and string types.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H
     16 #define LLVM_SUPPORT_FORMATPROVIDERS_H
     17 
     18 #include "llvm/ADT/Optional.h"
     19 #include "llvm/ADT/STLExtras.h"
     20 #include "llvm/ADT/StringSwitch.h"
     21 #include "llvm/ADT/Twine.h"
     22 #include "llvm/Support/FormatVariadicDetails.h"
     23 #include "llvm/Support/NativeFormatting.h"
     24 
     25 #include <type_traits>
     26 #include <vector>
     27 
     28 namespace llvm {
     29 namespace detail {
     30 template <typename T>
     31 struct use_integral_formatter
     32     : public std::integral_constant<
     33           bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
     34                           int64_t, uint64_t, int, unsigned, long, unsigned long,
     35                           long long, unsigned long long>::value> {};
     36 
     37 template <typename T>
     38 struct use_char_formatter
     39     : public std::integral_constant<bool, std::is_same<T, char>::value> {};
     40 
     41 template <typename T>
     42 struct is_cstring
     43     : public std::integral_constant<bool,
     44                                     is_one_of<T, char *, const char *>::value> {
     45 };
     46 
     47 template <typename T>
     48 struct use_string_formatter
     49     : public std::integral_constant<bool,
     50                                     std::is_convertible<T, llvm::StringRef>::value> {};
     51 
     52 template <typename T>
     53 struct use_pointer_formatter
     54     : public std::integral_constant<bool, std::is_pointer<T>::value &&
     55                                               !is_cstring<T>::value> {};
     56 
     57 template <typename T>
     58 struct use_double_formatter
     59     : public std::integral_constant<bool, std::is_floating_point<T>::value> {};
     60 
     61 class HelperFunctions {
     62 protected:
     63   static Optional<size_t> parseNumericPrecision(StringRef Str) {
     64     size_t Prec;
     65     Optional<size_t> Result;
     66     if (Str.empty())
     67       Result = None;
     68     else if (Str.getAsInteger(10, Prec)) {
     69       assert(false && "Invalid precision specifier");
     70       Result = None;
     71     } else {
     72       assert(Prec < 100 && "Precision out of range");
     73       Result = std::min<size_t>(99u, Prec);
     74     }
     75     return Result;
     76   }
     77 
     78   static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
     79     if (!Str.startswith_lower("x"))
     80       return false;
     81 
     82     if (Str.consume_front("x-"))
     83       Style = HexPrintStyle::Lower;
     84     else if (Str.consume_front("X-"))
     85       Style = HexPrintStyle::Upper;
     86     else if (Str.consume_front("x+") || Str.consume_front("x"))
     87       Style = HexPrintStyle::PrefixLower;
     88     else if (Str.consume_front("X+") || Str.consume_front("X"))
     89       Style = HexPrintStyle::PrefixUpper;
     90     return true;
     91   }
     92 
     93   static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style,
     94                                     size_t Default) {
     95     Str.consumeInteger(10, Default);
     96     if (isPrefixedHexStyle(Style))
     97       Default += 2;
     98     return Default;
     99   }
    100 };
    101 }
    102 
    103 /// Implementation of format_provider<T> for integral arithmetic types.
    104 ///
    105 /// The options string of an integral type has the grammar:
    106 ///
    107 ///   integer_options   :: [style][digits]
    108 ///   style             :: <see table below>
    109 ///   digits            :: <non-negative integer> 0-99
    110 ///
    111 ///   ==========================================================================
    112 ///   |  style  |     Meaning          |      Example     | Digits Meaning     |
    113 ///   --------------------------------------------------------------------------
    114 ///   |         |                      |  Input |  Output |                    |
    115 ///   ==========================================================================
    116 ///   |   x-    | Hex no prefix, lower |   42   |    2a   | Minimum # digits   |
    117 ///   |   X-    | Hex no prefix, upper |   42   |    2A   | Minimum # digits   |
    118 ///   | x+ / x  | Hex + prefix, lower  |   42   |   0x2a  | Minimum # digits   |
    119 ///   | X+ / X  | Hex + prefix, upper  |   42   |   0x2A  | Minimum # digits   |
    120 ///   | N / n   | Digit grouped number | 123456 | 123,456 | Ignored            |
    121 ///   | D / d   | Integer              | 100000 | 100000  | Ignored            |
    122 ///   | (empty) | Same as D / d        |        |         |                    |
    123 ///   ==========================================================================
    124 ///
    125 
    126 template <typename T>
    127 struct format_provider<
    128     T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
    129     : public detail::HelperFunctions {
    130 private:
    131 public:
    132   static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
    133     HexPrintStyle HS;
    134     size_t Digits = 0;
    135     if (consumeHexStyle(Style, HS)) {
    136       Digits = consumeNumHexDigits(Style, HS, 0);
    137       write_hex(Stream, V, HS, Digits);
    138       return;
    139     }
    140 
    141     IntegerStyle IS = IntegerStyle::Integer;
    142     if (Style.consume_front("N") || Style.consume_front("n"))
    143       IS = IntegerStyle::Number;
    144     else if (Style.consume_front("D") || Style.consume_front("d"))
    145       IS = IntegerStyle::Integer;
    146 
    147     Style.consumeInteger(10, Digits);
    148     assert(Style.empty() && "Invalid integral format style!");
    149     write_integer(Stream, V, Digits, IS);
    150   }
    151 };
    152 
    153 /// Implementation of format_provider<T> for integral pointer types.
    154 ///
    155 /// The options string of a pointer type has the grammar:
    156 ///
    157 ///   pointer_options   :: [style][precision]
    158 ///   style             :: <see table below>
    159 ///   digits            :: <non-negative integer> 0-sizeof(void*)
    160 ///
    161 ///   ==========================================================================
    162 ///   |   S     |     Meaning          |                Example                |
    163 ///   --------------------------------------------------------------------------
    164 ///   |         |                      |       Input       |      Output       |
    165 ///   ==========================================================================
    166 ///   |   x-    | Hex no prefix, lower |    0xDEADBEEF     |     deadbeef      |
    167 ///   |   X-    | Hex no prefix, upper |    0xDEADBEEF     |     DEADBEEF      |
    168 ///   | x+ / x  | Hex + prefix, lower  |    0xDEADBEEF     |    0xdeadbeef     |
    169 ///   | X+ / X  | Hex + prefix, upper  |    0xDEADBEEF     |    0xDEADBEEF     |
    170 ///   | (empty) | Same as X+ / X       |                   |                   |
    171 ///   ==========================================================================
    172 ///
    173 /// The default precision is the number of nibbles in a machine word, and in all
    174 /// cases indicates the minimum number of nibbles to print.
    175 template <typename T>
    176 struct format_provider<
    177     T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
    178     : public detail::HelperFunctions {
    179 private:
    180 public:
    181   static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
    182     HexPrintStyle HS = HexPrintStyle::PrefixUpper;
    183     consumeHexStyle(Style, HS);
    184     size_t Digits = consumeNumHexDigits(Style, HS, sizeof(void *) * 2);
    185     write_hex(Stream, reinterpret_cast<std::uintptr_t>(V), HS, Digits);
    186   }
    187 };
    188 
    189 /// Implementation of format_provider<T> for c-style strings and string
    190 /// objects such as std::string and llvm::StringRef.
    191 ///
    192 /// The options string of a string type has the grammar:
    193 ///
    194 ///   string_options :: [length]
    195 ///
    196 /// where `length` is an optional integer specifying the maximum number of
    197 /// characters in the string to print.  If `length` is omitted, the string is
    198 /// printed up to the null terminator.
    199 
    200 template <typename T>
    201 struct format_provider<
    202     T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> {
    203   static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
    204     size_t N = StringRef::npos;
    205     if (!Style.empty() && Style.getAsInteger(10, N)) {
    206       assert(false && "Style is not a valid integer");
    207     }
    208     llvm::StringRef S = V;
    209     Stream << S.substr(0, N);
    210   }
    211 };
    212 
    213 /// Implementation of format_provider<T> for llvm::Twine.
    214 ///
    215 /// This follows the same rules as the string formatter.
    216 
    217 template <> struct format_provider<Twine> {
    218   static void format(const Twine &V, llvm::raw_ostream &Stream,
    219                      StringRef Style) {
    220     format_provider<std::string>::format(V.str(), Stream, Style);
    221   }
    222 };
    223 
    224 /// Implementation of format_provider<T> for characters.
    225 ///
    226 /// The options string of a character type has the grammar:
    227 ///
    228 ///   char_options :: (empty) | [integer_options]
    229 ///
    230 /// If `char_options` is empty, the character is displayed as an ASCII
    231 /// character.  Otherwise, it is treated as an integer options string.
    232 ///
    233 template <typename T>
    234 struct format_provider<
    235     T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
    236   static void format(const char &V, llvm::raw_ostream &Stream,
    237                      StringRef Style) {
    238     if (Style.empty())
    239       Stream << V;
    240     else {
    241       int X = static_cast<int>(V);
    242       format_provider<int>::format(X, Stream, Style);
    243     }
    244   }
    245 };
    246 
    247 /// Implementation of format_provider<T> for type `bool`
    248 ///
    249 /// The options string of a boolean type has the grammar:
    250 ///
    251 ///   bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
    252 ///
    253 ///   ==================================
    254 ///   |    C    |     Meaning          |
    255 ///   ==================================
    256 ///   |    Y    |       YES / NO       |
    257 ///   |    y    |       yes / no       |
    258 ///   |  D / d  |    Integer 0 or 1    |
    259 ///   |    T    |     TRUE / FALSE     |
    260 ///   |    t    |     true / false     |
    261 ///   | (empty) |   Equivalent to 't'  |
    262 ///   ==================================
    263 template <> struct format_provider<bool> {
    264   static void format(const bool &B, llvm::raw_ostream &Stream,
    265                      StringRef Style) {
    266     Stream << StringSwitch<const char *>(Style)
    267                   .Case("Y", B ? "YES" : "NO")
    268                   .Case("y", B ? "yes" : "no")
    269                   .CaseLower("D", B ? "1" : "0")
    270                   .Case("T", B ? "TRUE" : "FALSE")
    271                   .Cases("t", "", B ? "true" : "false")
    272                   .Default(B ? "1" : "0");
    273   }
    274 };
    275 
    276 /// Implementation of format_provider<T> for floating point types.
    277 ///
    278 /// The options string of a floating point type has the format:
    279 ///
    280 ///   float_options   :: [style][precision]
    281 ///   style           :: <see table below>
    282 ///   precision       :: <non-negative integer> 0-99
    283 ///
    284 ///   =====================================================
    285 ///   |  style  |     Meaning          |      Example     |
    286 ///   -----------------------------------------------------
    287 ///   |         |                      |  Input |  Output |
    288 ///   =====================================================
    289 ///   | P / p   | Percentage           |  0.05  |  5.00%  |
    290 ///   | F / f   | Fixed point          |   1.0  |  1.00   |
    291 ///   |   E     | Exponential with E   | 100000 | 1.0E+05 |
    292 ///   |   e     | Exponential with e   | 100000 | 1.0e+05 |
    293 ///   | (empty) | Same as F / f        |        |         |
    294 ///   =====================================================
    295 ///
    296 /// The default precision is 6 for exponential (E / e) and 2 for everything
    297 /// else.
    298 
    299 template <typename T>
    300 struct format_provider<
    301     T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
    302     : public detail::HelperFunctions {
    303   static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
    304     FloatStyle S;
    305     if (Style.consume_front("P") || Style.consume_front("p"))
    306       S = FloatStyle::Percent;
    307     else if (Style.consume_front("F") || Style.consume_front("f"))
    308       S = FloatStyle::Fixed;
    309     else if (Style.consume_front("E"))
    310       S = FloatStyle::ExponentUpper;
    311     else if (Style.consume_front("e"))
    312       S = FloatStyle::Exponent;
    313     else
    314       S = FloatStyle::Fixed;
    315 
    316     Optional<size_t> Precision = parseNumericPrecision(Style);
    317     if (!Precision.hasValue())
    318       Precision = getDefaultPrecision(S);
    319 
    320     write_double(Stream, static_cast<double>(V), S, Precision);
    321   }
    322 };
    323 
    324 namespace detail {
    325 template <typename IterT>
    326 using IterValue = typename std::iterator_traits<IterT>::value_type;
    327 
    328 template <typename IterT>
    329 struct range_item_has_provider
    330     : public std::integral_constant<
    331           bool, !uses_missing_provider<IterValue<IterT>>::value> {};
    332 }
    333 
    334 /// Implementation of format_provider<T> for ranges.
    335 ///
    336 /// This will print an arbitrary range as a delimited sequence of items.
    337 ///
    338 /// The options string of a range type has the grammar:
    339 ///
    340 ///   range_style       ::= [separator] [element_style]
    341 ///   separator         ::= "$" delimeted_expr
    342 ///   element_style     ::= "@" delimeted_expr
    343 ///   delimeted_expr    ::= "[" expr "]" | "(" expr ")" | "<" expr ">"
    344 ///   expr              ::= <any string not containing delimeter>
    345 ///
    346 /// where the separator expression is the string to insert between consecutive
    347 /// items in the range and the argument expression is the Style specification to
    348 /// be used when formatting the underlying type.  The default separator if
    349 /// unspecified is ' ' (space).  The syntax of the argument expression follows
    350 /// whatever grammar is dictated by the format provider or format adapter used
    351 /// to format the value type.
    352 ///
    353 /// Note that attempting to format an `iterator_range<T>` where no format
    354 /// provider can be found for T will result in a compile error.
    355 ///
    356 
    357 template <typename IterT> class format_provider<llvm::iterator_range<IterT>> {
    358   using value = typename std::iterator_traits<IterT>::value_type;
    359   using reference = typename std::iterator_traits<IterT>::reference;
    360 
    361   static StringRef consumeOneOption(StringRef &Style, char Indicator,
    362                                     StringRef Default) {
    363     if (Style.empty())
    364       return Default;
    365     if (Style.front() != Indicator)
    366       return Default;
    367     Style = Style.drop_front();
    368     if (Style.empty()) {
    369       assert(false && "Invalid range style");
    370       return Default;
    371     }
    372 
    373     for (const char *D : {"[]", "<>", "()"}) {
    374       if (Style.front() != D[0])
    375         continue;
    376       size_t End = Style.find_first_of(D[1]);
    377       if (End == StringRef::npos) {
    378         assert(false && "Missing range option end delimeter!");
    379         return Default;
    380       }
    381       StringRef Result = Style.slice(1, End);
    382       Style = Style.drop_front(End + 1);
    383       return Result;
    384     }
    385     assert(false && "Invalid range style!");
    386     return Default;
    387   }
    388 
    389   static std::pair<StringRef, StringRef> parseOptions(StringRef Style) {
    390     StringRef Sep = consumeOneOption(Style, '$', ", ");
    391     StringRef Args = consumeOneOption(Style, '@', "");
    392     assert(Style.empty() && "Unexpected text in range option string!");
    393     return std::make_pair(Sep, Args);
    394   }
    395 
    396 public:
    397   static_assert(detail::range_item_has_provider<IterT>::value,
    398                 "Range value_type does not have a format provider!");
    399   static void format(const llvm::iterator_range<IterT> &V,
    400                      llvm::raw_ostream &Stream, StringRef Style) {
    401     StringRef Sep;
    402     StringRef ArgStyle;
    403     std::tie(Sep, ArgStyle) = parseOptions(Style);
    404     auto Begin = V.begin();
    405     auto End = V.end();
    406     if (Begin != End) {
    407       auto Adapter =
    408           detail::build_format_adapter(std::forward<reference>(*Begin));
    409       Adapter.format(Stream, ArgStyle);
    410       ++Begin;
    411     }
    412     while (Begin != End) {
    413       Stream << Sep;
    414       auto Adapter =
    415           detail::build_format_adapter(std::forward<reference>(*Begin));
    416       Adapter.format(Stream, ArgStyle);
    417       ++Begin;
    418     }
    419   }
    420 };
    421 }
    422 
    423 #endif
    424