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"
27#include
28#include
29#include
30#include
31#include <sys/types.h>
32#include <system_error>
33#if !defined(_MSC_VER) && !defined(__MINGW32__)
34#include <unistd.h>
35#else
36#include <io.h>
37#endif
38
39using namespace llvm;
40
41
42
43
44
46
47
48
50 bool RequiresNullTerminator) {
51 assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
52 "Buffer is not null terminated!");
53 BufferStart = BufStart;
54 BufferEnd = BufEnd;
55}
56
57
58
59
60
61
62
68
69namespace {
70struct NamedBufferAlloc {
71 const Twine &Name;
72 NamedBufferAlloc(const Twine &Name) : Name(Name) {}
73};
74}
75
76void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
79
80
81
82
83
84
85
86 char *Mem =
87 static_cast<char *>(std::malloc(N + sizeof(size_t) + NameRef.size() + 1));
88 if (!Mem)
90 *reinterpret_cast<size_t *>(Mem + N) = NameRef.size();
92 return Mem;
93}
94
95namespace {
96
97template
98class MemoryBufferMem : public MB {
99public:
100 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
102 RequiresNullTerminator);
103 }
104
105
106
107 void operator delete(void *p) { std::free(p); }
108
109 StringRef getBufferIdentifier() const override {
110
111 return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t),
112 *reinterpret_cast<const size_t *>(this + 1));
113 }
114
117 }
118};
119}
120
121template
124 bool IsText, bool RequiresNullTerminator, bool IsVolatile,
125 std::optional Alignment);
126
127std::unique_ptr
129 bool RequiresNullTerminator) {
130 auto *Ret = new (NamedBufferAlloc(BufferName))
131 MemoryBufferMem(InputData, RequiresNullTerminator);
132 return std::unique_ptr(Ret);
133}
134
135std::unique_ptr
137 return std::unique_ptr(getMemBuffer(
138 Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
139}
140
143 auto Buf =
145 if (!Buf)
147
148
149 llvm::copy(InputData, Buf->getBufferStart());
150 return std::move(Buf);
151}
152
153std::unique_ptr
156 if (Buf)
157 return std::move(*Buf);
158 return nullptr;
159}
160
163 bool RequiresNullTerminator,
164 std::optional Alignment) {
166
168 StringRef NameRef = Filename.toStringRef(NameBuf);
169
170 if (NameRef == "-")
172 return getFile(Filename, IsText, RequiresNullTerminator,
173 false, Alignment);
174}
175
179 std::optional Alignment) {
181
183 false, IsVolatile,
184 Alignment);
185}
186
187
188
189
190
191namespace {
192
193template
196template <>
199template <>
202template <>
205
206
207
208
209template
210class MemoryBufferMMapFile : public MB {
212
215 }
216
218 return Len + (Offset - getLegalMapOffset(Offset));
219 }
220
221 const char *getStart(uint64_t Len, uint64_t Offset) {
223 }
224
225public:
226 MemoryBufferMMapFile(bool RequiresNullTerminator, sys::fs::file_t FD, uint64_t Len,
227 uint64_t Offset, std::error_code &EC)
228 : MFR(FD, Mapmode, getLegalMapSize(Len, Offset),
229 getLegalMapOffset(Offset), EC) {
230 if (!EC) {
231 const char *Start = getStart(Len, Offset);
233 }
234 }
235
236
237
238 void operator delete(void *p) { std::free(p); }
239
240 StringRef getBufferIdentifier() const override {
241
242 return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t),
243 *reinterpret_cast<const size_t *>(this + 1));
244 }
245
248 }
249
250 void dontNeedIfMmap() override { MFR.dontNeed(); }
251};
252}
253
261
264 bool RequiresNullTerminator, bool IsVolatile,
265 std::optional Alignment) {
267
269 IsText, RequiresNullTerminator, IsVolatile,
270 Alignment);
271}
272
273template
276 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
277 bool IsVolatile, std::optional Alignment);
278
279template
282 bool IsText, bool RequiresNullTerminator, bool IsVolatile,
283 std::optional Alignment) {
286 if (!FDOrErr)
290 RequiresNullTerminator, IsVolatile, Alignment);
292 return Ret;
293}
294
297 std::optional Alignment) {
299
301 Filename, -1, 0, false,
302 false, IsVolatile, Alignment);
303}
304
308 std::optional Alignment) {
310
312 Filename, MapSize, Offset, false,
313 false, IsVolatile, Alignment);
314}
315
316std::unique_ptr
318 const Twine &BufferName,
319 std::optional Alignment) {
320 using MemBuffer = MemoryBufferMem;
321
322
323 Align BufAlign = Alignment.value_or(Align(16));
324
325
326
329
330 size_t StringLen = sizeof(MemBuffer) + sizeof(size_t) + NameRef.size() + 1;
331 size_t RealLen = StringLen + Size + 1 + BufAlign.value();
332 if (RealLen <= Size)
333 return nullptr;
334
335
336
337
338
339
340
341 char *Mem = static_cast<char *>(std::malloc(RealLen));
342 if (!Mem)
343 return nullptr;
344
345
346 *reinterpret_cast<size_t *>(Mem + sizeof(MemBuffer)) = NameRef.size();
347 CopyStringRef(Mem + sizeof(MemBuffer) + sizeof(size_t), NameRef);
348
349
350 char *Buf = (char *)alignAddr(Mem + StringLen, BufAlign);
351 Buf[Size] = 0;
352
353 auto *Ret = new (Mem) MemBuffer(StringRef(Buf, Size), true);
354 return std::unique_ptr(Ret);
355}
356
357std::unique_ptr
360 if (!SB)
361 return nullptr;
362 memset(SB->getBufferStart(), 0, Size);
363 return SB;
364}
365
367 size_t FileSize,
368 size_t MapSize,
370 bool RequiresNullTerminator,
372 bool IsVolatile) {
373#if defined(__MVS__)
374
375 return false;
376#endif
377
378
379
380
381 if (IsVolatile && RequiresNullTerminator)
382 return false;
383
384
385
386 if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
387 return false;
388
389 if (!RequiresNullTerminator)
390 return true;
391
392
393
394
395
396 if (FileSize == size_t(-1)) {
399 return false;
400 FileSize = Status.getSize();
401 }
402
403
404
405 size_t End = Offset + MapSize;
406 assert(End <= FileSize);
407 if (End != FileSize)
408 return false;
409
410
411
412 if ((FileSize & (PageSize -1)) == 0)
413 return false;
414
415#if defined(__CYGWIN__)
416
417
418
419 if ((FileSize & (4096 - 1)) == 0)
420 return false;
421#endif
422
423 return true;
424}
425
431 if (!FDOrErr)
434
435
436 if (MapSize == uint64_t(-1)) {
437
438
439 if (FileSize == uint64_t(-1)) {
442 if (EC)
443 return EC;
444
445
446
451
452 FileSize = Status.getSize();
453 }
454 MapSize = FileSize;
455 }
456
457 std::error_code EC;
458 std::unique_ptr Result(
459 new (NamedBufferAlloc(Filename))
460 MemoryBufferMMapFile(false, FD, MapSize,
462 if (EC)
463 return EC;
464 return std::move(Result);
465}
466
473
474
482
483template
486 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
487 bool IsVolatile, std::optional Alignment) {
489
490
491 if (MapSize == uint64_t(-1)) {
492
493
494 if (FileSize == uint64_t(-1)) {
497 if (EC)
498 return EC;
499
500
501
502
507
508 FileSize = Status.getSize();
509 }
510 MapSize = FileSize;
511 }
512
515 std::error_code EC;
516 std::unique_ptr Result(
517 new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(
518 RequiresNullTerminator, FD, MapSize, Offset, EC));
519 if (!EC) {
520
521
522
523
524 if (!RequiresNullTerminator || *Result->getBufferEnd() == '\0')
525 return std::move(Result);
526 }
527 }
528
529#ifdef __MVS__
530 ErrorOr NeedsConversion = needConversion(Filename, FD);
531 if (std::error_code EC = NeedsConversion.getError())
532 return EC;
533
534
535
536
537
538 if (*NeedsConversion && Offset == 0 && MapSize == FileSize)
540#endif
541
542 auto Buf =
544 if (!Buf) {
545
546
548 }
549
550
552 while (!ToRead.empty()) {
555 if (!ReadBytes)
557 if (*ReadBytes == 0) {
558 std::memset(ToRead.data(), 0, ToRead.size());
559 break;
560 }
561 ToRead = ToRead.drop_front(*ReadBytes);
562 Offset += *ReadBytes;
563 }
564
565 return std::move(Buf);
566}
567
570 uint64_t FileSize, bool RequiresNullTerminator,
571 bool IsVolatile, std::optional Alignment) {
573
575 RequiresNullTerminator, IsVolatile,
576 Alignment);
577}
578
581 bool IsVolatile, std::optional Alignment) {
583
585
587 IsVolatile, Alignment);
588}
589
592
593
594
595
596
598
600}
601
605
608 if (!FDOrErr)
614 return Ret;
615}
616
622
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:366
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:281
static ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, uint64_t Offset)
Definition MemoryBuffer.cpp:427
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:485
static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getMemBufferCopyImpl(StringRef InputData, const Twine &BufferName)
Definition MemoryBuffer.cpp:142
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:63
static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName)
Definition MemoryBuffer.cpp:255
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:569
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition MemoryBuffer.cpp:128
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:154
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:579
void init(const char *BufStart, const char *BufEnd, bool RequiresNullTerminator)
init - Initialize this MemoryBuffer as a reference to externally allocated memory,...
Definition MemoryBuffer.cpp:49
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:603
MemoryBufferRef getMemBufferRef() const
Definition MemoryBuffer.cpp:617
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:162
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:177
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:263
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
Definition MemoryBuffer.cpp:590
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:358
static LLVM_ABI ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getFile(const Twine &Filename, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Definition MemoryBuffer.cpp:296
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:317
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:306
static LLVM_ABI ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1)
Definition MemoryBuffer.cpp:468
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:476
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.
void violationIfEnabled()
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.