LLVM: lib/Support/MemoryBuffer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
16#include "llvm/Config/config.h"
26#include
27#include
28#include
29#include
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
42
43
45
46
47
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
58
59
60
61
67
68namespace {
69struct NamedBufferAlloc {
70 const Twine &Name;
71 NamedBufferAlloc(const Twine &Name) : Name(Name) {}
72};
73}
74
75void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
78
79
80
81
82
83
84
85 char *Mem =
86 static_cast<char *>(std::malloc(N + sizeof(size_t) + NameRef.size() + 1));
87 if (!Mem)
89 *reinterpret_cast<size_t *>(Mem + N) = NameRef.size();
91 return Mem;
92}
93
94namespace {
95
96template
97class MemoryBufferMem : public MB {
98public:
99 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
101 RequiresNullTerminator);
102 }
103
104
105
106 void operator delete(void *p) { std::free(p); }
107
108 StringRef getBufferIdentifier() const override {
109
110 return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t),
111 *reinterpret_cast<const size_t *>(this + 1));
112 }
113
116 }
117};
118}
119
120template
123 bool IsText, bool RequiresNullTerminator, bool IsVolatile,
124 std::optional Alignment);
125
126std::unique_ptr
128 bool RequiresNullTerminator) {
129 auto *Ret = new (NamedBufferAlloc(BufferName))
130 MemoryBufferMem(InputData, RequiresNullTerminator);
131 return std::unique_ptr(Ret);
132}
133
134std::unique_ptr
136 return std::unique_ptr(getMemBuffer(
137 Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
138}
139
142 auto Buf =
144 if (!Buf)
146
147
148 llvm::copy(InputData, Buf->getBufferStart());
149 return std::move(Buf);
150}
151
152std::unique_ptr
155 if (Buf)
156 return std::move(*Buf);
157 return nullptr;
158}
159
162 bool RequiresNullTerminator,
163 std::optional Alignment) {
165 StringRef NameRef = Filename.toStringRef(NameBuf);
166
167 if (NameRef == "-")
169 return getFile(Filename, IsText, RequiresNullTerminator,
170 false, Alignment);
171}
172
176 std::optional Alignment) {
178 false, IsVolatile,
179 Alignment);
180}
181
182
183
184
185
186namespace {
187
188template
191template <>
194template <>
197template <>
200
201
202
203
204template
205class MemoryBufferMMapFile : public MB {
207
210 }
211
213 return Len + (Offset - getLegalMapOffset(Offset));
214 }
215
216 const char *getStart(uint64_t Len, uint64_t 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, getLegalMapSize(Len, Offset),
224 getLegalMapOffset(Offset), EC) {
225 if (!EC) {
226 const char *Start = getStart(Len, Offset);
228 }
229 }
230
231
232
233 void operator delete(void *p) { std::free(p); }
234
235 StringRef getBufferIdentifier() const override {
236
237 return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t),
238 *reinterpret_cast<const size_t *>(this + 1));
239 }
240
243 }
244
245 void dontNeedIfMmap() override { MFR.dontNeed(); }
246};
247}
248
256
259 bool RequiresNullTerminator, bool IsVolatile,
260 std::optional Alignment) {
262 IsText, RequiresNullTerminator, IsVolatile,
263 Alignment);
264}
265
266template
269 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
270 bool IsVolatile, std::optional Alignment);
271
272template
275 bool IsText, bool RequiresNullTerminator, bool IsVolatile,
276 std::optional Alignment) {
279 if (!FDOrErr)
283 RequiresNullTerminator, IsVolatile, Alignment);
285 return Ret;
286}
287
290 std::optional Alignment) {
292 Filename, -1, 0, false,
293 false, IsVolatile, Alignment);
294}
295
299 std::optional Alignment) {
301 Filename, MapSize, Offset, false,
302 false, IsVolatile, Alignment);
303}
304
305std::unique_ptr
307 const Twine &BufferName,
308 std::optional Alignment) {
309 using MemBuffer = MemoryBufferMem;
310
311
312 Align BufAlign = Alignment.value_or(Align(16));
313
314
315
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)
322 return nullptr;
323
324
325
326
327
328
329
330 char *Mem = static_cast<char *>(std::malloc(RealLen));
331 if (!Mem)
332 return nullptr;
333
334
335 *reinterpret_cast<size_t *>(Mem + sizeof(MemBuffer)) = NameRef.size();
336 CopyStringRef(Mem + sizeof(MemBuffer) + sizeof(size_t), NameRef);
337
338
339 char *Buf = (char *)alignAddr(Mem + StringLen, BufAlign);
340 Buf[Size] = 0;
341
342 auto *Ret = new (Mem) MemBuffer(StringRef(Buf, Size), true);
343 return std::unique_ptr(Ret);
344}
345
346std::unique_ptr
349 if (!SB)
350 return nullptr;
351 memset(SB->getBufferStart(), 0, Size);
352 return SB;
353}
354
356 size_t FileSize,
357 size_t MapSize,
359 bool RequiresNullTerminator,
361 bool IsVolatile) {
362#if defined(__MVS__)
363
364 return false;
365#endif
366
367
368
369
370 if (IsVolatile && RequiresNullTerminator)
371 return false;
372
373
374
375 if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
376 return false;
377
378 if (!RequiresNullTerminator)
379 return true;
380
381
382
383
384
385 if (FileSize == size_t(-1)) {
388 return false;
389 FileSize = Status.getSize();
390 }
391
392
393
394 size_t End = Offset + MapSize;
395 assert(End <= FileSize);
396 if (End != FileSize)
397 return false;
398
399
400
401 if ((FileSize & (PageSize -1)) == 0)
402 return false;
403
404#if defined(__CYGWIN__)
405
406
407
408 if ((FileSize & (4096 - 1)) == 0)
409 return false;
410#endif
411
412 return true;
413}
414
420 if (!FDOrErr)
423
424
425 if (MapSize == uint64_t(-1)) {
426
427
428 if (FileSize == uint64_t(-1)) {
431 if (EC)
432 return EC;
433
434
435
440
441 FileSize = Status.getSize();
442 }
443 MapSize = FileSize;
444 }
445
446 std::error_code EC;
447 std::unique_ptr Result(
448 new (NamedBufferAlloc(Filename))
449 MemoryBufferMMapFile(false, FD, MapSize,
451 if (EC)
452 return EC;
453 return std::move(Result);
454}
455
460
461
467
468template
471 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
472 bool IsVolatile, std::optional Alignment) {
474
475
476 if (MapSize == uint64_t(-1)) {
477
478
479 if (FileSize == uint64_t(-1)) {
482 if (EC)
483 return EC;
484
485
486
487
492
493 FileSize = Status.getSize();
494 }
495 MapSize = FileSize;
496 }
497
500 std::error_code EC;
501 std::unique_ptr Result(
502 new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(
503 RequiresNullTerminator, FD, MapSize, Offset, EC));
504 if (!EC) {
505
506
507
508
509 if (!RequiresNullTerminator || *Result->getBufferEnd() == '\0')
510 return std::move(Result);
511 }
512 }
513
514#ifdef __MVS__
515 ErrorOr NeedsConversion = needConversion(Filename, FD);
516 if (std::error_code EC = NeedsConversion.getError())
517 return EC;
518
519
520
521
522
523 if (*NeedsConversion && Offset == 0 && MapSize == FileSize)
525#endif
526
527 auto Buf =
529 if (!Buf) {
530
531
533 }
534
535
537 while (!ToRead.empty()) {
540 if (!ReadBytes)
542 if (*ReadBytes == 0) {
543 std::memset(ToRead.data(), 0, ToRead.size());
544 break;
545 }
546 ToRead = ToRead.drop_front(*ReadBytes);
547 Offset += *ReadBytes;
548 }
549
550 return std::move(Buf);
551}
552
555 uint64_t FileSize, bool RequiresNullTerminator,
556 bool IsVolatile, std::optional Alignment) {
558 RequiresNullTerminator, IsVolatile,
559 Alignment);
560}
561
564 bool IsVolatile, std::optional Alignment) {
567 IsVolatile, Alignment);
568}
569
579
584 if (!FDOrErr)
590 return Ret;
591}
592
598
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Prepare AGPR Alloc
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
static bool shouldUseMmap(sys::fs::file_t FD, size_t FileSize, size_t MapSize, off_t Offset, bool RequiresNullTerminator, int PageSize, bool IsVolatile)
Definition MemoryBuffer.cpp:355
static ErrorOr< std::unique_ptr< MB > > getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsText, bool RequiresNullTerminator, bool IsVolatile, std::optional< Align > Alignment)
Definition MemoryBuffer.cpp:274
static ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, uint64_t Offset)
Definition MemoryBuffer.cpp:416
static ErrorOr< std::unique_ptr< MB > > getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatile, std::optional< Align > Alignment)
Definition MemoryBuffer.cpp:470
static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getMemBufferCopyImpl(StringRef InputData, const Twine &BufferName)
Definition MemoryBuffer.cpp:141
static void CopyStringRef(char *Memory, StringRef Data)
CopyStringRef - Copies contents of a StringRef into a block of memory and null-terminates it.
Definition MemoryBuffer.cpp:62
static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName)
Definition MemoryBuffer.cpp:250
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the SmallString class.
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
Definition MemoryBuffer.cpp:554
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition MemoryBuffer.cpp:127
BufferKind
The kind of memory backing used to support the MemoryBuffer.
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Definition MemoryBuffer.cpp:153
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, map some slice of it into a MemoryBuffer.
Definition MemoryBuffer.cpp:562
void init(const char *BufStart, const char *BufEnd, bool RequiresNullTerminator)
init - Initialize this MemoryBuffer as a reference to externally allocated memory,...
Definition MemoryBuffer.cpp:48
StringRef getBuffer() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileAsStream(const Twine &Filename)
Read all of the specified file into a MemoryBuffer as a stream (i.e.
Definition MemoryBuffer.cpp:581
MemoryBufferRef getMemBufferRef() const
Definition MemoryBuffer.cpp:593
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
Definition MemoryBuffer.cpp:161
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Map a subrange of the specified file as a MemoryBuffer.
Definition MemoryBuffer.cpp:174
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Definition MemoryBuffer.cpp:258
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
Definition MemoryBuffer.cpp:570
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
MutableArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
~SmallVectorMemoryBuffer() override
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
Definition MemoryBuffer.cpp:347
static LLVM_ABI ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getFile(const Twine &Filename, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Definition MemoryBuffer.cpp:289
static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)
Allocate a new MemoryBuffer of the specified size that is not initialized.
Definition MemoryBuffer.cpp:306
static LLVM_ABI ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Map a subrange of the specified file as a WritableMemoryBuffer.
Definition MemoryBuffer.cpp:297
static LLVM_ABI ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1)
Definition MemoryBuffer.cpp:457
static LLVM_ABI ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset)
Map a subrange of the specified file as a ReadWriteMemoryBuffer.
Definition MemoryBuffer.cpp:463
This class provides various memory handling functions that manipulate MemoryBlock instances.
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
Represents the result of a call to sys::fs::status().
This class represents a memory mapped file.
static LLVM_ABI int alignment()
@ priv
May modify via data, but changes are lost on destruction.
@ readonly
May only access map via const_data as read only.
@ readwrite
May access map via data and modify it. Written to path.
LLVM_ABI const char * const_data() const
Get a const view of the data.
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
LLVM_ABI Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl< char > &Buffer, ssize_t ChunkSize=DefaultReadChunkSize)
Reads from FileHandle until EOF, appending to Buffer in chunks of size ChunkSize.
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
file_type
An enumeration for the file system's view of the type.
@ CD_OpenExisting
CD_OpenExisting - When opening a file:
LLVM_ABI Expected< size_t > readNativeFileSlice(file_t FileHandle, MutableArrayRef< char > Buf, uint64_t Offset)
Reads Buf.size() bytes from FileHandle at offset Offset into Buf.
Expected< file_t > openNativeFileForReadWrite(const Twine &Name, CreationDisposition Disp, OpenFlags Flags, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
LLVM_ABI std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
LLVM_ABI file_t getStdinHandle()
Return an open handle to standard in.
LLVM_ABI std::error_code ChangeStdinMode(fs::OpenFlags Flags)
This is an optimization pass for GlobalISel generic memory operations.
std::error_code make_error_code(BitcodeError E)
@ Ref
The access may reference the value stored in memory.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
OutputIt copy(R &&Range, OutputIt Out)
LLVM_ABI std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
LLVM_ABI void report_bad_alloc_error(const char *Reason, bool GenCrashDiag=true)
Reports a bad alloc error, calling any user defined bad alloc error handler.
uintptr_t alignAddr(const void *Addr, Align Alignment)
Aligns Addr to Alignment bytes, rounding up.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.