/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 | } |