[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / include / llvm / Support / FormatProviders.h
blob629a4845716a42b9405e5255b01e88c255f46c4d
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.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_SUPPORT_FORMATPROVIDERS_H
15 #define LLVM_SUPPORT_FORMATPROVIDERS_H
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/Support/FormatVariadicDetails.h"
22 #include "llvm/Support/NativeFormatting.h"
24 #include <type_traits>
25 #include <vector>
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> {};
36 template <typename T>
37 struct use_char_formatter
38 : public std::integral_constant<bool, std::is_same<T, char>::value> {};
40 template <typename T>
41 struct is_cstring
42 : public std::integral_constant<bool,
43 is_one_of<T, char *, const char *>::value> {
46 template <typename T>
47 struct use_string_formatter
48 : public std::integral_constant<bool,
49 std::is_convertible<T, llvm::StringRef>::value> {};
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> {};
56 template <typename T>
57 struct use_double_formatter
58 : public std::integral_constant<bool, std::is_floating_point<T>::value> {};
60 class HelperFunctions {
61 protected:
62 static Optional<size_t> parseNumericPrecision(StringRef Str) {
63 size_t Prec;
64 Optional<size_t> Result;
65 if (Str.empty())
66 Result = None;
67 else if (Str.getAsInteger(10, Prec)) {
68 assert(false && "Invalid precision specifier");
69 Result = None;
70 } else {
71 assert(Prec < 100 && "Precision out of range");
72 Result = std::min<size_t>(99u, Prec);
74 return Result;
77 static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
78 if (!Str.startswith_lower("x"))
79 return false;
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;
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;
102 /// Implementation of format_provider<T> for integral arithmetic types.
104 /// The options string of an integral type has the grammar:
106 /// integer_options :: [style][digits]
107 /// style :: <see table below>
108 /// digits :: <non-negative integer> 0-99
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 /// ==========================================================================
125 template <typename T>
126 struct format_provider<
127 T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
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;
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;
146 Style.consumeInteger(10, Digits);
147 assert(Style.empty() && "Invalid integral format style!");
148 write_integer(Stream, V, Digits, IS);
152 /// Implementation of format_provider<T> for integral pointer types.
154 /// The options string of a pointer type has the grammar:
156 /// pointer_options :: [style][precision]
157 /// style :: <see table below>
158 /// digits :: <non-negative integer> 0-sizeof(void*)
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 /// ==========================================================================
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, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
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);
188 /// Implementation of format_provider<T> for c-style strings and string
189 /// objects such as std::string and llvm::StringRef.
191 /// The options string of a string type has the grammar:
193 /// string_options :: [length]
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.
199 template <typename T>
200 struct format_provider<
201 T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> {
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");
207 llvm::StringRef S = V;
208 Stream << S.substr(0, N);
212 /// Implementation of format_provider<T> for llvm::Twine.
214 /// This follows the same rules as the string formatter.
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);
223 /// Implementation of format_provider<T> for characters.
225 /// The options string of a character type has the grammar:
227 /// char_options :: (empty) | [integer_options]
229 /// If `char_options` is empty, the character is displayed as an ASCII
230 /// character. Otherwise, it is treated as an integer options string.
232 template <typename T>
233 struct format_provider<
234 T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
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);
246 /// Implementation of format_provider<T> for type `bool`
248 /// The options string of a boolean type has the grammar:
250 /// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
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");
275 /// Implementation of format_provider<T> for floating point types.
277 /// The options string of a floating point type has the format:
279 /// float_options :: [style][precision]
280 /// style :: <see table below>
281 /// precision :: <non-negative integer> 0-99
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 /// =====================================================
295 /// The default precision is 6 for exponential (E / e) and 2 for everything
296 /// else.
298 template <typename T>
299 struct format_provider<
300 T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
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;
315 Optional<size_t> Precision = parseNumericPrecision(Style);
316 if (!Precision.hasValue())
317 Precision = getDefaultPrecision(S);
319 write_double(Stream, static_cast<double>(V), S, Precision);
323 namespace detail {
324 template <typename IterT>
325 using IterValue = typename std::iterator_traits<IterT>::value_type;
327 template <typename IterT>
328 struct range_item_has_provider
329 : public std::integral_constant<
330 bool, !uses_missing_provider<IterValue<IterT>>::value> {};
333 /// Implementation of format_provider<T> for ranges.
335 /// This will print an arbitrary range as a delimited sequence of items.
337 /// The options string of a range type has the grammar:
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>
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.
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.
356 template <typename IterT> class format_provider<llvm::iterator_range<IterT>> {
357 using value = typename std::iterator_traits<IterT>::value_type;
358 using reference = typename std::iterator_traits<IterT>::reference;
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;
372 for (const char *D : {"[]", "<>", "()"}) {
373 if (Style.front() != D[0])
374 continue;
375 size_t End = Style.find_first_of(D[1]);
376 if (End == StringRef::npos) {
377 assert(false && "Missing range option end delimeter!");
378 return Default;
380 StringRef Result = Style.slice(1, End);
381 Style = Style.drop_front(End + 1);
382 return Result;
384 assert(false && "Invalid range style!");
385 return Default;
388 static std::pair<StringRef, StringRef> parseOptions(StringRef Style) {
389 StringRef Sep = consumeOneOption(Style, '$', ", ");
390 StringRef Args = consumeOneOption(Style, '@', "");
391 assert(Style.empty() && "Unexpected text in range option string!");
392 return std::make_pair(Sep, Args);
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(Sep, ArgStyle) = parseOptions(Style);
403 auto Begin = V.begin();
404 auto End = V.end();
405 if (Begin != End) {
406 auto Adapter =
407 detail::build_format_adapter(std::forward<reference>(*Begin));
408 Adapter.format(Stream, ArgStyle);
409 ++Begin;
411 while (Begin != End) {
412 Stream << Sep;
413 auto Adapter =
414 detail::build_format_adapter(std::forward<reference>(*Begin));
415 Adapter.format(Stream, ArgStyle);
416 ++Begin;
422 #endif