Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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