/src/keystone/llvm/lib/Support/raw_ostream.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===// |
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 | | // |
10 | | // This implements support for bulk buffered stream output. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/Support/raw_ostream.h" |
15 | | #include "llvm/ADT/STLExtras.h" |
16 | | #include "llvm/ADT/SmallVector.h" |
17 | | #include "llvm/ADT/StringExtras.h" |
18 | | #include "llvm/Config/config.h" |
19 | | #include "llvm/Support/Compiler.h" |
20 | | #include "llvm/Support/ErrorHandling.h" |
21 | | #include "llvm/Support/FileSystem.h" |
22 | | #include "llvm/Support/Format.h" |
23 | | #include "llvm/Support/MathExtras.h" |
24 | | #include <cctype> |
25 | | #include <cerrno> |
26 | | #include <sys/stat.h> |
27 | | #include <system_error> |
28 | | |
29 | | // <fcntl.h> may provide O_BINARY. |
30 | | #if defined(HAVE_FCNTL_H) |
31 | | # include <fcntl.h> |
32 | | #endif |
33 | | |
34 | | #if defined(HAVE_UNISTD_H) |
35 | | # include <unistd.h> |
36 | | #endif |
37 | | #if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV) |
38 | | # include <sys/uio.h> |
39 | | #endif |
40 | | |
41 | | #if defined(__CYGWIN__) |
42 | | #include <io.h> |
43 | | #endif |
44 | | |
45 | | #if defined(_MSC_VER) |
46 | | #include <io.h> |
47 | | #ifndef STDIN_FILENO |
48 | | # define STDIN_FILENO 0 |
49 | | #endif |
50 | | #ifndef STDOUT_FILENO |
51 | | # define STDOUT_FILENO 1 |
52 | | #endif |
53 | | #ifndef STDERR_FILENO |
54 | | # define STDERR_FILENO 2 |
55 | | #endif |
56 | | #endif |
57 | | |
58 | | #ifdef LLVM_ON_WIN32 |
59 | | #include "Windows/WindowsSupport.h" |
60 | | #endif |
61 | | |
62 | | using namespace llvm_ks; |
63 | | |
64 | 3.96M | raw_ostream::~raw_ostream() { |
65 | | // raw_ostream's subclasses should take care to flush the buffer |
66 | | // in their destructors. |
67 | 3.96M | assert(OutBufCur == OutBufStart && |
68 | 3.96M | "raw_ostream destructor called with non-empty buffer!"); |
69 | | |
70 | 3.96M | if (BufferMode == InternalBuffer) |
71 | 1 | delete [] OutBufStart; |
72 | 3.96M | } |
73 | | |
74 | | // An out of line virtual method to provide a home for the class vtable. |
75 | 0 | void raw_ostream::handle() {} |
76 | | |
77 | 1 | size_t raw_ostream::preferred_buffer_size() const { |
78 | | // BUFSIZ is intended to be a reasonable default. |
79 | 1 | return BUFSIZ; |
80 | 1 | } |
81 | | |
82 | 1 | void raw_ostream::SetBuffered() { |
83 | | // Ask the subclass to determine an appropriate buffer size. |
84 | 1 | if (size_t Size = preferred_buffer_size()) |
85 | 1 | SetBufferSize(Size); |
86 | 0 | else |
87 | | // It may return 0, meaning this stream should be unbuffered. |
88 | 0 | SetUnbuffered(); |
89 | 1 | } |
90 | | |
91 | | void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, |
92 | 3.96M | BufferKind Mode) { |
93 | 3.96M | assert(((Mode == Unbuffered && !BufferStart && Size == 0) || |
94 | 3.96M | (Mode != Unbuffered && BufferStart && Size != 0)) && |
95 | 3.96M | "stream must be unbuffered or have at least one byte"); |
96 | | // Make sure the current buffer is free of content (we can't flush here; the |
97 | | // child buffer management logic will be in write_impl). |
98 | 3.96M | assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!"); |
99 | | |
100 | 3.96M | if (BufferMode == InternalBuffer) |
101 | 3.96M | delete [] OutBufStart; |
102 | 3.96M | OutBufStart = BufferStart; |
103 | 3.96M | OutBufEnd = OutBufStart+Size; |
104 | 3.96M | OutBufCur = OutBufStart; |
105 | 3.96M | BufferMode = Mode; |
106 | | |
107 | 3.96M | assert(OutBufStart <= OutBufEnd && "Invalid size!"); |
108 | 3.96M | } |
109 | | |
110 | 3.33M | raw_ostream &raw_ostream::operator<<(unsigned long N) { |
111 | | // Zero is a special case. |
112 | 3.33M | if (N == 0) |
113 | 488k | return *this << '0'; |
114 | | |
115 | 2.84M | char NumberBuffer[20]; |
116 | 2.84M | char *EndPtr = NumberBuffer+sizeof(NumberBuffer); |
117 | 2.84M | char *CurPtr = EndPtr; |
118 | | |
119 | 8.53M | while (N) { |
120 | 5.68M | *--CurPtr = '0' + char(N % 10); |
121 | 5.68M | N /= 10; |
122 | 5.68M | } |
123 | 2.84M | return write(CurPtr, EndPtr-CurPtr); |
124 | 3.33M | } |
125 | | |
126 | 2.05M | raw_ostream &raw_ostream::operator<<(long N) { |
127 | 2.05M | if (N < 0) { |
128 | 9.89k | *this << '-'; |
129 | | // Avoid undefined behavior on LONG_MIN with a cast. |
130 | 9.89k | N = -(unsigned long)N; |
131 | 9.89k | } |
132 | | |
133 | 2.05M | return this->operator<<(static_cast<unsigned long>(N)); |
134 | 2.05M | } |
135 | | |
136 | 3 | raw_ostream &raw_ostream::operator<<(unsigned long long N) { |
137 | | // Output using 32-bit div/mod when possible. |
138 | 3 | if (N == static_cast<unsigned long>(N)) |
139 | 3 | return this->operator<<(static_cast<unsigned long>(N)); |
140 | | |
141 | 0 | char NumberBuffer[20]; |
142 | 0 | char *EndPtr = std::end(NumberBuffer); |
143 | 0 | char *CurPtr = EndPtr; |
144 | |
|
145 | 0 | while (N) { |
146 | 0 | *--CurPtr = '0' + char(N % 10); |
147 | 0 | N /= 10; |
148 | 0 | } |
149 | 0 | return write(CurPtr, EndPtr-CurPtr); |
150 | 3 | } |
151 | | |
152 | 3 | raw_ostream &raw_ostream::operator<<(long long N) { |
153 | 3 | if (N < 0) { |
154 | 2 | *this << '-'; |
155 | | // Avoid undefined behavior on INT64_MIN with a cast. |
156 | 2 | N = -(unsigned long long)N; |
157 | 2 | } |
158 | | |
159 | 3 | return this->operator<<(static_cast<unsigned long long>(N)); |
160 | 3 | } |
161 | | |
162 | 0 | raw_ostream &raw_ostream::write_hex(unsigned long long N) { |
163 | | // Zero is a special case. |
164 | 0 | if (N == 0) |
165 | 0 | return *this << '0'; |
166 | | |
167 | 0 | char NumberBuffer[16]; |
168 | 0 | char *EndPtr = std::end(NumberBuffer); |
169 | 0 | char *CurPtr = EndPtr; |
170 | |
|
171 | 0 | while (N) { |
172 | 0 | uintptr_t x = N % 16; |
173 | 0 | *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10); |
174 | 0 | N /= 16; |
175 | 0 | } |
176 | |
|
177 | 0 | return write(CurPtr, EndPtr-CurPtr); |
178 | 0 | } |
179 | | |
180 | | raw_ostream &raw_ostream::write_escaped(StringRef Str, |
181 | 0 | bool UseHexEscapes) { |
182 | 0 | for (unsigned i = 0, e = Str.size(); i != e; ++i) { |
183 | 0 | unsigned char c = Str[i]; |
184 | |
|
185 | 0 | switch (c) { |
186 | 0 | case '\\': |
187 | 0 | *this << '\\' << '\\'; |
188 | 0 | break; |
189 | 0 | case '\t': |
190 | 0 | *this << '\\' << 't'; |
191 | 0 | break; |
192 | 0 | case '\n': |
193 | 0 | *this << '\\' << 'n'; |
194 | 0 | break; |
195 | 0 | case '"': |
196 | 0 | *this << '\\' << '"'; |
197 | 0 | break; |
198 | 0 | default: |
199 | 0 | if (std::isprint(c)) { |
200 | 0 | *this << c; |
201 | 0 | break; |
202 | 0 | } |
203 | | |
204 | | // Write out the escaped representation. |
205 | 0 | if (UseHexEscapes) { |
206 | 0 | *this << '\\' << 'x'; |
207 | 0 | *this << hexdigit((c >> 4 & 0xF)); |
208 | 0 | *this << hexdigit((c >> 0) & 0xF); |
209 | 0 | } else { |
210 | | // Always use a full 3-character octal escape. |
211 | 0 | *this << '\\'; |
212 | 0 | *this << char('0' + ((c >> 6) & 7)); |
213 | 0 | *this << char('0' + ((c >> 3) & 7)); |
214 | 0 | *this << char('0' + ((c >> 0) & 7)); |
215 | 0 | } |
216 | 0 | } |
217 | 0 | } |
218 | | |
219 | 0 | return *this; |
220 | 0 | } |
221 | | |
222 | 0 | raw_ostream &raw_ostream::operator<<(const void *P) { |
223 | 0 | *this << '0' << 'x'; |
224 | |
|
225 | 0 | return write_hex((uintptr_t) P); |
226 | 0 | } |
227 | | |
228 | 0 | raw_ostream &raw_ostream::operator<<(double N) { |
229 | | #ifdef _WIN32 |
230 | | // On MSVCRT and compatible, output of %e is incompatible to Posix |
231 | | // by default. Number of exponent digits should be at least 2. "%+03d" |
232 | | // FIXME: Implement our formatter to here or Support/Format.h! |
233 | | #if __cplusplus >= 201103L && defined(__MINGW32__) |
234 | | // FIXME: It should be generic to C++11. |
235 | | if (N == 0.0 && std::signbit(N)) |
236 | | return *this << "-0.000000e+00"; |
237 | | #else |
238 | | int fpcl = _fpclass(N); |
239 | | |
240 | | // negative zero |
241 | | if (fpcl == _FPCLASS_NZ) |
242 | | return *this << "-0.000000e+00"; |
243 | | #endif |
244 | | |
245 | | char buf[16]; |
246 | | unsigned len; |
247 | | len = format("%e", N).snprint(buf, sizeof(buf)); |
248 | | if (len <= sizeof(buf) - 2) { |
249 | | if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { |
250 | | int cs = buf[len - 4]; |
251 | | if (cs == '+' || cs == '-') { |
252 | | int c1 = buf[len - 2]; |
253 | | int c0 = buf[len - 1]; |
254 | | if (isdigit(static_cast<unsigned char>(c1)) && |
255 | | isdigit(static_cast<unsigned char>(c0))) { |
256 | | // Trim leading '0': "...e+012" -> "...e+12\0" |
257 | | buf[len - 3] = c1; |
258 | | buf[len - 2] = c0; |
259 | | buf[--len] = 0; |
260 | | } |
261 | | } |
262 | | } |
263 | | return this->operator<<(buf); |
264 | | } |
265 | | #endif |
266 | 0 | return this->operator<<(format("%e", N)); |
267 | 0 | } |
268 | | |
269 | | |
270 | | |
271 | 1 | void raw_ostream::flush_nonempty() { |
272 | 1 | assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); |
273 | 1 | size_t Length = OutBufCur - OutBufStart; |
274 | 1 | OutBufCur = OutBufStart; |
275 | 1 | write_impl(OutBufStart, Length); |
276 | 1 | } |
277 | | |
278 | 1.35G | raw_ostream &raw_ostream::write(unsigned char C) { |
279 | | // Group exceptional cases into a single branch. |
280 | 1.35G | if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) { |
281 | 1.35G | if (LLVM_UNLIKELY(!OutBufStart)) { |
282 | 1.35G | if (BufferMode == Unbuffered) { |
283 | 1.35G | write_impl(reinterpret_cast<char*>(&C), 1); |
284 | 1.35G | return *this; |
285 | 1.35G | } |
286 | | // Set up a buffer and start over. |
287 | 0 | SetBuffered(); |
288 | 0 | return write(C); |
289 | 1.35G | } |
290 | | |
291 | 0 | flush_nonempty(); |
292 | 0 | } |
293 | | |
294 | 0 | *OutBufCur++ = C; |
295 | 0 | return *this; |
296 | 1.35G | } |
297 | | |
298 | 235M | raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { |
299 | | // Group exceptional cases into a single branch. |
300 | 235M | if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) { |
301 | 235M | if (LLVM_UNLIKELY(!OutBufStart)) { |
302 | 235M | if (BufferMode == Unbuffered) { |
303 | 235M | write_impl(Ptr, Size); |
304 | 235M | return *this; |
305 | 235M | } |
306 | | // Set up a buffer and start over. |
307 | 1 | SetBuffered(); |
308 | 1 | return write(Ptr, Size); |
309 | 235M | } |
310 | | |
311 | 0 | size_t NumBytes = OutBufEnd - OutBufCur; |
312 | | |
313 | | // If the buffer is empty at this point we have a string that is larger |
314 | | // than the buffer. Directly write the chunk that is a multiple of the |
315 | | // preferred buffer size and put the remainder in the buffer. |
316 | 0 | if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) { |
317 | 0 | assert(NumBytes != 0 && "undefined behavior"); |
318 | 0 | size_t BytesToWrite = Size - (Size % NumBytes); |
319 | 0 | write_impl(Ptr, BytesToWrite); |
320 | 0 | size_t BytesRemaining = Size - BytesToWrite; |
321 | 0 | if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) { |
322 | | // Too much left over to copy into our buffer. |
323 | 0 | return write(Ptr + BytesToWrite, BytesRemaining); |
324 | 0 | } |
325 | 0 | copy_to_buffer(Ptr + BytesToWrite, BytesRemaining); |
326 | 0 | return *this; |
327 | 0 | } |
328 | | |
329 | | // We don't have enough space in the buffer to fit the string in. Insert as |
330 | | // much as possible, flush and start over with the remainder. |
331 | 0 | copy_to_buffer(Ptr, NumBytes); |
332 | 0 | flush_nonempty(); |
333 | 0 | return write(Ptr + NumBytes, Size - NumBytes); |
334 | 0 | } |
335 | | |
336 | 61 | copy_to_buffer(Ptr, Size); |
337 | | |
338 | 61 | return *this; |
339 | 235M | } |
340 | | |
341 | 61 | void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { |
342 | 61 | assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!"); |
343 | | |
344 | | // Handle short strings specially, memcpy isn't very good at very short |
345 | | // strings. |
346 | 61 | switch (Size) { |
347 | 0 | case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH |
348 | 2 | case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH |
349 | 2 | case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH |
350 | 2 | case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH |
351 | 58 | case 0: break; |
352 | 3 | default: |
353 | 3 | memcpy(OutBufCur, Ptr, Size); |
354 | 3 | break; |
355 | 61 | } |
356 | | |
357 | 61 | OutBufCur += Size; |
358 | 61 | } |
359 | | |
360 | | // Formatted output. |
361 | 0 | raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { |
362 | | // If we have more than a few bytes left in our output buffer, try |
363 | | // formatting directly onto its end. |
364 | 0 | size_t NextBufferSize = 127; |
365 | 0 | size_t BufferBytesLeft = OutBufEnd - OutBufCur; |
366 | 0 | if (BufferBytesLeft > 3) { |
367 | 0 | size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); |
368 | | |
369 | | // Common case is that we have plenty of space. |
370 | 0 | if (BytesUsed <= BufferBytesLeft) { |
371 | 0 | OutBufCur += BytesUsed; |
372 | 0 | return *this; |
373 | 0 | } |
374 | | |
375 | | // Otherwise, we overflowed and the return value tells us the size to try |
376 | | // again with. |
377 | 0 | NextBufferSize = BytesUsed; |
378 | 0 | } |
379 | | |
380 | | // If we got here, we didn't have enough space in the output buffer for the |
381 | | // string. Try printing into a SmallVector that is resized to have enough |
382 | | // space. Iterate until we win. |
383 | 0 | SmallVector<char, 128> V; |
384 | |
|
385 | 0 | while (1) { |
386 | 0 | V.resize(NextBufferSize); |
387 | | |
388 | | // Try formatting into the SmallVector. |
389 | 0 | size_t BytesUsed = Fmt.print(V.data(), NextBufferSize); |
390 | | |
391 | | // If BytesUsed fit into the vector, we win. |
392 | 0 | if (BytesUsed <= NextBufferSize) |
393 | 0 | return write(V.data(), BytesUsed); |
394 | | |
395 | | // Otherwise, try again with a new size. |
396 | 0 | assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); |
397 | 0 | NextBufferSize = BytesUsed; |
398 | 0 | } |
399 | 0 | } |
400 | | |
401 | 0 | raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { |
402 | 0 | unsigned Len = FS.Str.size(); |
403 | 0 | int PadAmount = FS.Width - Len; |
404 | 0 | if (FS.RightJustify && (PadAmount > 0)) |
405 | 0 | this->indent(PadAmount); |
406 | 0 | this->operator<<(FS.Str); |
407 | 0 | if (!FS.RightJustify && (PadAmount > 0)) |
408 | 0 | this->indent(PadAmount); |
409 | 0 | return *this; |
410 | 0 | } |
411 | | |
412 | 1 | raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { |
413 | 1 | if (FN.Hex) { |
414 | 1 | unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; |
415 | 1 | unsigned PrefixChars = FN.HexPrefix ? 2 : 0; |
416 | 1 | unsigned Width = std::max(FN.Width, Nibbles + PrefixChars); |
417 | | |
418 | 1 | char NumberBuffer[20] = "0x0000000000000000"; |
419 | 1 | if (!FN.HexPrefix) |
420 | 0 | NumberBuffer[1] = '0'; |
421 | 1 | char *EndPtr = NumberBuffer+Width; |
422 | 1 | char *CurPtr = EndPtr; |
423 | 1 | const char A = FN.Upper ? 'A' : 'a'; |
424 | 1 | unsigned long long N = FN.HexValue; |
425 | 17 | while (N) { |
426 | 16 | uintptr_t x = N % 16; |
427 | 16 | *--CurPtr = (x < 10 ? '0' + x : A + x - 10); |
428 | 16 | N /= 16; |
429 | 16 | } |
430 | | |
431 | 1 | return write(NumberBuffer, Width); |
432 | 1 | } else { |
433 | | // Zero is a special case. |
434 | 0 | if (FN.DecValue == 0) { |
435 | 0 | this->indent(FN.Width-1); |
436 | 0 | return *this << '0'; |
437 | 0 | } |
438 | 0 | char NumberBuffer[32]; |
439 | 0 | char *EndPtr = NumberBuffer+sizeof(NumberBuffer); |
440 | 0 | char *CurPtr = EndPtr; |
441 | 0 | bool Neg = (FN.DecValue < 0); |
442 | 0 | uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue; |
443 | 0 | while (N) { |
444 | 0 | *--CurPtr = '0' + char(N % 10); |
445 | 0 | N /= 10; |
446 | 0 | } |
447 | 0 | int Len = EndPtr - CurPtr; |
448 | 0 | int Pad = FN.Width - Len; |
449 | 0 | if (Neg) |
450 | 0 | --Pad; |
451 | 0 | if (Pad > 0) |
452 | 0 | this->indent(Pad); |
453 | 0 | if (Neg) |
454 | 0 | *this << '-'; |
455 | 0 | return write(CurPtr, Len); |
456 | 0 | } |
457 | 1 | } |
458 | | |
459 | | |
460 | | /// indent - Insert 'NumSpaces' spaces. |
461 | 0 | raw_ostream &raw_ostream::indent(unsigned NumSpaces) { |
462 | 0 | static const char Spaces[] = " " |
463 | 0 | " " |
464 | 0 | " "; |
465 | | |
466 | | // Usually the indentation is small, handle it with a fastpath. |
467 | 0 | if (NumSpaces < array_lengthof(Spaces)) |
468 | 0 | return write(Spaces, NumSpaces); |
469 | | |
470 | 0 | while (NumSpaces) { |
471 | 0 | unsigned NumToWrite = std::min(NumSpaces, |
472 | 0 | (unsigned)array_lengthof(Spaces)-1); |
473 | 0 | write(Spaces, NumToWrite); |
474 | 0 | NumSpaces -= NumToWrite; |
475 | 0 | } |
476 | 0 | return *this; |
477 | 0 | } |
478 | | |
479 | | |
480 | | //===----------------------------------------------------------------------===// |
481 | | // Formatted Output |
482 | | //===----------------------------------------------------------------------===// |
483 | | |
484 | | // Out of line virtual method. |
485 | 0 | void format_object_base::home() { |
486 | 0 | } |
487 | | |
488 | | //===----------------------------------------------------------------------===// |
489 | | // raw_fd_ostream |
490 | | //===----------------------------------------------------------------------===// |
491 | | |
492 | | static int getFD(StringRef Filename, std::error_code &EC, |
493 | 0 | sys::fs::OpenFlags Flags) { |
494 | | // Handle "-" as stdout. Note that when we do this, we consider ourself |
495 | | // the owner of stdout. This means that we can do things like close the |
496 | | // file descriptor when we're done and set the "binary" flag globally. |
497 | 0 | if (Filename == "-") { |
498 | 0 | EC = std::error_code(); |
499 | 0 | return STDOUT_FILENO; |
500 | 0 | } |
501 | | |
502 | 0 | int FD; |
503 | 0 | EC = sys::fs::openFileForWrite(Filename, FD, Flags); |
504 | 0 | if (EC) |
505 | 0 | return -1; |
506 | | |
507 | 0 | return FD; |
508 | 0 | } |
509 | | |
510 | | raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, |
511 | | sys::fs::OpenFlags Flags) |
512 | 0 | : raw_fd_ostream(getFD(Filename, EC, Flags), true) {} |
513 | | |
514 | | /// FD is the file descriptor that this writes to. If ShouldClose is true, this |
515 | | /// closes the file when the stream is destroyed. |
516 | | raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) |
517 | 26 | : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose), |
518 | 26 | Error(false) { |
519 | 26 | if (FD < 0 ) { |
520 | 0 | ShouldClose = false; |
521 | 0 | return; |
522 | 0 | } |
523 | | |
524 | | // Get the starting position. |
525 | 26 | off_t loc = ::lseek(FD, 0, SEEK_CUR); |
526 | | #ifdef LLVM_ON_WIN32 |
527 | | // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes. |
528 | | sys::fs::file_status Status; |
529 | | std::error_code EC = status(FD, Status); |
530 | | SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file; |
531 | | #else |
532 | 26 | SupportsSeeking = loc != (off_t)-1; |
533 | 26 | #endif |
534 | 26 | if (!SupportsSeeking) |
535 | 0 | pos = 0; |
536 | 26 | else |
537 | 26 | pos = static_cast<uint64_t>(loc); |
538 | 26 | } |
539 | | |
540 | 26 | raw_fd_ostream::~raw_fd_ostream() { |
541 | 26 | if (FD >= 0) { |
542 | 26 | flush(); |
543 | 26 | } |
544 | | |
545 | | #ifdef __MINGW32__ |
546 | | // On mingw, global dtors should not call exit(). |
547 | | // report_fatal_error() invokes exit(). We know report_fatal_error() |
548 | | // might not write messages to stderr when any errors were detected |
549 | | // on FD == 2. |
550 | | if (FD == 2) return; |
551 | | #endif |
552 | | |
553 | | // If there are any pending errors, report them now. Clients wishing |
554 | | // to avoid report_fatal_error calls should check for errors with |
555 | | // has_error() and clear the error flag with clear_error() before |
556 | | // destructing raw_ostream objects which may have errors. |
557 | 26 | if (has_error()) |
558 | 0 | report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false); |
559 | 26 | } |
560 | | |
561 | | |
562 | 188M | void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { |
563 | 188M | assert(FD >= 0 && "File already closed."); |
564 | 188M | pos += Size; |
565 | | |
566 | 188M | #ifndef LLVM_ON_WIN32 |
567 | 188M | bool ShouldWriteInChunks = false; |
568 | | #else |
569 | | // Writing a large size of output to Windows console returns ENOMEM. It seems |
570 | | // that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and |
571 | | // the latter has a size limit (66000 bytes or less, depending on heap usage). |
572 | | bool ShouldWriteInChunks = !!::_isatty(FD) && !RunningWindows8OrGreater(); |
573 | | #endif |
574 | | |
575 | 188M | do { |
576 | 188M | size_t ChunkSize = Size; |
577 | 188M | if (ChunkSize > 32767 && ShouldWriteInChunks) |
578 | 0 | ChunkSize = 32767; |
579 | | |
580 | 188M | ssize_t ret = ::write(FD, Ptr, ChunkSize); |
581 | | |
582 | 188M | if (ret < 0) { |
583 | | // If it's a recoverable error, swallow it and retry the write. |
584 | | // |
585 | | // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since |
586 | | // raw_ostream isn't designed to do non-blocking I/O. However, some |
587 | | // programs, such as old versions of bjam, have mistakenly used |
588 | | // O_NONBLOCK. For compatibility, emulate blocking semantics by |
589 | | // spinning until the write succeeds. If you don't want spinning, |
590 | | // don't use O_NONBLOCK file descriptors with raw_ostream. |
591 | 0 | if (errno == EINTR || errno == EAGAIN |
592 | 0 | #ifdef EWOULDBLOCK |
593 | 0 | || errno == EWOULDBLOCK |
594 | 0 | #endif |
595 | 0 | ) |
596 | 0 | continue; |
597 | | |
598 | | // Otherwise it's a non-recoverable error. Note it and quit. |
599 | 0 | error_detected(); |
600 | 0 | break; |
601 | 0 | } |
602 | | |
603 | | // The write may have written some or all of the data. Update the |
604 | | // size and buffer pointer to reflect the remainder that needs |
605 | | // to be written. If there are no bytes left, we're done. |
606 | 188M | Ptr += ret; |
607 | 188M | Size -= ret; |
608 | 188M | } while (Size > 0); |
609 | 188M | } |
610 | | |
611 | 0 | void raw_fd_ostream::close() { |
612 | 0 | assert(ShouldClose); |
613 | 0 | ShouldClose = false; |
614 | 0 | flush(); |
615 | 0 | FD = -1; |
616 | 0 | } |
617 | | |
618 | 0 | uint64_t raw_fd_ostream::seek(uint64_t off) { |
619 | 0 | flush(); |
620 | 0 | pos = ::lseek(FD, off, SEEK_SET); |
621 | 0 | if (pos == (uint64_t)-1) |
622 | 0 | error_detected(); |
623 | 0 | return pos; |
624 | 0 | } |
625 | | |
626 | | void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size, |
627 | 0 | uint64_t Offset) { |
628 | 0 | uint64_t Pos = tell(); |
629 | 0 | seek(Offset); |
630 | 0 | write(Ptr, Size); |
631 | 0 | seek(Pos); |
632 | 0 | } |
633 | | |
634 | 0 | size_t raw_fd_ostream::preferred_buffer_size() const { |
635 | 0 | #if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix) |
636 | | // Windows and Minix have no st_blksize. |
637 | 0 | assert(FD >= 0 && "File not yet open!"); |
638 | 0 | struct stat statbuf; |
639 | 0 | if (fstat(FD, &statbuf) != 0) |
640 | 0 | return 0; |
641 | | |
642 | | // If this is a terminal, don't use buffering. Line buffering |
643 | | // would be a more traditional thing to do, but it's not worth |
644 | | // the complexity. |
645 | 0 | if (S_ISCHR(statbuf.st_mode) && isatty(FD)) |
646 | 0 | return 0; |
647 | | // Return the preferred block size. |
648 | 0 | return statbuf.st_blksize; |
649 | | #else |
650 | | return raw_ostream::preferred_buffer_size(); |
651 | | #endif |
652 | 0 | } |
653 | | |
654 | | raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, |
655 | 5.28M | bool bg) { |
656 | 5.28M | return *this; |
657 | 5.28M | } |
658 | | |
659 | 3.92M | raw_ostream &raw_fd_ostream::resetColor() { |
660 | 3.92M | return *this; |
661 | 3.92M | } |
662 | | |
663 | 0 | raw_ostream &raw_fd_ostream::reverseColor() { |
664 | 0 | return *this; |
665 | 0 | } |
666 | | |
667 | 0 | bool raw_fd_ostream::is_displayed() const { |
668 | 0 | return true; |
669 | 0 | } |
670 | | |
671 | 1.36M | bool raw_fd_ostream::has_colors() const { |
672 | 1.36M | return true; |
673 | 1.36M | } |
674 | | |
675 | | //===----------------------------------------------------------------------===// |
676 | | // outs(), errs(), nulls() |
677 | | //===----------------------------------------------------------------------===// |
678 | | |
679 | | /// outs() - This returns a reference to a raw_ostream for standard output. |
680 | | /// Use it like: outs() << "foo" << "bar"; |
681 | 0 | raw_ostream &llvm_ks::outs() { |
682 | | // Set buffer settings to model stdout behavior. |
683 | | // Delete the file descriptor when the program exits, forcing error |
684 | | // detection. If you don't want this behavior, don't use outs(). |
685 | 0 | std::error_code EC; |
686 | 0 | static raw_fd_ostream S("-", EC, sys::fs::F_None); |
687 | 0 | assert(!EC); |
688 | 0 | return S; |
689 | 0 | } |
690 | | |
691 | | /// errs() - This returns a reference to a raw_ostream for standard error. |
692 | | /// Use it like: errs() << "foo" << "bar"; |
693 | 2.72M | raw_ostream &llvm_ks::errs() { |
694 | | // Set standard error to be unbuffered by default. |
695 | 2.72M | static raw_fd_ostream S(STDERR_FILENO, false, true); |
696 | 2.72M | return S; |
697 | 2.72M | } |
698 | | |
699 | | /// nulls() - This returns a reference to a raw_ostream which discards output. |
700 | 0 | raw_ostream &llvm_ks::nulls() { |
701 | 0 | static raw_null_ostream S; |
702 | 0 | return S; |
703 | 0 | } |
704 | | |
705 | | |
706 | | //===----------------------------------------------------------------------===// |
707 | | // raw_string_ostream |
708 | | //===----------------------------------------------------------------------===// |
709 | | |
710 | 1 | raw_string_ostream::~raw_string_ostream() { |
711 | 1 | flush(); |
712 | 1 | } |
713 | | |
714 | 1 | void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { |
715 | 1 | OS.append(Ptr, Size); |
716 | 1 | } |
717 | | |
718 | | //===----------------------------------------------------------------------===// |
719 | | // raw_svector_ostream |
720 | | //===----------------------------------------------------------------------===// |
721 | | |
722 | 911k | uint64_t raw_svector_ostream::current_pos() const { return OS.size(); } |
723 | | |
724 | 1.39G | void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { |
725 | 1.39G | OS.append(Ptr, Ptr + Size); |
726 | 1.39G | } |
727 | | |
728 | | void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size, |
729 | 0 | uint64_t Offset) { |
730 | 0 | memcpy(OS.data() + Offset, Ptr, Size); |
731 | 0 | } |
732 | | |
733 | | //===----------------------------------------------------------------------===// |
734 | | // raw_null_ostream |
735 | | //===----------------------------------------------------------------------===// |
736 | | |
737 | 0 | raw_null_ostream::~raw_null_ostream() { |
738 | 0 | #ifndef NDEBUG |
739 | | // ~raw_ostream asserts that the buffer is empty. This isn't necessary |
740 | | // with raw_null_ostream, but it's better to have raw_null_ostream follow |
741 | | // the rules than to change the rules just for raw_null_ostream. |
742 | 0 | flush(); |
743 | 0 | #endif |
744 | 0 | } |
745 | | |
746 | 0 | void raw_null_ostream::write_impl(const char *Ptr, size_t Size) { |
747 | 0 | } |
748 | | |
749 | 0 | uint64_t raw_null_ostream::current_pos() const { |
750 | 0 | return 0; |
751 | 0 | } |
752 | | |
753 | | void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size, |
754 | 0 | uint64_t Offset) {} |