LLVM  10.0.0svn
FormatProviders.h
Go to the documentation of this file.
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/Optional.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/ADT/Twine.h"
23 
24 #include <type_traits>
25 #include <vector>
26 
27 namespace llvm {
28 namespace detail {
29 template <typename T>
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>
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>
48  : public std::integral_constant<bool,
49  std::is_convertible<T, llvm::StringRef>::value> {};
50 
51 template <typename T>
53  : public std::integral_constant<bool, std::is_pointer<T>::value &&
54  !is_cstring<T>::value> {};
55 
56 template <typename T>
58  : public std::integral_constant<bool, std::is_floating_point<T>::value> {};
59 
61 protected:
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);
73  }
74  return Result;
75  }
76 
78  if (!Str.startswith_lower("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"))
87  else if (Str.consume_front("X+") || Str.consume_front("X"))
89  return true;
90  }
91 
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>
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) {
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 
141  if (Style.consume_front("N") || Style.consume_front("n"))
143  else if (Style.consume_front("D") || Style.consume_front("d"))
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>
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) {
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>
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");
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) {
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>
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);
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>
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"))
306  else if (Style.consume_front("F") || Style.consume_front("f"))
307  S = FloatStyle::Fixed;
308  else if (Style.consume_front("E"))
310  else if (Style.consume_front("e"))
312  else
313  S = FloatStyle::Fixed;
314 
315  Optional<size_t> Precision = parseNumericPrecision(Style);
316  if (!Precision.hasValue())
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>
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  using reference = typename std::iterator_traits<IterT>::reference;
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 : {"[]", "<>", "()"}) {
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;
379  }
380  StringRef Result = Style.slice(1, End);
381  Style = Style.drop_front(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, '$', ", ");
390  StringRef Args = consumeOneOption(Style, '@', "");
391  assert(Style.empty() && "Unexpected text in range option string!");
392  return std::make_pair(Sep, Args);
393  }
394 
395 public:
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;
410  }
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;
417  }
418  }
419 };
420 }
421 
422 #endif
const NoneType None
Definition: None.h:23
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
LLVM_NODISCARD bool startswith_lower(StringRef Prefix) const
Check if this string starts with the given Prefix, ignoring case.
Definition: StringRef.cpp:46
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:663
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
static void format(const bool &B, llvm::raw_ostream &Stream, StringRef Style)
static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style)
void write_double(raw_ostream &S, double D, FloatStyle Style, Optional< size_t > Precision=None)
Definition: BitVector.h:937
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
LLVM_NODISCARD StringRef drop_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the first N elements dropped.
Definition: StringRef.h:634
LLVM_NODISCARD StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:693
size_t getDefaultPrecision(FloatStyle Style)
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:592
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:140
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:526
bool isPrefixedHexStyle(HexPrintStyle S)
static void format(const char &V, llvm::raw_ostream &Stream, StringRef Style)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:492
static void format(const llvm::iterator_range< IterT > &V, llvm::raw_ostream &Stream, StringRef Style)
static void format(const Twine &V, llvm::raw_ostream &Stream, StringRef Style)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
A range adaptor for a pair of iterators.
typename std::iterator_traits< IterT >::value_type IterValue
bool hasValue() const
Definition: Optional.h:259
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, Optional< size_t > Width=None)
static const size_t npos
Definition: StringRef.h:50
LLVM_NODISCARD size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition: StringRef.h:394
#define N
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM_NODISCARD char front() const
front - Get the first character in the string.
Definition: StringRef.h:148
std::enable_if< uses_format_member< T >::value, T >::type build_format_adapter(T &&Item)
IteratorT begin() const
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
static Optional< size_t > parseNumericPrecision(StringRef Str)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
void write_integer(raw_ostream &S, unsigned int N, size_t MinDigits, IntegerStyle Style)
IteratorT end() const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style, size_t Default)