| 1 | //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===// | 
| 2 | // | 
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
| 4 | // See https://llvm.org/LICENSE.txt for license information. | 
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| 6 | // | 
| 7 | //===----------------------------------------------------------------------===// | 
| 8 | // | 
| 9 | // This file implements format providers for many common LLVM types, for example | 
| 10 | // allowing precision and width specifiers for scalar and string types. | 
| 11 | // | 
| 12 | //===----------------------------------------------------------------------===// | 
| 13 |  | 
| 14 | #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H | 
| 15 | #define LLVM_SUPPORT_FORMATPROVIDERS_H | 
| 16 |  | 
| 17 | #include "llvm/ADT/STLExtras.h" | 
| 18 | #include "llvm/ADT/StringSwitch.h" | 
| 19 | #include "llvm/ADT/Twine.h" | 
| 20 | #include "llvm/Support/FormatVariadicDetails.h" | 
| 21 | #include "llvm/Support/NativeFormatting.h" | 
| 22 |  | 
| 23 | #include <array> | 
| 24 | #include <optional> | 
| 25 | #include <type_traits> | 
| 26 |  | 
| 27 | namespace llvm { | 
| 28 | namespace detail { | 
| 29 | template <typename T> | 
| 30 | struct use_integral_formatter | 
| 31 |     : public std::integral_constant< | 
| 32 |           bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t, | 
| 33 |                           int64_t, uint64_t, int, unsigned, long, unsigned long, | 
| 34 |                           long long, unsigned long long>::value> {}; | 
| 35 |  | 
| 36 | template <typename T> | 
| 37 | struct use_char_formatter | 
| 38 |     : public std::integral_constant<bool, std::is_same_v<T, char>> {}; | 
| 39 |  | 
| 40 | template <typename T> | 
| 41 | struct is_cstring | 
| 42 |     : public std::integral_constant<bool, | 
| 43 |                                     is_one_of<T, char *, const char *>::value> { | 
| 44 | }; | 
| 45 |  | 
| 46 | template <typename T> | 
| 47 | struct use_string_formatter | 
| 48 |     : public std::integral_constant<bool, | 
| 49 |                                     std::is_convertible_v<T, llvm::StringRef>> { | 
| 50 | }; | 
| 51 |  | 
| 52 | template <typename T> | 
| 53 | struct use_pointer_formatter | 
| 54 |     : public std::integral_constant<bool, std::is_pointer_v<T> && | 
| 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_v<T>> {}; | 
| 60 |  | 
| 61 | class HelperFunctions { | 
| 62 | protected: | 
| 63 |   static std::optional<size_t> parseNumericPrecision(StringRef Str) { | 
| 64 |     size_t Prec; | 
| 65 |     std::optional<size_t> Result; | 
| 66 |     if (Str.empty()) | 
| 67 |       Result = std::nullopt; | 
| 68 |     else if (Str.getAsInteger(Radix: 10, Result&: Prec)) { | 
| 69 |       assert(false && "Invalid precision specifier" ); | 
| 70 |       Result = std::nullopt; | 
| 71 |     } else { | 
| 72 |       assert(Prec < 100 && "Precision out of range" ); | 
| 73 |       Result = std::min<size_t>(a: 99u, b: Prec); | 
| 74 |     } | 
| 75 |     return Result; | 
| 76 |   } | 
| 77 |  | 
| 78 |   static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) { | 
| 79 |     if (!Str.starts_with_insensitive(Prefix: "x" )) | 
| 80 |       return false; | 
| 81 |  | 
| 82 |     if (Str.consume_front(Prefix: "x-" )) | 
| 83 |       Style = HexPrintStyle::Lower; | 
| 84 |     else if (Str.consume_front(Prefix: "X-" )) | 
| 85 |       Style = HexPrintStyle::Upper; | 
| 86 |     else if (Str.consume_front(Prefix: "x+" ) || Str.consume_front(Prefix: "x" )) | 
| 87 |       Style = HexPrintStyle::PrefixLower; | 
| 88 |     else if (Str.consume_front(Prefix: "X+" ) || Str.consume_front(Prefix: "X" )) | 
| 89 |       Style = HexPrintStyle::PrefixUpper; | 
| 90 |     return true; | 
| 91 |   } | 
| 92 |  | 
| 93 |   static size_t (StringRef &Str, HexPrintStyle Style, | 
| 94 |                                     size_t Default) { | 
| 95 |     Str.consumeInteger(Radix: 10, Result&: Default); | 
| 96 |     if (isPrefixedHexStyle(S: 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, std::enable_if_t<detail::use_integral_formatter<T>::value>> | 
| 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(Str&: Style, Style&: HS)) { | 
| 136 |       Digits = consumeNumHexDigits(Str&: Style, Style: HS, Default: 0); | 
| 137 |       write_hex(Stream, V, HS, Digits); | 
| 138 |       return; | 
| 139 |     } | 
| 140 |  | 
| 141 |     IntegerStyle IS = IntegerStyle::Integer; | 
| 142 |     if (Style.consume_front(Prefix: "N" ) || Style.consume_front(Prefix: "n" )) | 
| 143 |       IS = IntegerStyle::Number; | 
| 144 |     else if (Style.consume_front(Prefix: "D" ) || Style.consume_front(Prefix: "d" )) | 
| 145 |       IS = IntegerStyle::Integer; | 
| 146 |  | 
| 147 |     Style.consumeInteger(Radix: 10, Result&: 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, std::enable_if_t<detail::use_pointer_formatter<T>::value>> | 
| 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(Str&: Style, Style&: HS); | 
| 184 |     size_t Digits = consumeNumHexDigits(Str&: Style, Style: HS, Default: sizeof(void *) * 2); | 
| 185 |     write_hex(S&: Stream, N: reinterpret_cast<std::uintptr_t>(V), Style: HS, Width: 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, std::enable_if_t<detail::use_string_formatter<T>::value>> { | 
| 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(Radix: 10, Result&: N)) { | 
| 206 |       assert(false && "Style is not a valid integer" ); | 
| 207 |     } | 
| 208 |     llvm::StringRef S = V; | 
| 209 |     Stream << S.substr(Start: 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: 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<T, | 
| 235 |                        std::enable_if_t<detail::use_char_formatter<T>::value>> { | 
| 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(V: 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(S: "Y" , Value: B ? "YES"  : "NO" ) | 
| 268 |                   .Case(S: "y" , Value: B ? "yes"  : "no" ) | 
| 269 |                   .CaseLower(S: "D" , Value: B ? "1"  : "0" ) | 
| 270 |                   .Case(S: "T" , Value: B ? "TRUE"  : "FALSE" ) | 
| 271 |                   .Cases(S0: "t" , S1: "" , Value: B ? "true"  : "false" ) | 
| 272 |                   .Default(Value: 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<T, | 
| 301 |                        std::enable_if_t<detail::use_double_formatter<T>::value>> | 
| 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(Prefix: "P" ) || Style.consume_front(Prefix: "p" )) | 
| 306 |       S = FloatStyle::Percent; | 
| 307 |     else if (Style.consume_front(Prefix: "F" ) || Style.consume_front(Prefix: "f" )) | 
| 308 |       S = FloatStyle::Fixed; | 
| 309 |     else if (Style.consume_front(Prefix: "E" )) | 
| 310 |       S = FloatStyle::ExponentUpper; | 
| 311 |     else if (Style.consume_front(Prefix: "e" )) | 
| 312 |       S = FloatStyle::Exponent; | 
| 313 |     else | 
| 314 |       S = FloatStyle::Fixed; | 
| 315 |  | 
| 316 |     std::optional<size_t> Precision = parseNumericPrecision(Str: Style); | 
| 317 |     if (!Precision) | 
| 318 |       Precision = getDefaultPrecision(Style: S); | 
| 319 |  | 
| 320 |     write_double(S&: Stream, D: static_cast<double>(V), Style: 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 |  | 
| 360 |   static StringRef consumeOneOption(StringRef &Style, char Indicator, | 
| 361 |                                     StringRef Default) { | 
| 362 |     if (Style.empty()) | 
| 363 |       return Default; | 
| 364 |     if (Style.front() != Indicator) | 
| 365 |       return Default; | 
| 366 |     Style = Style.drop_front(); | 
| 367 |     if (Style.empty()) { | 
| 368 |       assert(false && "Invalid range style" ); | 
| 369 |       return Default; | 
| 370 |     } | 
| 371 |  | 
| 372 |     for (const char *D : std::array<const char *, 3>{"[]" , "<>" , "()" }) { | 
| 373 |       if (Style.front() != D[0]) | 
| 374 |         continue; | 
| 375 |       size_t End = Style.find_first_of(C: D[1]); | 
| 376 |       if (End == StringRef::npos) { | 
| 377 |         assert(false && "Missing range option end delimeter!" ); | 
| 378 |         return Default; | 
| 379 |       } | 
| 380 |       StringRef Result = Style.slice(Start: 1, End); | 
| 381 |       Style = Style.drop_front(N: End + 1); | 
| 382 |       return Result; | 
| 383 |     } | 
| 384 |     assert(false && "Invalid range style!" ); | 
| 385 |     return Default; | 
| 386 |   } | 
| 387 |  | 
| 388 |   static std::pair<StringRef, StringRef> parseOptions(StringRef Style) { | 
| 389 |     StringRef Sep = consumeOneOption(Style, Indicator: '$', Default: ", " ); | 
| 390 |     StringRef Args = consumeOneOption(Style, Indicator: '@', Default: "" ); | 
| 391 |     assert(Style.empty() && "Unexpected text in range option string!" ); | 
| 392 |     return std::make_pair(x&: Sep, y&: Args); | 
| 393 |   } | 
| 394 |  | 
| 395 | public: | 
| 396 |   static_assert(detail::range_item_has_provider<IterT>::value, | 
| 397 |                 "Range value_type does not have a format provider!" ); | 
| 398 |   static void format(const llvm::iterator_range<IterT> &V, | 
| 399 |                      llvm::raw_ostream &Stream, StringRef Style) { | 
| 400 |     StringRef Sep; | 
| 401 |     StringRef ArgStyle; | 
| 402 |     std::tie(args&: Sep, args&: ArgStyle) = parseOptions(Style); | 
| 403 |     auto Begin = V.begin(); | 
| 404 |     auto End = V.end(); | 
| 405 |     if (Begin != End) { | 
| 406 |       auto Adapter = detail::build_format_adapter(*Begin); | 
| 407 |       Adapter.format(Stream, ArgStyle); | 
| 408 |       ++Begin; | 
| 409 |     } | 
| 410 |     while (Begin != End) { | 
| 411 |       Stream << Sep; | 
| 412 |       auto Adapter = detail::build_format_adapter(*Begin); | 
| 413 |       Adapter.format(Stream, ArgStyle); | 
| 414 |       ++Begin; | 
| 415 |     } | 
| 416 |   } | 
| 417 | }; | 
| 418 | } | 
| 419 |  | 
| 420 | #endif | 
| 421 |  |