diff options
Diffstat (limited to 'contrib/llvm/lib/Support/FileOutputBuffer.cpp')
| -rw-r--r-- | contrib/llvm/lib/Support/FileOutputBuffer.cpp | 81 | 
1 files changed, 42 insertions, 39 deletions
| diff --git a/contrib/llvm/lib/Support/FileOutputBuffer.cpp b/contrib/llvm/lib/Support/FileOutputBuffer.cpp index b8223126227d..3d6b569f2993 100644 --- a/contrib/llvm/lib/Support/FileOutputBuffer.cpp +++ b/contrib/llvm/lib/Support/FileOutputBuffer.cpp @@ -1,9 +1,8 @@  //===- FileOutputBuffer.cpp - File Output Buffer ----------------*- C++ -*-===//  // -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  //  //===----------------------------------------------------------------------===//  // @@ -76,18 +75,26 @@ private:  // output file on commit(). This is used only when we cannot use OnDiskBuffer.  class InMemoryBuffer : public FileOutputBuffer {  public: -  InMemoryBuffer(StringRef Path, MemoryBlock Buf, unsigned Mode) -      : FileOutputBuffer(Path), Buffer(Buf), Mode(Mode) {} +  InMemoryBuffer(StringRef Path, MemoryBlock Buf, std::size_t BufSize, +                 unsigned Mode) +      : FileOutputBuffer(Path), Buffer(Buf), BufferSize(BufSize), +        Mode(Mode) {}    uint8_t *getBufferStart() const override { return (uint8_t *)Buffer.base(); }    uint8_t *getBufferEnd() const override { -    return (uint8_t *)Buffer.base() + Buffer.size(); +    return (uint8_t *)Buffer.base() + BufferSize;    } -  size_t getBufferSize() const override { return Buffer.size(); } +  size_t getBufferSize() const override { return BufferSize; }    Error commit() override { +    if (FinalPath == "-") { +      llvm::outs() << StringRef((const char *)Buffer.base(), BufferSize); +      llvm::outs().flush(); +      return Error::success(); +    } +      using namespace sys::fs;      int FD;      std::error_code EC; @@ -95,12 +102,14 @@ public:              openFileForWrite(FinalPath, FD, CD_CreateAlways, OF_None, Mode))        return errorCodeToError(EC);      raw_fd_ostream OS(FD, /*shouldClose=*/true, /*unbuffered=*/true); -    OS << StringRef((const char *)Buffer.base(), Buffer.size()); +    OS << StringRef((const char *)Buffer.base(), BufferSize);      return Error::success();    }  private: +  // Buffer may actually contain a larger memory block than BufferSize    OwningMemoryBlock Buffer; +  size_t BufferSize;    unsigned Mode;  };  } // namespace @@ -112,43 +121,42 @@ createInMemoryBuffer(StringRef Path, size_t Size, unsigned Mode) {        Size, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);    if (EC)      return errorCodeToError(EC); -  return llvm::make_unique<InMemoryBuffer>(Path, MB, Mode); +  return llvm::make_unique<InMemoryBuffer>(Path, MB, Size, Mode);  } -static Expected<std::unique_ptr<OnDiskBuffer>> -createOnDiskBuffer(StringRef Path, size_t Size, bool InitExisting, -                   unsigned Mode) { +static Expected<std::unique_ptr<FileOutputBuffer>> +createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {    Expected<fs::TempFile> FileOrErr =        fs::TempFile::create(Path + ".tmp%%%%%%%", Mode);    if (!FileOrErr)      return FileOrErr.takeError();    fs::TempFile File = std::move(*FileOrErr); -  if (InitExisting) { -    if (auto EC = sys::fs::copy_file(Path, File.FD)) -      return errorCodeToError(EC); -  } else {  #ifndef _WIN32 -    // On Windows, CreateFileMapping (the mmap function on Windows) -    // automatically extends the underlying file. We don't need to -    // extend the file beforehand. _chsize (ftruncate on Windows) is -    // pretty slow just like it writes specified amount of bytes, -    // so we should avoid calling that function. -    if (auto EC = fs::resize_file(File.FD, Size)) { -      consumeError(File.discard()); -      return errorCodeToError(EC); -    } -#endif +  // On Windows, CreateFileMapping (the mmap function on Windows) +  // automatically extends the underlying file. We don't need to +  // extend the file beforehand. _chsize (ftruncate on Windows) is +  // pretty slow just like it writes specified amount of bytes, +  // so we should avoid calling that function. +  if (auto EC = fs::resize_file(File.FD, Size)) { +    consumeError(File.discard()); +    return errorCodeToError(EC);    } +#endif    // Mmap it.    std::error_code EC;    auto MappedFile = llvm::make_unique<fs::mapped_file_region>( -      File.FD, fs::mapped_file_region::readwrite, Size, 0, EC); +      fs::convertFDToNativeFile(File.FD), fs::mapped_file_region::readwrite, +      Size, 0, EC); + +  // mmap(2) can fail if the underlying filesystem does not support it. +  // If that happens, we fall back to in-memory buffer as the last resort.    if (EC) {      consumeError(File.discard()); -    return errorCodeToError(EC); +    return createInMemoryBuffer(Path, Size, Mode);    } +    return llvm::make_unique<OnDiskBuffer>(Path, std::move(File),                                           std::move(MappedFile));  } @@ -156,6 +164,10 @@ createOnDiskBuffer(StringRef Path, size_t Size, bool InitExisting,  // Create an instance of FileOutputBuffer.  Expected<std::unique_ptr<FileOutputBuffer>>  FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) { +  // Handle "-" as stdout just like llvm::raw_ostream does. +  if (Path == "-") +    return createInMemoryBuffer("-", Size, /*Mode=*/0); +    unsigned Mode = fs::all_read | fs::all_write;    if (Flags & F_executable)      Mode |= fs::all_exe; @@ -163,15 +175,6 @@ FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) {    fs::file_status Stat;    fs::status(Path, Stat); -  if ((Flags & F_modify) && Size == size_t(-1)) { -    if (Stat.type() == fs::file_type::regular_file) -      Size = Stat.getSize(); -    else if (Stat.type() == fs::file_type::file_not_found) -      return errorCodeToError(errc::no_such_file_or_directory); -    else -      return errorCodeToError(errc::invalid_argument); -  } -    // Usually, we want to create OnDiskBuffer to create a temporary file in    // the same directory as the destination file and atomically replaces it    // by rename(2). @@ -186,7 +189,7 @@ FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) {    case fs::file_type::regular_file:    case fs::file_type::file_not_found:    case fs::file_type::status_error: -    return createOnDiskBuffer(Path, Size, !!(Flags & F_modify), Mode); +    return createOnDiskBuffer(Path, Size, Mode);    default:      return createInMemoryBuffer(Path, Size, Mode);    } | 
