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