1
//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This file implements the MemoryBuffer interface.
12
//===----------------------------------------------------------------------===//
14
#include "llvm/Support/MemoryBuffer.h"
15
#include "llvm/ADT/OwningPtr.h"
16
#include "llvm/ADT/SmallString.h"
17
#include "llvm/System/Path.h"
18
#include "llvm/System/Process.h"
19
#include "llvm/System/Program.h"
24
#include <sys/types.h>
26
#if !defined(_MSC_VER) && !defined(__MINGW32__)
35
//===----------------------------------------------------------------------===//
36
// MemoryBuffer implementation itself.
37
//===----------------------------------------------------------------------===//
39
MemoryBuffer::~MemoryBuffer() {
41
free((void*)BufferStart);
44
/// initCopyOf - Initialize this source buffer with a copy of the specified
45
/// memory range. We make the copy so that we can null terminate it
47
void MemoryBuffer::initCopyOf(const char *BufStart, const char *BufEnd) {
48
size_t Size = BufEnd-BufStart;
49
BufferStart = (char *)malloc(Size+1);
50
BufferEnd = BufferStart+Size;
51
memcpy(const_cast<char*>(BufferStart), BufStart, Size);
52
*const_cast<char*>(BufferEnd) = 0; // Null terminate buffer.
53
MustDeleteBuffer = true;
56
/// init - Initialize this MemoryBuffer as a reference to externally allocated
57
/// memory, memory that we know is already null terminated.
58
void MemoryBuffer::init(const char *BufStart, const char *BufEnd) {
59
assert(BufEnd[0] == 0 && "Buffer is not null terminated!");
60
BufferStart = BufStart;
62
MustDeleteBuffer = false;
65
//===----------------------------------------------------------------------===//
66
// MemoryBufferMem implementation.
67
//===----------------------------------------------------------------------===//
70
class MemoryBufferMem : public MemoryBuffer {
73
MemoryBufferMem(const char *Start, const char *End, StringRef FID,
79
initCopyOf(Start, End);
82
virtual const char *getBufferIdentifier() const {
83
return FileID.c_str();
88
/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
89
/// that EndPtr[0] must be a null byte and be accessible!
90
MemoryBuffer *MemoryBuffer::getMemBuffer(const char *StartPtr,
92
const char *BufferName) {
93
return new MemoryBufferMem(StartPtr, EndPtr, BufferName);
96
/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
97
/// copying the contents and taking ownership of it. This has no requirements
99
MemoryBuffer *MemoryBuffer::getMemBufferCopy(const char *StartPtr,
101
const char *BufferName) {
102
return new MemoryBufferMem(StartPtr, EndPtr, BufferName, true);
105
/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
106
/// that is completely initialized to zeros. Note that the caller should
107
/// initialize the memory allocated by this method. The memory is owned by
108
/// the MemoryBuffer object.
109
MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
110
StringRef BufferName) {
111
char *Buf = (char *)malloc(Size+1);
114
MemoryBufferMem *SB = new MemoryBufferMem(Buf, Buf+Size, BufferName);
115
// The memory for this buffer is owned by the MemoryBuffer.
116
SB->MustDeleteBuffer = true;
120
/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
121
/// is completely initialized to zeros. Note that the caller should
122
/// initialize the memory allocated by this method. The memory is owned by
123
/// the MemoryBuffer object.
124
MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size,
125
const char *BufferName) {
126
MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
128
memset(const_cast<char*>(SB->getBufferStart()), 0, Size+1);
133
/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
134
/// if the Filename is "-". If an error occurs, this returns null and fills
135
/// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN)
136
/// returns an empty buffer.
137
MemoryBuffer *MemoryBuffer::getFileOrSTDIN(StringRef Filename,
142
return getFile(Filename, ErrStr, FileSize);
145
//===----------------------------------------------------------------------===//
146
// MemoryBuffer::getFile implementation.
147
//===----------------------------------------------------------------------===//
150
/// MemoryBufferMMapFile - This represents a file that was mapped in with the
151
/// sys::Path::MapInFilePages method. When destroyed, it calls the
152
/// sys::Path::UnMapFilePages method.
153
class MemoryBufferMMapFile : public MemoryBuffer {
154
std::string Filename;
156
MemoryBufferMMapFile(StringRef filename, const char *Pages, uint64_t Size)
157
: Filename(filename) {
158
init(Pages, Pages+Size);
161
virtual const char *getBufferIdentifier() const {
162
return Filename.c_str();
165
~MemoryBufferMMapFile() {
166
sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
171
MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr,
175
OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
177
SmallString<256> PathBuf(Filename.begin(), Filename.end());
178
int FD = ::open(PathBuf.c_str(), O_RDONLY|OpenFlags);
180
if (ErrStr) *ErrStr = strerror(errno);
184
// If we don't know the file size, use fstat to find out. fstat on an open
185
// file descriptor is cheaper than stat on a random path.
186
if (FileSize == -1) {
187
struct stat FileInfo;
188
// TODO: This should use fstat64 when available.
189
if (fstat(FD, &FileInfo) == -1) {
190
if (ErrStr) *ErrStr = strerror(errno);
194
FileSize = FileInfo.st_size;
198
// If the file is large, try to use mmap to read it in. We don't use mmap
199
// for small files, because this can severely fragment our address space. Also
200
// don't try to map files that are exactly a multiple of the system page size,
201
// as the file would not have the required null terminator.
203
// FIXME: Can we just mmap an extra page in the latter case?
204
if (FileSize >= 4096*4 &&
205
(FileSize & (sys::Process::GetPageSize()-1)) != 0) {
206
if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
207
// Close the file descriptor, now that the whole file is in memory.
209
return new MemoryBufferMMapFile(Filename, Pages, FileSize);
213
MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename);
215
// Failed to create a buffer.
216
if (ErrStr) *ErrStr = "could not allocate buffer";
221
OwningPtr<MemoryBuffer> SB(Buf);
222
char *BufPtr = const_cast<char*>(SB->getBufferStart());
224
size_t BytesLeft = FileSize;
226
ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
228
BytesLeft -= NumRead;
230
} else if (NumRead == -1 && errno == EINTR) {
234
if (ErrStr) *ErrStr = strerror(errno);
244
//===----------------------------------------------------------------------===//
245
// MemoryBuffer::getSTDIN implementation.
246
//===----------------------------------------------------------------------===//
249
class STDINBufferFile : public MemoryBuffer {
251
virtual const char *getBufferIdentifier() const {
257
MemoryBuffer *MemoryBuffer::getSTDIN() {
260
std::vector<char> FileData;
262
// Read in all of the data from stdin, we cannot mmap stdin.
264
// FIXME: That isn't necessarily true, we should try to mmap stdin and
265
// fallback if it fails.
266
sys::Program::ChangeStdinToBinary();
269
ReadBytes = fread(Buffer, sizeof(char), sizeof(Buffer), stdin);
270
FileData.insert(FileData.end(), Buffer, Buffer+ReadBytes);
271
} while (ReadBytes == sizeof(Buffer));
273
FileData.push_back(0); // &FileData[Size] is invalid. So is &*FileData.end().
274
size_t Size = FileData.size();
275
MemoryBuffer *B = new STDINBufferFile();
276
B->initCopyOf(&FileData[0], &FileData[Size-1]);