Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/llvm/lib/Support/NativeFormatting.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- NativeFormatting.cpp - Low level formatting helpers -------*- 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
#include "llvm/Support/NativeFormatting.h"
10
#include "llvm/ADT/ArrayRef.h"
11
#include "llvm/ADT/SmallString.h"
12
#include "llvm/ADT/StringExtras.h"
13
#include "llvm/Support/Format.h"
14
#include "llvm/Support/raw_ostream.h"
15
#include <float.h>
16
17
using namespace llvm;
18
19
template<typename T, std::size_t N>
20
36
static int format_to_buffer(T Value, char (&Buffer)[N]) {
21
36
  char *EndPtr = std::end(Buffer);
22
36
  char *CurPtr = EndPtr;
23
36
24
36
  do {
25
36
    *--CurPtr = '0' + char(Value % 10);
26
36
    Value /= 10;
27
36
  } while (Value);
28
36
  return EndPtr - CurPtr;
29
36
}
NativeFormatting.cpp:_ZL16format_to_bufferIjLm128EEiT_RAT0__c
Line
Count
Source
20
36
static int format_to_buffer(T Value, char (&Buffer)[N]) {
21
36
  char *EndPtr = std::end(Buffer);
22
36
  char *CurPtr = EndPtr;
23
36
24
36
  do {
25
36
    *--CurPtr = '0' + char(Value % 10);
26
36
    Value /= 10;
27
36
  } while (Value);
28
36
  return EndPtr - CurPtr;
29
36
}
Unexecuted instantiation: NativeFormatting.cpp:_ZL16format_to_bufferImLm128EEiT_RAT0__c
Unexecuted instantiation: NativeFormatting.cpp:_ZL16format_to_bufferIyLm128EEiT_RAT0__c
30
31
0
static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
32
0
  assert(!Buffer.empty());
33
0
34
0
  ArrayRef<char> ThisGroup;
35
0
  int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
36
0
  ThisGroup = Buffer.take_front(InitialDigits);
37
0
  S.write(ThisGroup.data(), ThisGroup.size());
38
0
39
0
  Buffer = Buffer.drop_front(InitialDigits);
40
0
  assert(Buffer.size() % 3 == 0);
41
0
  while (!Buffer.empty()) {
42
0
    S << ',';
43
0
    ThisGroup = Buffer.take_front(3);
44
0
    S.write(ThisGroup.data(), 3);
45
0
    Buffer = Buffer.drop_front(3);
46
0
  }
47
0
}
48
49
template <typename T>
50
static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
51
36
                                IntegerStyle Style, bool IsNegative) {
52
36
  static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
53
36
54
36
  char NumberBuffer[128];
55
36
  std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
56
36
57
36
  size_t Len = 0;
58
36
  Len = format_to_buffer(N, NumberBuffer);
59
36
60
36
  if (IsNegative)
61
0
    S << '-';
62
36
63
36
  if (Len < MinDigits && Style != IntegerStyle::Number) {
64
0
    for (size_t I = Len; I < MinDigits; ++I)
65
0
      S << '0';
66
0
  }
67
36
68
36
  if (Style == IntegerStyle::Number) {
69
0
    writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
70
36
  } else {
71
36
    S.write(std::end(NumberBuffer) - Len, Len);
72
36
  }
73
36
}
NativeFormatting.cpp:_ZL19write_unsigned_implIjEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleEb
Line
Count
Source
51
36
                                IntegerStyle Style, bool IsNegative) {
52
36
  static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
53
36
54
36
  char NumberBuffer[128];
55
36
  std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
56
36
57
36
  size_t Len = 0;
58
36
  Len = format_to_buffer(N, NumberBuffer);
59
36
60
36
  if (IsNegative)
61
0
    S << '-';
62
36
63
36
  if (Len < MinDigits && Style != IntegerStyle::Number) {
64
0
    for (size_t I = Len; I < MinDigits; ++I)
65
0
      S << '0';
66
0
  }
67
36
68
36
  if (Style == IntegerStyle::Number) {
69
0
    writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
70
36
  } else {
71
36
    S.write(std::end(NumberBuffer) - Len, Len);
72
36
  }
73
36
}
Unexecuted instantiation: NativeFormatting.cpp:_ZL19write_unsigned_implImEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleEb
Unexecuted instantiation: NativeFormatting.cpp:_ZL19write_unsigned_implIyEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleEb
74
75
template <typename T>
76
static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
77
36
                           IntegerStyle Style, bool IsNegative = false) {
78
36
  // Output using 32-bit div/mod if possible.
79
36
  if (N == static_cast<uint32_t>(N))
80
36
    write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
81
36
                        IsNegative);
82
0
  else
83
0
    write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
84
36
}
Unexecuted instantiation: NativeFormatting.cpp:_ZL14write_unsignedIjEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleEb
NativeFormatting.cpp:_ZL14write_unsignedImEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleEb
Line
Count
Source
77
36
                           IntegerStyle Style, bool IsNegative = false) {
78
36
  // Output using 32-bit div/mod if possible.
79
36
  if (N == static_cast<uint32_t>(N))
80
36
    write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
81
36
                        IsNegative);
