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.