diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 | 
| commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
| tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /lib/Support/MemoryBuffer.cpp | |
| parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
Notes
Diffstat (limited to 'lib/Support/MemoryBuffer.cpp')
| -rw-r--r-- | lib/Support/MemoryBuffer.cpp | 187 | 
1 files changed, 83 insertions, 104 deletions
| diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index dcd55299213b9..5f4b7daae53d1 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -12,34 +12,26 @@  //===----------------------------------------------------------------------===//  #include "llvm/Support/MemoryBuffer.h" -#include "llvm/ADT/OwningPtr.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/Config/config.h" +#include "llvm/Support/Errc.h"  #include "llvm/Support/Errno.h"  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/MathExtras.h"  #include "llvm/Support/Path.h"  #include "llvm/Support/Process.h"  #include "llvm/Support/Program.h" -#include "llvm/Support/system_error.h"  #include <cassert>  #include <cerrno>  #include <cstdio>  #include <cstring>  #include <new> -#include <sys/stat.h>  #include <sys/types.h> +#include <system_error>  #if !defined(_MSC_VER) && !defined(__MINGW32__)  #include <unistd.h>  #else  #include <io.h> -// Simplistic definitinos of these macros for use in getOpenFile. -#ifndef S_ISREG -#define S_ISREG(x) (1) -#endif -#ifndef S_ISBLK -#define S_ISBLK(x) (0) -#endif  #endif  using namespace llvm; @@ -91,12 +83,12 @@ public:      init(InputData.begin(), InputData.end(), RequiresNullTerminator);    } -  virtual const char *getBufferIdentifier() const LLVM_OVERRIDE { +  const char *getBufferIdentifier() const override {       // The name is stored after the class itself.      return reinterpret_cast<const char*>(this + 1);    } -  virtual BufferKind getBufferKind() const LLVM_OVERRIDE { +  BufferKind getBufferKind() const override {      return MemoryBuffer_Malloc;    }  }; @@ -117,7 +109,7 @@ MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,  MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,                                               StringRef BufferName) {    MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName); -  if (!Buf) return 0; +  if (!Buf) return nullptr;    memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),           InputData.size());    return Buf; @@ -131,12 +123,13 @@ MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,                                                    StringRef BufferName) {    // Allocate space for the MemoryBuffer, the data and the name. It is important    // that MemoryBuffer and data are aligned so PointerIntPair works with them. +  // TODO: Is 16-byte alignment enough?  We copy small object files with large +  // alignment expectations into this buffer.    size_t AlignedStringLen = -    RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1, -                       sizeof(void*)); // TODO: Is sizeof(void*) enough? +      RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1, 16);    size_t RealLen = AlignedStringLen + Size + 1;    char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow)); -  if (!Mem) return 0; +  if (!Mem) return nullptr;    // The name is stored after the class itself.    CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName); @@ -154,24 +147,19 @@ MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,  /// the MemoryBuffer object.  MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {    MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); -  if (!SB) return 0; +  if (!SB) return nullptr;    memset(const_cast<char*>(SB->getBufferStart()), 0, Size);    return SB;  } - -/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin -/// if the Filename is "-".  If an error occurs, this returns null and fills -/// in *ErrStr with a reason.  If stdin is empty, this API (unlike getSTDIN) -/// returns an empty buffer. -error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename, -                                        OwningPtr<MemoryBuffer> &result, -                                        int64_t FileSize) { +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFileOrSTDIN(StringRef Filename, int64_t FileSize) {    if (Filename == "-") -    return getSTDIN(result); -  return getFile(Filename, result, FileSize); +    return getSTDIN(); +  return getFile(Filename, FileSize);  } +  //===----------------------------------------------------------------------===//  // MemoryBuffer::getFile implementation.  //===----------------------------------------------------------------------===// @@ -197,7 +185,7 @@ class MemoryBufferMMapFile : public MemoryBuffer {  public:    MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len, -                       uint64_t Offset, error_code EC) +                       uint64_t Offset, std::error_code EC)        : MFR(FD, false, sys::fs::mapped_file_region::readonly,              getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {      if (!EC) { @@ -206,20 +194,19 @@ public:      }    } -  virtual const char *getBufferIdentifier() const LLVM_OVERRIDE { +  const char *getBufferIdentifier() const override {      // The name is stored after the class itself.      return reinterpret_cast<const char *>(this + 1);    } -  virtual BufferKind getBufferKind() const LLVM_OVERRIDE { +  BufferKind getBufferKind() const override {      return MemoryBuffer_MMap;    }  };  } -static error_code getMemoryBufferForStream(int FD, -                                           StringRef BufferName, -                                           OwningPtr<MemoryBuffer> &result) { +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getMemoryBufferForStream(int FD, StringRef BufferName) {    const ssize_t ChunkSize = 4096*4;    SmallString<ChunkSize> Buffer;    ssize_t ReadBytes; @@ -229,47 +216,48 @@ static error_code getMemoryBufferForStream(int FD,      ReadBytes = read(FD, Buffer.end(), ChunkSize);      if (ReadBytes == -1) {        if (errno == EINTR) continue; -      return error_code(errno, posix_category()); +      return std::error_code(errno, std::generic_category());      }      Buffer.set_size(Buffer.size() + ReadBytes);    } while (ReadBytes != 0); -  result.reset(MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); -  return error_code::success(); +  std::unique_ptr<MemoryBuffer> Ret( +      MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); +  return std::move(Ret);  } -static error_code getFileAux(const char *Filename, -                             OwningPtr<MemoryBuffer> &result, int64_t FileSize, -                             bool RequiresNullTerminator); +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getFileAux(const char *Filename, int64_t FileSize, bool RequiresNullTerminator, +           bool IsVolatileSize); -error_code MemoryBuffer::getFile(Twine Filename, -                                 OwningPtr<MemoryBuffer> &result, -                                 int64_t FileSize, -                                 bool RequiresNullTerminator) { +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFile(Twine Filename, int64_t FileSize, +                      bool RequiresNullTerminator, bool IsVolatileSize) {    // Ensure the path is null terminated.    SmallString<256> PathBuf;    StringRef NullTerminatedName = Filename.toNullTerminatedStringRef(PathBuf); -  return getFileAux(NullTerminatedName.data(), result, FileSize, -                    RequiresNullTerminator); +  return getFileAux(NullTerminatedName.data(), FileSize, RequiresNullTerminator, +                    IsVolatileSize);  } -static error_code getOpenFileImpl(int FD, const char *Filename, -                                  OwningPtr<MemoryBuffer> &Result, -                                  uint64_t FileSize, uint64_t MapSize, -                                  int64_t Offset, bool RequiresNullTerminator); +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, +                uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, +                bool IsVolatileSize); -static error_code getFileAux(const char *Filename, -                             OwningPtr<MemoryBuffer> &result, int64_t FileSize, -                             bool RequiresNullTerminator) { +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getFileAux(const char *Filename, int64_t FileSize, bool RequiresNullTerminator, +           bool IsVolatileSize) {    int FD; -  error_code EC = sys::fs::openFileForRead(Filename, FD); +  std::error_code EC = sys::fs::openFileForRead(Filename, FD);    if (EC)      return EC; -  error_code ret = getOpenFileImpl(FD, Filename, result, FileSize, FileSize, 0, -                                   RequiresNullTerminator); +  ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = +      getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, +                      RequiresNullTerminator, IsVolatileSize);    close(FD); -  return ret; +  return Ret;  }  static bool shouldUseMmap(int FD, @@ -277,7 +265,14 @@ static bool shouldUseMmap(int FD,                            size_t MapSize,                            off_t Offset,                            bool RequiresNullTerminator, -                          int PageSize) { +                          int PageSize, +                          bool IsVolatileSize) { +  // mmap may leave the buffer without null terminator if the file size changed +  // by the time the last page is mapped in, so avoid it if the file size is +  // likely to change. +  if (IsVolatileSize) +    return false; +    // We don't use mmap for small files because this can severely fragment our    // address space.    if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize) @@ -293,9 +288,8 @@ static bool shouldUseMmap(int FD,    // RequiresNullTerminator = false and MapSize != -1.    if (FileSize == size_t(-1)) {      sys::fs::file_status Status; -    error_code EC = sys::fs::status(FD, Status); -    if (EC) -      return EC; +    if (sys::fs::status(FD, Status)) +      return false;      FileSize = Status.getSize();    } @@ -306,15 +300,6 @@ static bool shouldUseMmap(int FD,    if (End != FileSize)      return false; -#if defined(_WIN32) || defined(__CYGWIN__) -  // Don't peek the next page if file is multiple of *physical* pagesize(4k) -  // but is not multiple of AllocationGranularity(64k), -  // when a null terminator is required. -  // FIXME: It's not good to hardcode 4096 here. dwPageSize shows 4096. -  if ((FileSize & (4096 - 1)) == 0) -    return false; -#endif -    // Don't try to map files that are exactly a multiple of the system page size    // if we need a null terminator.    if ((FileSize & (PageSize -1)) == 0) @@ -323,10 +308,10 @@ static bool shouldUseMmap(int FD,    return true;  } -static error_code getOpenFileImpl(int FD, const char *Filename, -                                  OwningPtr<MemoryBuffer> &result, -                                  uint64_t FileSize, uint64_t MapSize, -                                  int64_t Offset, bool RequiresNullTerminator) { +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, +                uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, +                bool IsVolatileSize) {    static int PageSize = sys::process::get_self()->page_size();    // Default is to map the full file. @@ -335,7 +320,7 @@ static error_code getOpenFileImpl(int FD, const char *Filename,      // file descriptor is cheaper than stat on a random path.      if (FileSize == uint64_t(-1)) {        sys::fs::file_status Status; -      error_code EC = sys::fs::status(FD, Status); +      std::error_code EC = sys::fs::status(FD, Status);        if (EC)          return EC; @@ -345,7 +330,7 @@ static error_code getOpenFileImpl(int FD, const char *Filename,        sys::fs::file_type Type = Status.type();        if (Type != sys::fs::file_type::regular_file &&            Type != sys::fs::file_type::block_file) -        return getMemoryBufferForStream(FD, Filename, result); +        return getMemoryBufferForStream(FD, Filename);        FileSize = Status.getSize();      } @@ -353,12 +338,13 @@ static error_code getOpenFileImpl(int FD, const char *Filename,    }    if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, -                    PageSize)) { -    error_code EC; -    result.reset(new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile( -        RequiresNullTerminator, FD, MapSize, Offset, EC)); +                    PageSize, IsVolatileSize)) { +    std::error_code EC; +    std::unique_ptr<MemoryBuffer> Result( +        new (NamedBufferAlloc(Filename)) +        MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC));      if (!EC) -      return error_code::success(); +      return std::move(Result);    }    MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); @@ -368,13 +354,13 @@ static error_code getOpenFileImpl(int FD, const char *Filename,      return make_error_code(errc::not_enough_memory);    } -  OwningPtr<MemoryBuffer> SB(Buf); +  std::unique_ptr<MemoryBuffer> SB(Buf);    char *BufPtr = const_cast<char*>(SB->getBufferStart());    size_t BytesLeft = MapSize;  #ifndef HAVE_PREAD    if (lseek(FD, Offset, SEEK_SET) == -1) -    return error_code(errno, posix_category()); +    return std::error_code(errno, std::generic_category());  #endif    while (BytesLeft) { @@ -387,46 +373,39 @@ static error_code getOpenFileImpl(int FD, const char *Filename,        if (errno == EINTR)          continue;        // Error while reading. -      return error_code(errno, posix_category()); +      return std::error_code(errno, std::generic_category());      }      if (NumRead == 0) { -      assert(0 && "We got inaccurate FileSize value or fstat reported an " -                   "invalid file size."); -      *BufPtr = '\0'; // null-terminate at the actual size. +      memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.        break;      }      BytesLeft -= NumRead;      BufPtr += NumRead;    } -  result.swap(SB); -  return error_code::success(); +  return std::move(SB);  } -error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, -                                     OwningPtr<MemoryBuffer> &Result, -                                     uint64_t FileSize, -                                     bool RequiresNullTerminator) { -  return getOpenFileImpl(FD, Filename, Result, FileSize, FileSize, 0, -                         RequiresNullTerminator); +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getOpenFile(int FD, const char *Filename, uint64_t FileSize, +                          bool RequiresNullTerminator, bool IsVolatileSize) { +  return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, +                         RequiresNullTerminator, IsVolatileSize);  } -error_code MemoryBuffer::getOpenFileSlice(int FD, const char *Filename, -                                          OwningPtr<MemoryBuffer> &Result, -                                          uint64_t MapSize, int64_t Offset) { -  return getOpenFileImpl(FD, Filename, Result, -1, MapSize, Offset, false); +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, +                               int64_t Offset, bool IsVolatileSize) { +  return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false, +                         IsVolatileSize);  } -//===----------------------------------------------------------------------===// -// MemoryBuffer::getSTDIN implementation. -//===----------------------------------------------------------------------===// - -error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { +ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {    // Read in all of the data from stdin, we cannot mmap stdin.    //    // FIXME: That isn't necessarily true, we should try to mmap stdin and    // fallback if it fails.    sys::ChangeStdinToBinary(); -  return getMemoryBufferForStream(0, "<stdin>", result); +  return getMemoryBufferForStream(0, "<stdin>");  } | 
