MemoryBuffer.cpp 20 KB

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