brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.4 KiB · d6f27fb Raw
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