diff options
author | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
---|---|---|
committer | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
commit | b5530586d68bd25831a6796b5d3199cb0769a35c (patch) | |
tree | fac4a03b53b6a64b0c00f433e4d8b3c9f2bc67cd /lib/Support/raw_ostream.cpp | |
parent | b4e17c5bf4361bbdeced39aa071150d7fa9c3c10 (diff) | |
parent | d01f50f42ce60207ed6d27fb1778e456d83be06c (diff) | |
download | external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.zip external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.gz external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.bz2 |
Merge upstream r127116
Diffstat (limited to 'lib/Support/raw_ostream.cpp')
-rw-r--r-- | lib/Support/raw_ostream.cpp | 82 |
1 files changed, 62 insertions, 20 deletions
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index dceccad..b175d20 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -13,8 +13,9 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Format.h" -#include "llvm/System/Program.h" -#include "llvm/System/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Process.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Config/config.h" #include "llvm/Support/Compiler.h" @@ -31,6 +32,9 @@ #if defined(HAVE_FCNTL_H) # include <fcntl.h> #endif +#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV) +# include <sys/uio.h> +#endif #if defined(__CYGWIN__) #include <io.h> @@ -167,7 +171,8 @@ raw_ostream &raw_ostream::write_hex(unsigned long long N) { return write(CurPtr, EndPtr-CurPtr); } -raw_ostream &raw_ostream::write_escaped(StringRef Str) { +raw_ostream &raw_ostream::write_escaped(StringRef Str, + bool UseHexEscapes) { for (unsigned i = 0, e = Str.size(); i != e; ++i) { unsigned char c = Str[i]; @@ -190,11 +195,18 @@ raw_ostream &raw_ostream::write_escaped(StringRef Str) { break; } - // Always expand to a 3-character octal escape. - *this << '\\'; - *this << char('0' + ((c >> 6) & 7)); - *this << char('0' + ((c >> 3) & 7)); - *this << char('0' + ((c >> 0) & 7)); + // Write out the escaped representation. + if (UseHexEscapes) { + *this << '\\' << 'x'; + *this << hexdigit((c >> 4 & 0xF)); + *this << hexdigit((c >> 0) & 0xF); + } else { + // Always use a full 3-character octal escape. + *this << '\\'; + *this << char('0' + ((c >> 6) & 7)); + *this << char('0' + ((c >> 3) & 7)); + *this << char('0' + ((c >> 0) & 7)); + } } } @@ -253,15 +265,23 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { return write(Ptr, Size); } - // Write out the data in buffer-sized blocks until the remainder - // fits within the buffer. - do { - size_t NumBytes = OutBufEnd - OutBufCur; - copy_to_buffer(Ptr, NumBytes); - flush_nonempty(); - Ptr += NumBytes; - Size -= NumBytes; - } while (OutBufCur+Size > OutBufEnd); + size_t NumBytes = OutBufEnd - OutBufCur; + + // If the buffer is empty at this point we have a string that is larger + // than the buffer. Directly write the chunk that is a multiple of the + // preferred buffer size and put the remainder in the buffer. + if (BUILTIN_EXPECT(OutBufCur == OutBufStart, false)) { + size_t BytesToWrite = Size - (Size % NumBytes); + write_impl(Ptr, BytesToWrite); + copy_to_buffer(Ptr + BytesToWrite, Size - BytesToWrite); + return *this; + } + + // We don't have enough space in the buffer to fit the string in. Insert as + // much as possible, flush and start over with the remainder. + copy_to_buffer(Ptr, NumBytes); + flush_nonempty(); + return write(Ptr + NumBytes, Size - NumBytes); } copy_to_buffer(Ptr, Size); @@ -366,7 +386,9 @@ void format_object_base::home() { /// stream should be immediately destroyed; the string will be empty /// if no error occurred. raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, - unsigned Flags) : Error(false), pos(0) { + unsigned Flags) + : Error(false), UseAtomicWrites(false), pos(0) +{ assert(Filename != 0 && "Filename is null"); // Verify that we don't have both "append" and "excl". assert((!(Flags & F_Excl) || !(Flags & F_Append)) && @@ -417,13 +439,20 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, /// ShouldClose is true, this closes the file when the stream is destroyed. raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) : raw_ostream(unbuffered), FD(fd), - ShouldClose(shouldClose), Error(false) { + ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) { #ifdef O_BINARY // Setting STDOUT and STDERR to binary mode is necessary in Win32 // to avoid undesirable linefeed conversion. if (fd == STDOUT_FILENO || fd == STDERR_FILENO) setmode(fd, O_BINARY); #endif + + // Get the starting position. + off_t loc = ::lseek(FD, 0, SEEK_CUR); + if (loc == (off_t)-1) + pos = 0; + else + pos = static_cast<uint64_t>(loc); } raw_fd_ostream::~raw_fd_ostream() { @@ -451,7 +480,20 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { pos += Size; do { - ssize_t ret = ::write(FD, Ptr, Size); + ssize_t ret; + + // Check whether we should attempt to use atomic writes. + if (BUILTIN_EXPECT(!UseAtomicWrites, true)) { + ret = ::write(FD, Ptr, Size); + } else { + // Use ::writev() where available. +#if defined(HAVE_WRITEV) + struct iovec IOV = { (void*) Ptr, Size }; + ret = ::writev(FD, &IOV, 1); +#else + ret = ::write(FD, Ptr, Size); +#endif + } if (ret < 0) { // If it's a recoverable error, swallow it and retry the write. |