Home | History | Annotate | Line # | Download | only in Support
      1 //===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 //  This file implements the MemoryBuffer interface.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "llvm/Support/MemoryBuffer.h"
     14 #include "llvm/ADT/SmallString.h"
     15 #include "llvm/Config/config.h"
     16 #include "llvm/Support/AutoConvert.h"
     17 #include "llvm/Support/Errc.h"
     18 #include "llvm/Support/Errno.h"
     19 #include "llvm/Support/FileSystem.h"
     20 #include "llvm/Support/MathExtras.h"
     21 #include "llvm/Support/Path.h"
     22 #include "llvm/Support/Process.h"
     23 #include "llvm/Support/Program.h"
     24 #include "llvm/Support/SmallVectorMemoryBuffer.h"
     25 #include <cassert>
     26 #include <cerrno>
     27 #include <cstring>
     28 #include <new>
     29 #include <sys/types.h>
     30 #include <system_error>
     31 #if !defined(_MSC_VER) && !defined(__MINGW32__)
     32 #include <unistd.h>
     33 #else
     34 #include <io.h>
     35 #endif
     36 using namespace llvm;
     37 
     38 //===----------------------------------------------------------------------===//
     39 // MemoryBuffer implementation itself.
     40 //===----------------------------------------------------------------------===//
     41 
     42 MemoryBuffer::~MemoryBuffer() { }
     43 
     44 /// init - Initialize this MemoryBuffer as a reference to externally allocated
     45 /// memory, memory that we know is already null terminated.
     46 void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
     47                         bool RequiresNullTerminator) {
     48   assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
     49          "Buffer is not null terminated!");
     50   BufferStart = BufStart;
     51   BufferEnd = BufEnd;
     52 }
     53 
     54 //===----------------------------------------------------------------------===//
     55 // MemoryBufferMem implementation.
     56 //===----------------------------------------------------------------------===//
     57 
     58 /// CopyStringRef - Copies contents of a StringRef into a block of memory and
     59 /// null-terminates it.
     60 static void CopyStringRef(char *Memory, StringRef Data) {
     61   if (!Data.empty())
     62     memcpy(Memory, Data.data(), Data.size());
     63   Memory[Data.size()] = 0; // Null terminate string.
     64 }
     65 
     66 namespace {
     67 struct NamedBufferAlloc {
     68   const Twine &Name;
     69   NamedBufferAlloc(const Twine &Name) : Name(Name) {}
     70 };
     71 } // namespace
     72 
     73 void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
     74   SmallString<256> NameBuf;
     75   StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
     76 
     77   char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1));
     78   CopyStringRef(Mem + N, NameRef);
     79   return Mem;
     80 }
     81 
     82 namespace {
     83 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
     84 template<typename MB>
     85 class MemoryBufferMem : public MB {
     86 public:
     87   MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
     88     MemoryBuffer::init(InputData.begin(), InputData.end(),
     89                        RequiresNullTerminator);
     90   }
     91 
     92   /// Disable sized deallocation for MemoryBufferMem, because it has
     93   /// tail-allocated data.
     94   void operator delete(void *p) { ::operator delete(p); }
     95 
     96   StringRef getBufferIdentifier() const override {
     97     // The name is stored after the class itself.
     98     return StringRef(reinterpret_cast<const char *>(this + 1));
     99   }
    100 
    101   MemoryBuffer::BufferKind getBufferKind() const override {
    102     return MemoryBuffer::MemoryBuffer_Malloc;
    103   }
    104 };
    105 } // namespace
    106 
    107 template <typename MB>
    108 static ErrorOr<std::unique_ptr<MB>>
    109 getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
    110            bool IsText, bool RequiresNullTerminator, bool IsVolatile);
    111 
    112 std::unique_ptr<MemoryBuffer>
    113 MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
    114                            bool RequiresNullTerminator) {
    115   auto *Ret = new (NamedBufferAlloc(BufferName))
    116       MemoryBufferMem<MemoryBuffer>(InputData, RequiresNullTerminator);
    117   return std::unique_ptr<MemoryBuffer>(Ret);
    118 }
    119 
    120 std::unique_ptr<MemoryBuffer>
    121 MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) {
    122   return std::unique_ptr<MemoryBuffer>(getMemBuffer(
    123       Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
    124 }
    125 
    126 static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
    127 getMemBufferCopyImpl(StringRef InputData, const Twine &BufferName) {
    128   auto Buf = WritableMemoryBuffer::getNewUninitMemBuffer(InputData.size(), BufferName);
    129   if (!Buf)
    130     return make_error_code(errc::not_enough_memory);
    131   memcpy(Buf->getBufferStart(), InputData.data(), InputData.size());
    132   return std::move(Buf);
    133 }
    134 
    135 std::unique_ptr<MemoryBuffer>
    136 MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) {
    137   auto Buf = getMemBufferCopyImpl(InputData, BufferName);
    138   if (Buf)
    139     return std::move(*Buf);
    140   return nullptr;
    141 }
    142 
    143 ErrorOr<std::unique_ptr<MemoryBuffer>>
    144 MemoryBuffer::getFileOrSTDIN(const Twine &Filename, bool IsText,
    145                              bool RequiresNullTerminator) {
    146   SmallString<256> NameBuf;
    147   StringRef NameRef = Filename.toStringRef(NameBuf);
    148 
    149   if (NameRef == "-")
    150     return getSTDIN();
    151   return getFile(Filename, IsText, RequiresNullTerminator,
    152                  /*IsVolatile=*/false);
    153 }
    154 
    155 ErrorOr<std::unique_ptr<MemoryBuffer>>
    156 MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
    157                            uint64_t Offset, bool IsVolatile) {
    158   return getFileAux<MemoryBuffer>(FilePath, MapSize, Offset, /*IsText=*/false,
    159                                   /*RequiresNullTerminator=*/false, IsVolatile);
    160 }
    161 
    162 //===----------------------------------------------------------------------===//
    163 // MemoryBuffer::getFile implementation.
    164 //===----------------------------------------------------------------------===//
    165 
    166 namespace {
    167 
    168 template <typename MB>
    169 constexpr sys::fs::mapped_file_region::mapmode Mapmode =
    170     sys::fs::mapped_file_region::readonly;
    171 template <>
    172 constexpr sys::fs::mapped_file_region::mapmode Mapmode<MemoryBuffer> =
    173     sys::fs::mapped_file_region::readonly;
    174 template <>
    175 constexpr sys::fs::mapped_file_region::mapmode Mapmode<WritableMemoryBuffer> =
    176     sys::fs::mapped_file_region::priv;
    177 template <>
    178 constexpr sys::fs::mapped_file_region::mapmode
    179     Mapmode<WriteThroughMemoryBuffer> = sys::fs::mapped_file_region::readwrite;
    180 
    181 /// Memory maps a file descriptor using sys::fs::mapped_file_region.
    182 ///
    183 /// This handles converting the offset into a legal offset on the platform.
    184 template<typename MB>
    185 class MemoryBufferMMapFile : public MB {
    186   sys::fs::mapped_file_region MFR;
    187 
    188   static uint64_t getLegalMapOffset(uint64_t Offset) {
    189     return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
    190   }
    191 
    192   static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
    193     return Len + (Offset - getLegalMapOffset(Offset));
    194   }
    195 
    196   const char *getStart(uint64_t Len, uint64_t Offset) {
    197     return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
    198   }
    199 
    200 public:
    201   MemoryBufferMMapFile(bool RequiresNullTerminator, sys::fs::file_t FD, uint64_t Len,
    202                        uint64_t Offset, std::error_code &EC)
    203       : MFR(FD, Mapmode<MB>, getLegalMapSize(Len, Offset),
    204             getLegalMapOffset(Offset), EC) {
    205     if (!EC) {
    206       const char *Start = getStart(Len, Offset);
    207       MemoryBuffer::init(Start, Start + Len, RequiresNullTerminator);
    208     }
    209   }
    210 
    211   /// Disable sized deallocation for MemoryBufferMMapFile, because it has
    212   /// tail-allocated data.
    213   void operator delete(void *p) { ::operator delete(p); }
    214 
    215   StringRef getBufferIdentifier() const override {
    216     // The name is stored after the class itself.
    217     return StringRef(reinterpret_cast<const char *>(this + 1));
    218   }
    219 
    220   MemoryBuffer::BufferKind getBufferKind() const override {
    221     return MemoryBuffer::MemoryBuffer_MMap;
    222   }
    223 };
    224 } // namespace
    225 
    226 static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
    227 getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName) {
    228   const ssize_t ChunkSize = 4096*4;
    229   SmallString<ChunkSize> Buffer;
    230   // Read into Buffer until we hit EOF.
    231   for (;;) {
    232     Buffer.reserve(Buffer.size() + ChunkSize);
    233     Expected<size_t> ReadBytes = sys::fs::readNativeFile(
    234         FD, makeMutableArrayRef(Buffer.end(), ChunkSize));
    235     if (!ReadBytes)
    236       return errorToErrorCode(ReadBytes.takeError());
    237     if (*ReadBytes == 0)
    238       break;
    239     Buffer.set_size(Buffer.size() + *ReadBytes);
    240   }
    241 
    242   return getMemBufferCopyImpl(Buffer, BufferName);
    243 }
    244 
    245 ErrorOr<std::unique_ptr<MemoryBuffer>>
    246 MemoryBuffer::getFile(const Twine &Filename, bool IsText,
    247                       bool RequiresNullTerminator, bool IsVolatile) {
    248   return getFileAux<MemoryBuffer>(Filename, /*MapSize=*/-1, /*Offset=*/0,
    249                                   IsText, RequiresNullTerminator, IsVolatile);
    250 }
    251 
    252 template <typename MB>
    253 static ErrorOr<std::unique_ptr<MB>>
    254 getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
    255                 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
    256                 bool IsVolatile);
    257 
    258 template <typename MB>
    259 static ErrorOr<std::unique_ptr<MB>>
    260 getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
    261            bool IsText, bool RequiresNullTerminator, bool IsVolatile) {
    262   Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForRead(
    263       Filename, IsText ? sys::fs::OF_TextWithCRLF : sys::fs::OF_None);
    264   if (!FDOrErr)
    265     return errorToErrorCode(FDOrErr.takeError());
    266   sys::fs::file_t FD = *FDOrErr;
    267   auto Ret = getOpenFileImpl<MB>(FD, Filename, /*FileSize=*/-1, MapSize, Offset,
    268                                  RequiresNullTerminator, IsVolatile);
    269   sys::fs::closeFile(FD);
    270   return Ret;
    271 }
    272 
    273 ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
    274 WritableMemoryBuffer::getFile(const Twine &Filename, bool IsVolatile) {
    275   return getFileAux<WritableMemoryBuffer>(
    276       Filename, /*MapSize=*/-1, /*Offset=*/0, /*IsText=*/false,
    277       /*RequiresNullTerminator=*/false, IsVolatile);
    278 }
    279 
    280 ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
    281 WritableMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize,
    282                                    uint64_t Offset, bool IsVolatile) {
    283   return getFileAux<WritableMemoryBuffer>(
    284       Filename, MapSize, Offset, /*IsText=*/false,
    285       /*RequiresNullTerminator=*/false, IsVolatile);
    286 }
    287 
    288 std::unique_ptr<WritableMemoryBuffer>
    289 WritableMemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
    290   using MemBuffer = MemoryBufferMem<WritableMemoryBuffer>;
    291   // Allocate space for the MemoryBuffer, the data and the name. It is important
    292   // that MemoryBuffer and data are aligned so PointerIntPair works with them.
    293   // TODO: Is 16-byte alignment enough?  We copy small object files with large
    294   // alignment expectations into this buffer.
    295   SmallString<256> NameBuf;
    296   StringRef NameRef = BufferName.toStringRef(NameBuf);
    297   size_t AlignedStringLen = alignTo(sizeof(MemBuffer) + NameRef.size() + 1, 16);
    298   size_t RealLen = AlignedStringLen + Size + 1;
    299   char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
    300   if (!Mem)
    301     return nullptr;
    302 
    303   // The name is stored after the class itself.
    304   CopyStringRef(Mem + sizeof(MemBuffer), NameRef);
    305 
    306   // The buffer begins after the name and must be aligned.
    307   char *Buf = Mem + AlignedStringLen;
    308   Buf[Size] = 0; // Null terminate buffer.
    309 
    310   auto *Ret = new (Mem) MemBuffer(StringRef(Buf, Size), true);
    311   return std::unique_ptr<WritableMemoryBuffer>(Ret);
    312 }
    313 
    314 std::unique_ptr<WritableMemoryBuffer>
    315 WritableMemoryBuffer::getNewMemBuffer(size_t Size, const Twine &BufferName) {
    316   auto SB = WritableMemoryBuffer::getNewUninitMemBuffer(Size, BufferName);
    317   if (!SB)
    318     return nullptr;
    319   memset(SB->getBufferStart(), 0, Size);
    320   return SB;
    321 }
    322 
    323 static bool shouldUseMmap(sys::fs::file_t FD,
    324                           size_t FileSize,
    325                           size_t MapSize,
    326                           off_t Offset,
    327                           bool RequiresNullTerminator,
    328                           int PageSize,
    329                           bool IsVolatile) {
    330   // mmap may leave the buffer without null terminator if the file size changed
    331   // by the time the last page is mapped in, so avoid it if the file size is
    332   // likely to change.
    333   if (IsVolatile && RequiresNullTerminator)
    334     return false;
    335 
    336   // We don't use mmap for small files because this can severely fragment our
    337   // address space.
    338   if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
    339     return false;
    340 
    341   if (!RequiresNullTerminator)
    342     return true;
    343 
    344   // If we don't know the file size, use fstat to find out.  fstat on an open
    345   // file descriptor is cheaper than stat on a random path.
    346   // FIXME: this chunk of code is duplicated, but it avoids a fstat when
    347   // RequiresNullTerminator = false and MapSize != -1.
    348   if (FileSize == size_t(-1)) {
    349     sys::fs::file_status Status;
    350     if (sys::fs::status(FD, Status))
    351       return false;
    352     FileSize = Status.getSize();
    353   }
    354 
    355   // If we need a null terminator and the end of the map is inside the file,
    356   // we cannot use mmap.
    357   size_t End = Offset + MapSize;
    358   assert(End <= FileSize);
    359   if (End != FileSize)
    360     return false;
    361 
    362   // Don't try to map files that are exactly a multiple of the system page size
    363   // if we need a null terminator.
    364   if ((FileSize & (PageSize -1)) == 0)
    365     return false;
    366 
    367 #if defined(__CYGWIN__)
    368   // Don't try to map files that are exactly a multiple of the physical page size
    369   // if we need a null terminator.
    370   // FIXME: We should reorganize again getPageSize() on Win32.
    371   if ((FileSize & (4096 - 1)) == 0)
    372     return false;
    373 #endif
    374 
    375   return true;
    376 }
    377 
    378 static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
    379 getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize,
    380                  uint64_t Offset) {
    381   Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForReadWrite(
    382       Filename, sys::fs::CD_OpenExisting, sys::fs::OF_None);
    383   if (!FDOrErr)
    384     return errorToErrorCode(FDOrErr.takeError());
    385   sys::fs::file_t FD = *FDOrErr;
    386 
    387   // Default is to map the full file.
    388   if (MapSize == uint64_t(-1)) {
    389     // If we don't know the file size, use fstat to find out.  fstat on an open
    390     // file descriptor is cheaper than stat on a random path.
    391     if (FileSize == uint64_t(-1)) {
    392       sys::fs::file_status Status;
    393       std::error_code EC = sys::fs::status(FD, Status);
    394       if (EC)
    395         return EC;
    396 
    397       // If this not a file or a block device (e.g. it's a named pipe
    398       // or character device), we can't mmap it, so error out.
    399       sys::fs::file_type Type = Status.type();
    400       if (Type != sys::fs::file_type::regular_file &&
    401           Type != sys::fs::file_type::block_file)
    402         return make_error_code(errc::invalid_argument);
    403 
    404       FileSize = Status.getSize();
    405     }
    406     MapSize = FileSize;
    407   }
    408 
    409   std::error_code EC;
    410   std::unique_ptr<WriteThroughMemoryBuffer> Result(
    411       new (NamedBufferAlloc(Filename))
    412           MemoryBufferMMapFile<WriteThroughMemoryBuffer>(false, FD, MapSize,
    413                                                          Offset, EC));
    414   if (EC)
    415     return EC;
    416   return std::move(Result);
    417 }
    418 
    419 ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
    420 WriteThroughMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize) {
    421   return getReadWriteFile(Filename, FileSize, FileSize, 0);
    422 }
    423 
    424 /// Map a subrange of the specified file as a WritableMemoryBuffer.
    425 ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
    426 WriteThroughMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize,
    427                                        uint64_t Offset) {
    428   return getReadWriteFile(Filename, -1, MapSize, Offset);
    429 }
    430 
    431 template <typename MB>
    432 static ErrorOr<std::unique_ptr<MB>>
    433 getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
    434                 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
    435                 bool IsVolatile) {
    436   static int PageSize = sys::Process::getPageSizeEstimate();
    437 
    438   // Default is to map the full file.
    439   if (MapSize == uint64_t(-1)) {
    440     // If we don't know the file size, use fstat to find out.  fstat on an open
    441     // file descriptor is cheaper than stat on a random path.
    442     if (FileSize == uint64_t(-1)) {
    443       sys::fs::file_status Status;
    444       std::error_code EC = sys::fs::status(FD, Status);
    445       if (EC)
    446         return EC;
    447 
    448       // If this not a file or a block device (e.g. it's a named pipe
    449       // or character device), we can't trust the size. Create the memory
    450       // buffer by copying off the stream.
    451       sys::fs::file_type Type = Status.type();
    452       if (Type != sys::fs::file_type::regular_file &&
    453           Type != sys::fs::file_type::block_file)
    454         return getMemoryBufferForStream(FD, Filename);
    455 
    456       FileSize = Status.getSize();
    457     }
    458     MapSize = FileSize;
    459   }
    460 
    461   if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
    462                     PageSize, IsVolatile)) {
    463     std::error_code EC;
    464     std::unique_ptr<MB> Result(
    465         new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile<MB>(
    466             RequiresNullTerminator, FD, MapSize, Offset, EC));
    467     if (!EC)
    468       return std::move(Result);
    469   }
    470 
    471 #ifdef __MVS__
    472   // Set codepage auto-conversion for z/OS.
    473   if (auto EC = llvm::enableAutoConversion(FD))
    474     return EC;
    475 #endif
    476 
    477   auto Buf = WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
    478   if (!Buf) {
    479     // Failed to create a buffer. The only way it can fail is if
    480     // new(std::nothrow) returns 0.
    481     return make_error_code(errc::not_enough_memory);
    482   }
    483 
    484   // Read until EOF, zero-initialize the rest.
    485   MutableArrayRef<char> ToRead = Buf->getBuffer();
    486   while (!ToRead.empty()) {
    487     Expected<size_t> ReadBytes =
    488         sys::fs::readNativeFileSlice(FD, ToRead, Offset);
    489     if (!ReadBytes)
    490       return errorToErrorCode(ReadBytes.takeError());
    491     if (*ReadBytes == 0) {
    492       std::memset(ToRead.data(), 0, ToRead.size());
    493       break;
    494     }
    495     ToRead = ToRead.drop_front(*ReadBytes);
    496     Offset += *ReadBytes;
    497   }
    498 
    499   return std::move(Buf);
    500 }
    501 
    502 ErrorOr<std::unique_ptr<MemoryBuffer>>
    503 MemoryBuffer::getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
    504                           bool RequiresNullTerminator, bool IsVolatile) {
    505   return getOpenFileImpl<MemoryBuffer>(FD, Filename, FileSize, FileSize, 0,
    506                          RequiresNullTerminator, IsVolatile);
    507 }
    508 
    509 ErrorOr<std::unique_ptr<MemoryBuffer>>
    510 MemoryBuffer::getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize,
    511                                int64_t Offset, bool IsVolatile) {
    512   assert(MapSize != uint64_t(-1));
    513   return getOpenFileImpl<MemoryBuffer>(FD, Filename, -1, MapSize, Offset, false,
    514                                        IsVolatile);
    515 }
    516 
    517 ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
    518   // Read in all of the data from stdin, we cannot mmap stdin.
    519   //
    520   // FIXME: That isn't necessarily true, we should try to mmap stdin and
    521   // fallback if it fails.
    522   sys::ChangeStdinMode(sys::fs::OF_Text);
    523 
    524   return getMemoryBufferForStream(sys::fs::getStdinHandle(), "<stdin>");
    525 }
    526 
    527 ErrorOr<std::unique_ptr<MemoryBuffer>>
    528 MemoryBuffer::getFileAsStream(const Twine &Filename) {
    529   Expected<sys::fs::file_t> FDOrErr =
    530       sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None);
    531   if (!FDOrErr)
    532     return errorToErrorCode(FDOrErr.takeError());
    533   sys::fs::file_t FD = *FDOrErr;
    534   ErrorOr<std::unique_ptr<MemoryBuffer>> Ret =
    535       getMemoryBufferForStream(FD, Filename);
    536   sys::fs::closeFile(FD);
    537   return Ret;
    538 }
    539 
    540 MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
    541   StringRef Data = getBuffer();
    542   StringRef Identifier = getBufferIdentifier();
    543   return MemoryBufferRef(Data, Identifier);
    544 }
    545 
    546 SmallVectorMemoryBuffer::~SmallVectorMemoryBuffer() {}
    547