82
0
  else
83
0
    write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
84
36
}
Unexecuted instantiation: NativeFormatting.cpp:_ZL14write_unsignedIyEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleEb
85
86
template <typename T>
87
static void write_signed(raw_ostream &S, T N, size_t MinDigits,
88
36
                         IntegerStyle Style) {
89
36
  static_assert(std::is_signed<T>::value, "Value is not signed!");
90
36
91
36
  using UnsignedT = std::make_unsigned_t<T>;
92
36
93
36
  if (N >= 0) {
94
36
    write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
95
36
    return;
96
36
  }
97
0
98
0
  UnsignedT UN = -(UnsignedT)N;
99
0
  write_unsigned(S, UN, MinDigits, Style, true);
100
0
}
Unexecuted instantiation: NativeFormatting.cpp:_ZL12write_signedIiEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleE
NativeFormatting.cpp:_ZL12write_signedIlEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleE
Line
Count
Source
88
36
                         IntegerStyle Style) {
89
36
  static_assert(std::is_signed<T>::value, "Value is not signed!");
90
36
91
36
  using UnsignedT = std::make_unsigned_t<T>;
92
36
93
36
  if (N >= 0) {
94
36
    write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
95
36
    return;
96
36
  }
97
0
98
0
  UnsignedT UN = -(UnsignedT)N;
99
0
  write_unsigned(S, UN, MinDigits, Style, true);
100
0
}
Unexecuted instantiation: NativeFormatting.cpp:_ZL12write_signedIxEvRN4llvm11raw_ostreamET_mNS0_12IntegerStyleE
101
102
void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
103
0
                         IntegerStyle Style) {
104
0
  write_unsigned(S, N, MinDigits, Style);
105
0
}
106
107
void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
108
0
                         IntegerStyle Style) {
109
0
  write_signed(S, N, MinDigits, Style);
110
0
}
111
112
void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
113
0
                         IntegerStyle Style) {
114
0
  write_unsigned(S, N, MinDigits, Style);
115
0
}
116
117
void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
118
36
                         IntegerStyle Style) {
119
36
  write_signed(S, N, MinDigits, Style);
120
36
}
121
122
void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
123
0
                         IntegerStyle Style) {
124
0
  write_unsigned(S, N, MinDigits, Style);
125
0
}
126
127
void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
128
0
                         IntegerStyle Style) {
129
0
  write_signed(S, N, MinDigits, Style);
130
0
}
131
132
void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
133
0
                     Optional<size_t> Width) {
134
0
  const size_t kMaxWidth = 128u;
135
0
136
0
  size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
137
0
138
0
  unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
139
0
  bool Prefix = (Style == HexPrintStyle::PrefixLower ||
140
0
                 Style == HexPrintStyle::PrefixUpper);
141
0
  bool Upper =
142
0
      (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
143
0
  unsigned PrefixChars = Prefix ? 2 : 0;
144
0
  unsigned NumChars =
145
0
      std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
146
0
147
0
  char NumberBuffer[kMaxWidth];
148
0
  ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
149
0
  if (Prefix)
150
0
    NumberBuffer[1] = 'x';
151
0
  char *EndPtr = NumberBuffer + NumChars;
152
0
  char *CurPtr = EndPtr;
153
0
  while (N) {
154
0
    unsigned char x = static_cast<unsigned char>(N) % 16;
155
0
    *--CurPtr = hexdigit(x, !Upper);
156
0
    N /= 16;
157
0
  }
158
0
159
0
  S.write(NumberBuffer, NumChars);
160
0
}
161
162
void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
163
0
                        Optional<size_t> Precision) {
164
0
  size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
165
0
166
0
  if (std::isnan(N)) {
167
0
    S << "nan";
168
0
    return;
169
0
  } else if (std::isinf(N)) {
170
0
    S << "INF";
171
0
    return;
172
0
  }
173
0
174
0
  char Letter;
175
0
  if (Style == FloatStyle::Exponent)
176
0
    Letter = 'e';
177
0
  else if (Style == FloatStyle::ExponentUpper)
178
0
    Letter = 'E';
179
0
  else
180
0
    Letter = 'f';
181
0
182
0
  SmallString<8> Spec;
183
0
  llvm::raw_svector_ostream Out(Spec);
184
0
  Out << "%." << Prec << Letter;
185
0
186
0
  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
0
238
0
  if (Style == FloatStyle::Percent)
239
0
    N *= 100.0;
240
0
241
0
  char Buf[32];
242
0
  format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
243
0
  S << Buf;
244
0
  if (Style == FloatStyle::Percent)
245
0
    S << '%';
246
0
}
247
248
0
bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
249
0
  return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
250
0
}
251
252
0
size_t llvm::getDefaultPrecision(FloatStyle Style) {
253
0
  switch (Style) {
254
0
  case FloatStyle::Exponent:
255
0
  case FloatStyle::ExponentUpper:
256
0
    return 6; // Number of decimal places.
257
0
  case FloatStyle::Fixed:
258
0
  case FloatStyle::Percent:
259
0
    return 2; // Number of decimal places.
260
0
  }
261
0
  LLVM_BUILTIN_UNREACHABLE;
262
0
}