LLVM  4.0.0
NativeFormatting.cpp
Go to the documentation of this file.
1 //===- NativeFormatting.cpp - Low level formatting helpers -------*- 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 
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/StringExtras.h"
15 #include "llvm/Support/Format.h"
16 
17 using namespace llvm;
18 
19 template<typename T, std::size_t N>
20 static int format_to_buffer(T Value, char (&Buffer)[N]) {
21  char *EndPtr = std::end(Buffer);
22  char *CurPtr = EndPtr;
23 
24  do {
25  *--CurPtr = '0' + char(Value % 10);
26  Value /= 10;
27  } while (Value);
28  return EndPtr - CurPtr;
29 }
30 
31 static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
32  assert(!Buffer.empty());
33 
34  ArrayRef<char> ThisGroup;
35  int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
36  ThisGroup = Buffer.take_front(InitialDigits);
37  S.write(ThisGroup.data(), ThisGroup.size());
38 
39  Buffer = Buffer.drop_front(InitialDigits);
40  assert(Buffer.size() % 3 == 0);
41  while (!Buffer.empty()) {
42  S << ',';
43  ThisGroup = Buffer.take_front(3);
44  S.write(ThisGroup.data(), 3);
45  Buffer = Buffer.drop_front(3);
46  }
47 }
48 
49 template <typename T>
50 static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
51  IntegerStyle Style, bool IsNegative) {
52  static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
53 
54  char NumberBuffer[128];
55  std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
56 
57  size_t Len = 0;
58  Len = format_to_buffer(N, NumberBuffer);
59 
60  if (IsNegative)
61  S << '-';
62 
63  if (Len < MinDigits && Style != IntegerStyle::Number) {
64  for (size_t I = Len; I < MinDigits; ++I)
65  S << '0';
66  }
67 
68  if (Style == IntegerStyle::Number) {
69  writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
70  } else {
71  S.write(std::end(NumberBuffer) - Len, Len);
72  }
73 }
74 
75 template <typename T>
76 static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
77  IntegerStyle Style, bool IsNegative = false) {
78  // Output using 32-bit div/mod if possible.
79  if (N == static_cast<uint32_t>(N))
80  write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
81  IsNegative);
82  else
83  write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
84 }
85 
86 template <typename T>
87 static void write_signed(raw_ostream &S, T N, size_t MinDigits,
89  static_assert(std::is_signed<T>::value, "Value is not signed!");
90 
91  using UnsignedT = typename std::make_unsigned<T>::type;
92 
93  if (N >= 0) {
94  write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
95  return;
96  }
97 
98  UnsignedT UN = -(UnsignedT)N;
99  write_unsigned(S, UN, MinDigits, Style, true);
100 }
101 
102 void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
104  write_unsigned(S, N, MinDigits, Style);
105 }
106 
107 void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
109  write_signed(S, N, MinDigits, Style);
110 }
111 
112 void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
114  write_unsigned(S, N, MinDigits, Style);
115 }
116 
117 void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
119  write_signed(S, N, MinDigits, Style);
120 }
121 
122 void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
124  write_unsigned(S, N, MinDigits, Style);
125 }
126 
127 void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
129  write_signed(S, N, MinDigits, Style);
130 }
131 
133  Optional<size_t> Width) {
134  const size_t kMaxWidth = 128u;
135 
136  size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
137 
138  unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
139  bool Prefix = (Style == HexPrintStyle::PrefixLower ||
140  Style == HexPrintStyle::PrefixUpper);
141  bool Upper =
142  (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
143  unsigned PrefixChars = Prefix ? 2 : 0;
144  unsigned NumChars =
145  std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
146 
147  char NumberBuffer[kMaxWidth];
148  ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
149  if (Prefix)
150  NumberBuffer[1] = 'x';
151  char *EndPtr = NumberBuffer + NumChars;
152  char *CurPtr = EndPtr;
153  while (N) {
154  unsigned char x = static_cast<unsigned char>(N) % 16;
155  *--CurPtr = hexdigit(x, !Upper);
156  N /= 16;
157  }
158 
159  S.write(NumberBuffer, NumChars);
160 }
161 
163  Optional<size_t> Precision) {
164  size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
165 
166  if (std::isnan(N)) {
167  S << "nan";
168  return;
169  } else if (std::isinf(N)) {
170  S << "INF";
171  return;
172  }
173 
174  char Letter;
175  if (Style == FloatStyle::Exponent)
176  Letter = 'e';
177  else if (Style == FloatStyle::ExponentUpper)
178  Letter = 'E';
179  else
180  Letter = 'f';
181 
182  SmallString<8> Spec;
183  llvm::raw_svector_ostream Out(Spec);
184  Out << "%." << Prec << Letter;
185 
186  if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
187 #ifdef _WIN32
188 // On MSVCRT and compatible, output of %e is incompatible to Posix
189 // by default. Number of exponent digits should be at least 2. "%+03d"
190 // FIXME: Implement our formatter to here or Support/Format.h!
191 #if defined(__MINGW32__)
192  // FIXME: It should be generic to C++11.
193  if (N == 0.0 && std::signbit(N)) {
194  char NegativeZero[] = "-0.000000e+00";
195  if (Style == FloatStyle::ExponentUpper)
196  NegativeZero[strlen(NegativeZero) - 4] = 'E';
197  S << NegativeZero;
198  return;
199  }
200 #else
201  int fpcl = _fpclass(N);
202 
203  // negative zero
204  if (fpcl == _FPCLASS_NZ) {
205  char NegativeZero[] = "-0.000000e+00";
206  if (Style == FloatStyle::ExponentUpper)
207  NegativeZero[strlen(NegativeZero) - 4] = 'E';
208  S << NegativeZero;
209  return;
210  }
211 #endif
212 
213  char buf[32];
214  unsigned len;
215  len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
216  if (len <= sizeof(buf) - 2) {
217  if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
218  buf[len - 3] == '0') {
219  int cs = buf[len - 4];
220  if (cs == '+' || cs == '-') {
221  int c1 = buf[len - 2];
222  int c0 = buf[len - 1];
223  if (isdigit(static_cast<unsigned char>(c1)) &&
224  isdigit(static_cast<unsigned char>(c0))) {
225  // Trim leading '0': "...e+012" -> "...e+12\0"
226  buf[len - 3] = c1;
227  buf[len - 2] = c0;
228  buf[--len] = 0;
229  }
230  }
231  }
232  S << buf;
233  return;
234  }
235 #endif
236  }
237 
238  if (Style == FloatStyle::Percent)
239  N *= 100.0;
240 
241  char Buf[32];
242  format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
243  S << Buf;
244  if (Style == FloatStyle::Percent)
245  S << '%';
246 }
247 
250 }
251 
253  switch (Style) {
256  return 6; // Number of decimal places.
257  case FloatStyle::Fixed:
258  case FloatStyle::Percent:
259  return 2; // Number of decimal places.
260  }
261  LLVM_BUILTIN_UNREACHABLE;
262 }
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:241
static void write_unsigned(raw_ostream &S, T N, size_t MinDigits, IntegerStyle Style, bool IsNegative=false)
static void write_signed(raw_ostream &S, T N, size_t MinDigits, IntegerStyle Style)
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Definition: Optional.h:132
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:490
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the most significant bit to the least stopping at the first 1...
Definition: MathExtras.h:180
void write_double(raw_ostream &S, double D, FloatStyle Style, Optional< size_t > Precision=None)
size_t getDefaultPrecision(FloatStyle Style)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
bool isPrefixedHexStyle(HexPrintStyle S)
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:141
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition: ArrayRef.h:204
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:136
raw_ostream & write(unsigned char C)
constexpr size_t array_lengthof(T(&)[N])
Find the length of an array.
Definition: STLExtras.h:649
static char hexdigit(unsigned X, bool LowerCase=false)
hexdigit - Return the hexadecimal character for the given number X (which should be less than 16)...
Definition: StringExtras.h:27
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, Optional< size_t > Width=None)
static int format_to_buffer(T Value, char(&Buffer)[N])
const char * c_str()
Definition: SmallString.h:270
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
static void writeWithCommas(raw_ostream &S, ArrayRef< char > Buffer)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition: ArrayRef.h:180
LLVM Value Representation.
Definition: Value.h:71
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
void write_integer(raw_ostream &S, unsigned int N, size_t MinDigits, IntegerStyle Style)
static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits, IntegerStyle Style, bool IsNegative)