1030 lines · cpp
1//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This implements support for bulk buffered stream output.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/Support/raw_ostream.h"14#include "llvm/ADT/StringExtras.h"15#include "llvm/Config/config.h"16#include "llvm/Support/AutoConvert.h"17#include "llvm/Support/Compiler.h"18#include "llvm/Support/Duration.h"19#include "llvm/Support/ErrorHandling.h"20#include "llvm/Support/FileSystem.h"21#include "llvm/Support/Format.h"22#include "llvm/Support/FormatVariadic.h"23#include "llvm/Support/MathExtras.h"24#include "llvm/Support/NativeFormatting.h"25#include "llvm/Support/Process.h"26#include "llvm/Support/Program.h"27#include <algorithm>28#include <cerrno>29#include <cstdio>30#include <sys/stat.h>31 32// <fcntl.h> may provide O_BINARY.33# include <fcntl.h>34 35#if defined(HAVE_UNISTD_H)36# include <unistd.h>37#endif38 39#if defined(__CYGWIN__)40#include <io.h>41#endif42 43#if defined(_MSC_VER)44#include <io.h>45#ifndef STDIN_FILENO46# define STDIN_FILENO 047#endif48#ifndef STDOUT_FILENO49# define STDOUT_FILENO 150#endif51#ifndef STDERR_FILENO52# define STDERR_FILENO 253#endif54#endif55 56#ifdef _WIN3257#include "llvm/Support/ConvertUTF.h"58#include "llvm/Support/Signals.h"59#include "llvm/Support/Windows/WindowsSupport.h"60#endif61 62using namespace llvm;63 64raw_ostream::~raw_ostream() {65 // raw_ostream's subclasses should take care to flush the buffer66 // in their destructors.67 assert(OutBufCur == OutBufStart &&68 "raw_ostream destructor called with non-empty buffer!");69 70 if (BufferMode == BufferKind::InternalBuffer)71 delete [] OutBufStart;72}73 74size_t raw_ostream::preferred_buffer_size() const {75#ifdef _WIN3276 // On Windows BUFSIZ is only 512 which results in more calls to write. This77 // overhead can cause significant performance degradation. Therefore use a78 // better default.79 return (16 * 1024);80#else81 // BUFSIZ is intended to be a reasonable default.82 return BUFSIZ;83#endif84}85 86void raw_ostream::SetBuffered() {87 // Ask the subclass to determine an appropriate buffer size.88 if (size_t Size = preferred_buffer_size())89 SetBufferSize(Size);90 else91 // It may return 0, meaning this stream should be unbuffered.92 SetUnbuffered();93}94 95void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,96 BufferKind Mode) {97 assert(((Mode == BufferKind::Unbuffered && !BufferStart && Size == 0) ||98 (Mode != BufferKind::Unbuffered && BufferStart && Size != 0)) &&99 "stream must be unbuffered or have at least one byte");100 // Make sure the current buffer is free of content (we can't flush here; the101 // child buffer management logic will be in write_impl).102 assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");103 104 if (BufferMode == BufferKind::InternalBuffer)105 delete [] OutBufStart;106 OutBufStart = BufferStart;107 OutBufEnd = OutBufStart+Size;108 OutBufCur = OutBufStart;109 BufferMode = Mode;110 111 assert(OutBufStart <= OutBufEnd && "Invalid size!");112}113 114raw_ostream &raw_ostream::operator<<(unsigned long N) {115 write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);116 return *this;117}118 119raw_ostream &raw_ostream::operator<<(long N) {120 write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);121 return *this;122}123 124raw_ostream &raw_ostream::operator<<(unsigned long long N) {125 write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);126 return *this;127}128 129raw_ostream &raw_ostream::operator<<(long long N) {130 write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);131 return *this;132}133 134raw_ostream &raw_ostream::write_hex(unsigned long long N) {135 llvm::write_hex(*this, N, HexPrintStyle::Lower);136 return *this;137}138 139raw_ostream &raw_ostream::operator<<(Colors C) {140 if (C == Colors::RESET)141 resetColor();142 else143 changeColor(C);144 return *this;145}146 147raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) {148 for (int Idx = 0; Idx < 16; ++Idx) {149 *this << format("%02" PRIX32, UUID[Idx]);150 if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)151 *this << "-";152 }153 return *this;154}155 156 157raw_ostream &raw_ostream::write_escaped(StringRef Str,158 bool UseHexEscapes) {159 for (unsigned char c : Str) {160 switch (c) {161 case '\\':162 *this << '\\' << '\\';163 break;164 case '\t':165 *this << '\\' << 't';166 break;167 case '\n':168 *this << '\\' << 'n';169 break;170 case '"':171 *this << '\\' << '"';172 break;173 default:174 if (isPrint(c)) {175 *this << c;176 break;177 }178 179 // Write out the escaped representation.180 if (UseHexEscapes) {181 *this << '\\' << 'x';182 *this << hexdigit((c >> 4) & 0xF);183 *this << hexdigit((c >> 0) & 0xF);184 } else {185 // Always use a full 3-character octal escape.186 *this << '\\';187 *this << char('0' + ((c >> 6) & 7));188 *this << char('0' + ((c >> 3) & 7));189 *this << char('0' + ((c >> 0) & 7));190 }191 }192 }193 194 return *this;195}196 197raw_ostream &raw_ostream::operator<<(const void *P) {198 llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower);199 return *this;200}201 202raw_ostream &raw_ostream::operator<<(double N) {203 llvm::write_double(*this, N, FloatStyle::Exponent);204 return *this;205}206 207void raw_ostream::flush_nonempty() {208 assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");209 size_t Length = OutBufCur - OutBufStart;210 OutBufCur = OutBufStart;211 write_impl(OutBufStart, Length);212}213 214raw_ostream &raw_ostream::write(unsigned char C) {215 // Group exceptional cases into a single branch.216 if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {217 if (LLVM_UNLIKELY(!OutBufStart)) {218 if (BufferMode == BufferKind::Unbuffered) {219 write_impl(reinterpret_cast<char *>(&C), 1);220 return *this;221 }222 // Set up a buffer and start over.223 SetBuffered();224 return write(C);225 }226 227 flush_nonempty();228 }229 230 *OutBufCur++ = C;231 return *this;232}233 234raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {235 // Group exceptional cases into a single branch.236 if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {237 if (LLVM_UNLIKELY(!OutBufStart)) {238 if (BufferMode == BufferKind::Unbuffered) {239 write_impl(Ptr, Size);240 return *this;241 }242 // Set up a buffer and start over.243 SetBuffered();244 return write(Ptr, Size);245 }246 247 size_t NumBytes = OutBufEnd - OutBufCur;248 249 // If the buffer is empty at this point we have a string that is larger250 // than the buffer. Directly write the chunk that is a multiple of the251 // preferred buffer size and put the remainder in the buffer.252 if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) {253 assert(NumBytes != 0 && "undefined behavior");254 size_t BytesToWrite = Size - (Size % NumBytes);255 write_impl(Ptr, BytesToWrite);256 size_t BytesRemaining = Size - BytesToWrite;257 if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) {258 // Too much left over to copy into our buffer.259 return write(Ptr + BytesToWrite, BytesRemaining);260 }261 copy_to_buffer(Ptr + BytesToWrite, BytesRemaining);262 return *this;263 }264 265 // We don't have enough space in the buffer to fit the string in. Insert as266 // much as possible, flush and start over with the remainder.267 copy_to_buffer(Ptr, NumBytes);268 flush_nonempty();269 return write(Ptr + NumBytes, Size - NumBytes);270 }271 272 copy_to_buffer(Ptr, Size);273 274 return *this;275}276 277void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {278 assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!");279 280 // Handle short strings specially, memcpy isn't very good at very short281 // strings.282 switch (Size) {283 case 4: OutBufCur[3] = Ptr[3]; [[fallthrough]];284 case 3: OutBufCur[2] = Ptr[2]; [[fallthrough]];285 case 2: OutBufCur[1] = Ptr[1]; [[fallthrough]];286 case 1: OutBufCur[0] = Ptr[0]; [[fallthrough]];287 case 0: break;288 default:289 memcpy(OutBufCur, Ptr, Size);290 break;291 }292 293 OutBufCur += Size;294}295 296// Formatted output.297raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {298 // If we have more than a few bytes left in our output buffer, try299 // formatting directly onto its end.300 size_t NextBufferSize = 127;301 size_t BufferBytesLeft = OutBufEnd - OutBufCur;302 if (BufferBytesLeft > 3) {303 size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);304 305 // Common case is that we have plenty of space.306 if (BytesUsed <= BufferBytesLeft) {307 OutBufCur += BytesUsed;308 return *this;309 }310 311 // Otherwise, we overflowed and the return value tells us the size to try312 // again with.313 NextBufferSize = BytesUsed;314 }315 316 // If we got here, we didn't have enough space in the output buffer for the317 // string. Try printing into a SmallVector that is resized to have enough318 // space. Iterate until we win.319 SmallVector<char, 128> V;320 321 while (true) {322 V.resize(NextBufferSize);323 324 // Try formatting into the SmallVector.325 size_t BytesUsed = Fmt.print(V.data(), NextBufferSize);326 327 // If BytesUsed fit into the vector, we win.328 if (BytesUsed <= NextBufferSize)329 return write(V.data(), BytesUsed);330 331 // Otherwise, try again with a new size.332 assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");333 NextBufferSize = BytesUsed;334 }335}336 337raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) {338 Obj.format(*this);339 return *this;340}341 342raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {343 unsigned LeftIndent = 0;344 unsigned RightIndent = 0;345 const ssize_t Difference = FS.Width - FS.Str.size();346 if (Difference > 0) {347 switch (FS.Justify) {348 case FormattedString::JustifyNone:349 break;350 case FormattedString::JustifyLeft:351 RightIndent = Difference;352 break;353 case FormattedString::JustifyRight:354 LeftIndent = Difference;355 break;356 case FormattedString::JustifyCenter:357 LeftIndent = Difference / 2;358 RightIndent = Difference - LeftIndent;359 break;360 }361 }362 indent(LeftIndent);363 (*this) << FS.Str;364 indent(RightIndent);365 return *this;366}367 368raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {369 if (FN.Hex) {370 HexPrintStyle Style;371 if (FN.Upper && FN.HexPrefix)372 Style = HexPrintStyle::PrefixUpper;373 else if (FN.Upper && !FN.HexPrefix)374 Style = HexPrintStyle::Upper;375 else if (!FN.Upper && FN.HexPrefix)376 Style = HexPrintStyle::PrefixLower;377 else378 Style = HexPrintStyle::Lower;379 llvm::write_hex(*this, FN.HexValue, Style, FN.Width);380 } else {381 llvm::SmallString<16> Buffer;382 llvm::raw_svector_ostream Stream(Buffer);383 llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer);384 if (Buffer.size() < FN.Width)385 indent(FN.Width - Buffer.size());386 (*this) << Buffer;387 }388 return *this;389}390 391raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) {392 if (FB.Bytes.empty())393 return *this;394 395 size_t LineIndex = 0;396 auto Bytes = FB.Bytes;397 const size_t Size = Bytes.size();398 HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower;399 uint64_t OffsetWidth = 0;400 if (FB.FirstByteOffset) {401 // Figure out how many nibbles are needed to print the largest offset402 // represented by this data set, so that we can align the offset field403 // to the right width.404 size_t Lines = Size / FB.NumPerLine;405 uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine;406 unsigned Power = 0;407 if (MaxOffset > 0)408 Power = llvm::Log2_64_Ceil(MaxOffset);409 OffsetWidth = std::max<uint64_t>(4, llvm::alignTo(Power, 4) / 4);410 }411 412 // The width of a block of data including all spaces for group separators.413 unsigned NumByteGroups =414 alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize;415 unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1;416 417 while (!Bytes.empty()) {418 indent(FB.IndentLevel);419 420 if (FB.FirstByteOffset) {421 uint64_t Offset = *FB.FirstByteOffset;422 llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth);423 *this << ": ";424 }425 426 auto Line = Bytes.take_front(FB.NumPerLine);427 428 size_t CharsPrinted = 0;429 // Print the hex bytes for this line in groups430 for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) {431 if (I && (I % FB.ByteGroupSize) == 0) {432 ++CharsPrinted;433 *this << " ";434 }435 llvm::write_hex(*this, Line[I], HPS, 2);436 }437 438 if (FB.ASCII) {439 // Print any spaces needed for any bytes that we didn't print on this440 // line so that the ASCII bytes are correctly aligned.441 assert(BlockCharWidth >= CharsPrinted);442 indent(BlockCharWidth - CharsPrinted + 2);443 *this << "|";444 445 // Print the ASCII char values for each byte on this line446 for (uint8_t Byte : Line) {447 if (isPrint(Byte))448 *this << static_cast<char>(Byte);449 else450 *this << '.';451 }452 *this << '|';453 }454 455 Bytes = Bytes.drop_front(Line.size());456 LineIndex += Line.size();457 if (LineIndex < Size)458 *this << '\n';459 }460 return *this;461}462 463template <char C>464static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {465 static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,466 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,467 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,468 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,469 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C};470 471 // Usually the indentation is small, handle it with a fastpath.472 if (NumChars < std::size(Chars))473 return OS.write(Chars, NumChars);474 475 while (NumChars) {476 unsigned NumToWrite = std::min(NumChars, (unsigned)std::size(Chars) - 1);477 OS.write(Chars, NumToWrite);478 NumChars -= NumToWrite;479 }480 return OS;481}482 483/// indent - Insert 'NumSpaces' spaces.484raw_ostream &raw_ostream::indent(unsigned NumSpaces) {485 return write_padding<' '>(*this, NumSpaces);486}487 488/// write_zeros - Insert 'NumZeros' nulls.489raw_ostream &raw_ostream::write_zeros(unsigned NumZeros) {490 return write_padding<'\0'>(*this, NumZeros);491}492 493bool raw_ostream::prepare_colors() {494 // Colors were explicitly disabled.495 if (!ColorEnabled)496 return false;497 498 // Colors require changing the terminal but this stream is not going to a499 // terminal.500 if (sys::Process::ColorNeedsFlush() && !is_displayed())501 return false;502 503 if (sys::Process::ColorNeedsFlush())504 flush();505 506 return true;507}508 509raw_ostream &raw_ostream::changeColor(enum Colors colors, bool bold, bool bg) {510 if (!prepare_colors())511 return *this;512 513 const char *colorcode =514 (colors == SAVEDCOLOR)515 ? sys::Process::OutputBold(bg)516 : sys::Process::OutputColor(static_cast<char>(colors), bold, bg);517 if (colorcode)518 write(colorcode, strlen(colorcode));519 return *this;520}521 522raw_ostream &raw_ostream::resetColor() {523 if (!prepare_colors())524 return *this;525 526 if (const char *colorcode = sys::Process::ResetColor())527 write(colorcode, strlen(colorcode));528 return *this;529}530 531raw_ostream &raw_ostream::reverseColor() {532 if (!prepare_colors())533 return *this;534 535 if (const char *colorcode = sys::Process::OutputReverse())536 write(colorcode, strlen(colorcode));537 return *this;538}539 540void raw_ostream::anchor() {}541 542//===----------------------------------------------------------------------===//543// Formatted Output544//===----------------------------------------------------------------------===//545 546// Out of line virtual method.547void format_object_base::home() {548}549 550//===----------------------------------------------------------------------===//551// raw_fd_ostream552//===----------------------------------------------------------------------===//553 554static int getFD(StringRef Filename, std::error_code &EC,555 sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,556 sys::fs::OpenFlags Flags) {557 assert((Access & sys::fs::FA_Write) &&558 "Cannot make a raw_ostream from a read-only descriptor!");559 560 // Handle "-" as stdout. Note that when we do this, we consider ourself561 // the owner of stdout and may set the "binary" flag globally based on Flags.562 if (Filename == "-") {563 EC = std::error_code();564 // Change stdout's text/binary mode based on the Flags.565 sys::ChangeStdoutMode(Flags);566 return STDOUT_FILENO;567 }568 569 int FD;570 if (Access & sys::fs::FA_Read)571 EC = sys::fs::openFileForReadWrite(Filename, FD, Disp, Flags);572 else573 EC = sys::fs::openFileForWrite(Filename, FD, Disp, Flags);574 if (EC)575 return -1;576 577 return FD;578}579 580raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC)581 : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,582 sys::fs::OF_None) {}583 584raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,585 sys::fs::CreationDisposition Disp)586 : raw_fd_ostream(Filename, EC, Disp, sys::fs::FA_Write, sys::fs::OF_None) {}587 588raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,589 sys::fs::FileAccess Access)590 : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, Access,591 sys::fs::OF_None) {}592 593raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,594 sys::fs::OpenFlags Flags)595 : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,596 Flags) {}597 598raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,599 sys::fs::CreationDisposition Disp,600 sys::fs::FileAccess Access,601 sys::fs::OpenFlags Flags)602 : raw_fd_ostream(getFD(Filename, EC, Disp, Access, Flags), true) {}603 604/// FD is the file descriptor that this writes to. If ShouldClose is true, this605/// closes the file when the stream is destroyed.606raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,607 OStreamKind K)608 : raw_pwrite_stream(unbuffered, K), FD(fd), ShouldClose(shouldClose) {609 if (FD < 0 ) {610 ShouldClose = false;611 return;612 }613 614 enable_colors(true);615 616 // Do not attempt to close stdout or stderr. We used to try to maintain the617 // property that tools that support writing file to stdout should not also618 // write informational output to stdout, but in practice we were never able to619 // maintain this invariant. Many features have been added to LLVM and clang620 // (-fdump-record-layouts, optimization remarks, etc) that print to stdout, so621 // users must simply be aware that mixed output and remarks is a possibility.622 if (FD <= STDERR_FILENO)623 ShouldClose = false;624 625#ifdef _WIN32626 // Check if this is a console device. This is not equivalent to isatty.627 IsWindowsConsole =628 ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;629#endif630 631 // Get the starting position.632 off_t loc = ::lseek(FD, 0, SEEK_CUR);633 sys::fs::file_status Status;634 std::error_code EC = status(FD, Status);635 IsRegularFile = Status.type() == sys::fs::file_type::regular_file;636#ifdef _WIN32637 // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.638 SupportsSeeking = !EC && IsRegularFile;639#else640 SupportsSeeking = !EC && loc != (off_t)-1;641#endif642 if (!SupportsSeeking)643 pos = 0;644 else645 pos = static_cast<uint64_t>(loc);646}647 648raw_fd_ostream::~raw_fd_ostream() {649 if (FD >= 0) {650 flush();651 if (ShouldClose) {652 if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))653 error_detected(EC);654 }655 }656 657#ifdef __MINGW32__658 // On mingw, global dtors should not call exit().659 // report_fatal_error() invokes exit(). We know report_fatal_error()660 // might not write messages to stderr when any errors were detected661 // on FD == 2.662 if (FD == 2) return;663#endif664 665 // If there are any pending errors, report them now. Clients wishing666 // to avoid report_fatal_error calls should check for errors with667 // has_error() and clear the error flag with clear_error() before668 // destructing raw_ostream objects which may have errors.669 if (has_error())670 reportFatalUsageError(Twine("IO failure on output stream: ") +671 error().message());672}673 674#if defined(_WIN32)675// The most reliable way to print unicode in a Windows console is with676// WriteConsoleW. To use that, first transcode from UTF-8 to UTF-16. This677// assumes that LLVM programs always print valid UTF-8 to the console. The data678// might not be UTF-8 for two major reasons:679// 1. The program is printing binary (-filetype=obj -o -), in which case it680// would have been gibberish anyway.681// 2. The program is printing text in a semi-ascii compatible codepage like682// shift-jis or cp1252.683//684// Most LLVM programs don't produce non-ascii text unless they are quoting685// user source input. A well-behaved LLVM program should either validate that686// the input is UTF-8 or transcode from the local codepage to UTF-8 before687// quoting it. If they don't, this may mess up the encoding, but this is still688// probably the best compromise we can make.689static bool write_console_impl(int FD, StringRef Data) {690 SmallVector<wchar_t, 256> WideText;691 692 // Fall back to ::write if it wasn't valid UTF-8.693 if (auto EC = sys::windows::UTF8ToUTF16(Data, WideText))694 return false;695 696 // On Windows 7 and earlier, WriteConsoleW has a low maximum amount of data697 // that can be written to the console at a time.698 size_t MaxWriteSize = WideText.size();699 if (!RunningWindows8OrGreater())700 MaxWriteSize = 32767;701 702 size_t WCharsWritten = 0;703 do {704 size_t WCharsToWrite =705 std::min(MaxWriteSize, WideText.size() - WCharsWritten);706 DWORD ActuallyWritten;707 bool Success =708 ::WriteConsoleW((HANDLE)::_get_osfhandle(FD), &WideText[WCharsWritten],709 WCharsToWrite, &ActuallyWritten,710 /*Reserved=*/nullptr);711 712 // The most likely reason for WriteConsoleW to fail is that FD no longer713 // points to a console. Fall back to ::write. If this isn't the first loop714 // iteration, something is truly wrong.715 if (!Success)716 return false;717 718 WCharsWritten += ActuallyWritten;719 } while (WCharsWritten != WideText.size());720 return true;721}722#endif723 724void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {725 if (TiedStream)726 TiedStream->flush();727 728 assert(FD >= 0 && "File already closed.");729 pos += Size;730 731#if defined(_WIN32)732 // If this is a Windows console device, try re-encoding from UTF-8 to UTF-16733 // and using WriteConsoleW. If that fails, fall back to plain write().734 if (IsWindowsConsole)735 if (write_console_impl(FD, StringRef(Ptr, Size)))736 return;737#endif738 739 // The maximum write size is limited to INT32_MAX. A write740 // greater than SSIZE_MAX is implementation-defined in POSIX,741 // and Windows _write requires 32 bit input.742 size_t MaxWriteSize = INT32_MAX;743 744#if defined(__linux__)745 // It is observed that Linux returns EINVAL for a very large write (>2G).746 // Make it a reasonably small value.747 MaxWriteSize = 1024 * 1024 * 1024;748#endif749 750 do {751 size_t ChunkSize = std::min(Size, MaxWriteSize);752 ssize_t ret = ::write(FD, Ptr, ChunkSize);753 754 if (ret < 0) {755 // If it's a recoverable error, swallow it and retry the write.756 //757 // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since758 // raw_ostream isn't designed to do non-blocking I/O. However, some759 // programs, such as old versions of bjam, have mistakenly used760 // O_NONBLOCK. For compatibility, emulate blocking semantics by761 // spinning until the write succeeds. If you don't want spinning,762 // don't use O_NONBLOCK file descriptors with raw_ostream.763 if (errno == EINTR || errno == EAGAIN764#ifdef EWOULDBLOCK765 || errno == EWOULDBLOCK766#endif767 )768 continue;769 770#ifdef _WIN32771 // Windows equivalents of SIGPIPE/EPIPE.772 DWORD WinLastError = GetLastError();773 if (WinLastError == ERROR_BROKEN_PIPE ||774 (WinLastError == ERROR_NO_DATA && errno == EINVAL)) {775 llvm::sys::CallOneShotPipeSignalHandler();776 errno = EPIPE;777 }778#endif779 // Otherwise it's a non-recoverable error. Note it and quit.780 error_detected(errnoAsErrorCode());781 break;782 }783 784 // The write may have written some or all of the data. Update the785 // size and buffer pointer to reflect the remainder that needs786 // to be written. If there are no bytes left, we're done.787 Ptr += ret;788 Size -= ret;789 } while (Size > 0);790}791 792void raw_fd_ostream::close() {793 assert(ShouldClose);794 ShouldClose = false;795 flush();796 if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))797 error_detected(EC);798 FD = -1;799}800 801uint64_t raw_fd_ostream::seek(uint64_t off) {802 assert(SupportsSeeking && "Stream does not support seeking!");803 flush();804#ifdef _WIN32805 pos = ::_lseeki64(FD, off, SEEK_SET);806#else807 pos = ::lseek(FD, off, SEEK_SET);808#endif809 if (pos == (uint64_t)-1)810 error_detected(errnoAsErrorCode());811 return pos;812}813 814void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size,815 uint64_t Offset) {816 uint64_t Pos = tell();817 seek(Offset);818 write(Ptr, Size);819 seek(Pos);820}821 822size_t raw_fd_ostream::preferred_buffer_size() const {823#if defined(_WIN32)824 // Disable buffering for console devices. Console output is re-encoded from825 // UTF-8 to UTF-16 on Windows, and buffering it would require us to split the826 // buffer on a valid UTF-8 codepoint boundary. Terminal buffering is disabled827 // below on most other OSs, so do the same thing on Windows and avoid that828 // complexity.829 if (IsWindowsConsole)830 return 0;831 return raw_ostream::preferred_buffer_size();832#elif defined(__MVS__)833 // The buffer size on z/OS is defined with macro BUFSIZ, which can be834 // retrieved by invoking function raw_ostream::preferred_buffer_size().835 return raw_ostream::preferred_buffer_size();836#else837 assert(FD >= 0 && "File not yet open!");838 struct stat statbuf;839 if (fstat(FD, &statbuf) != 0)840 return 0;841 842 // If this is a terminal, don't use buffering. Line buffering843 // would be a more traditional thing to do, but it's not worth844 // the complexity.845 if (S_ISCHR(statbuf.st_mode) && is_displayed())846 return 0;847 // Return the preferred block size.848 return statbuf.st_blksize;849#endif850}851 852bool raw_fd_ostream::is_displayed() const {853 return sys::Process::FileDescriptorIsDisplayed(FD);854}855 856bool raw_fd_ostream::has_colors() const {857 if (!HasColors)858 HasColors = sys::Process::FileDescriptorHasColors(FD);859 return *HasColors;860}861 862Expected<sys::fs::FileLocker> raw_fd_ostream::lock() {863 std::error_code EC = sys::fs::lockFile(FD);864 if (!EC)865 return sys::fs::FileLocker(FD);866 return errorCodeToError(EC);867}868 869Expected<sys::fs::FileLocker>870raw_fd_ostream::tryLockFor(Duration const& Timeout) {871 std::error_code EC = sys::fs::tryLockFile(FD, Timeout.getDuration());872 if (!EC)873 return sys::fs::FileLocker(FD);874 return errorCodeToError(EC);875}876 877void raw_fd_ostream::anchor() {}878 879//===----------------------------------------------------------------------===//880// outs(), errs(), nulls()881//===----------------------------------------------------------------------===//882 883raw_fd_ostream &llvm::outs() {884 // Set buffer settings to model stdout behavior.885 std::error_code EC;886 887 // On z/OS we need to enable auto conversion888 static std::error_code EC1 = enableAutoConversion(STDOUT_FILENO);889 assert(!EC1);890 (void)EC1;891 892 static raw_fd_ostream S("-", EC, sys::fs::OF_None);893 assert(!EC);894 return S;895}896 897raw_fd_ostream &llvm::errs() {898 // On z/OS we need to enable auto conversion899 static std::error_code EC = enableAutoConversion(STDERR_FILENO);900 assert(!EC);901 (void)EC;902 903 // Set standard error to be unbuffered.904 static raw_fd_ostream S(STDERR_FILENO, false, true);905 return S;906}907 908/// nulls() - This returns a reference to a raw_ostream which discards output.909raw_ostream &llvm::nulls() {910 static raw_null_ostream S;911 return S;912}913 914//===----------------------------------------------------------------------===//915// File Streams916//===----------------------------------------------------------------------===//917 918raw_fd_stream::raw_fd_stream(StringRef Filename, std::error_code &EC)919 : raw_fd_ostream(getFD(Filename, EC, sys::fs::CD_CreateAlways,920 sys::fs::FA_Write | sys::fs::FA_Read,921 sys::fs::OF_None),922 true, false, OStreamKind::OK_FDStream) {923 if (EC)924 return;925 926 if (!isRegularFile())927 EC = std::make_error_code(std::errc::invalid_argument);928}929 930raw_fd_stream::raw_fd_stream(int fd, bool shouldClose)931 : raw_fd_ostream(fd, shouldClose, false, OStreamKind::OK_FDStream) {}932 933ssize_t raw_fd_stream::read(char *Ptr, size_t Size) {934 assert(get_fd() >= 0 && "File already closed.");935 ssize_t Ret = ::read(get_fd(), (void *)Ptr, Size);936 if (Ret >= 0)937 inc_pos(Ret);938 else939 error_detected(errnoAsErrorCode());940 return Ret;941}942 943bool raw_fd_stream::classof(const raw_ostream *OS) {944 return OS->get_kind() == OStreamKind::OK_FDStream;945}946 947//===----------------------------------------------------------------------===//948// raw_string_ostream949//===----------------------------------------------------------------------===//950 951void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {952 OS.append(Ptr, Size);953}954 955//===----------------------------------------------------------------------===//956// raw_svector_ostream957//===----------------------------------------------------------------------===//958 959uint64_t raw_svector_ostream::current_pos() const { return OS.size(); }960 961void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {962 OS.append(Ptr, Ptr + Size);963}964 965void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,966 uint64_t Offset) {967 memcpy(OS.data() + Offset, Ptr, Size);968}969 970bool raw_svector_ostream::classof(const raw_ostream *OS) {971 return OS->get_kind() == OStreamKind::OK_SVecStream;972}973 974//===----------------------------------------------------------------------===//975// raw_null_ostream976//===----------------------------------------------------------------------===//977 978raw_null_ostream::~raw_null_ostream() {979#ifndef NDEBUG980 // ~raw_ostream asserts that the buffer is empty. This isn't necessary981 // with raw_null_ostream, but it's better to have raw_null_ostream follow982 // the rules than to change the rules just for raw_null_ostream.983 flush();984#endif985}986 987void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {988}989 990uint64_t raw_null_ostream::current_pos() const {991 return 0;992}993 994void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,995 uint64_t Offset) {}996 997void raw_pwrite_stream::anchor() {}998 999void buffer_ostream::anchor() {}1000 1001void buffer_unique_ostream::anchor() {}1002 1003Error llvm::writeToOutput(StringRef OutputFileName,1004 std::function<Error(raw_ostream &)> Write) {1005 if (OutputFileName == "-")1006 return Write(outs());1007 1008 if (OutputFileName == "/dev/null") {1009 raw_null_ostream Out;1010 return Write(Out);1011 }1012 1013 unsigned Mode = sys::fs::all_read | sys::fs::all_write;1014 Expected<sys::fs::TempFile> Temp =1015 sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%%%%%", Mode);1016 if (!Temp)1017 return createFileError(OutputFileName, Temp.takeError());1018 1019 raw_fd_ostream Out(Temp->FD, false);1020 1021 if (Error E = Write(Out)) {1022 if (Error DiscardError = Temp->discard())1023 return joinErrors(std::move(E), std::move(DiscardError));1024 return E;1025 }1026 Out.flush();1027 1028 return Temp->keep(OutputFileName);1029}1030