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.