Coverage Report

Created: 2024-01-17 10:31

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