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/Support/MathExtras.h"
18 #include "llvm/Support/Errno.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/Process.h"
21 #include "llvm/Support/Program.h"
22 #include "llvm/Support/system_error.h"
27 #include <sys/types.h>
29 #if !defined(_MSC_VER) && !defined(__MINGW32__)
38 //===----------------------------------------------------------------------===//
39 // MemoryBuffer implementation itself.
40 //===----------------------------------------------------------------------===//
42 MemoryBuffer::~MemoryBuffer() { }
44 /// init - Initialize this MemoryBuffer as a reference to externally allocated
45 /// memory, memory that we know is already null terminated.
46 void MemoryBuffer::init(const char *BufStart, const char *BufEnd) {
47 assert(BufEnd[0] == 0 && "Buffer is not null terminated!");
48 BufferStart = BufStart;
52 //===----------------------------------------------------------------------===//
53 // MemoryBufferMem implementation.
54 //===----------------------------------------------------------------------===//
56 /// CopyStringRef - Copies contents of a StringRef into a block of memory and
57 /// null-terminates it.
58 static void CopyStringRef(char *Memory, StringRef Data) {
59 memcpy(Memory, Data.data(), Data.size());
60 Memory[Data.size()] = 0; // Null terminate string.
63 /// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
65 static T* GetNamedBuffer(StringRef Buffer, StringRef Name) {
66 char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1));
67 CopyStringRef(Mem + sizeof(T), Name);
68 return new (Mem) T(Buffer);
72 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
73 class MemoryBufferMem : public MemoryBuffer {
75 MemoryBufferMem(StringRef InputData) {
76 init(InputData.begin(), InputData.end());
79 virtual const char *getBufferIdentifier() const {
80 // The name is stored after the class itself.
81 return reinterpret_cast<const char*>(this + 1);
86 /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
87 /// that EndPtr[0] must be a null byte and be accessible!
88 MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
89 StringRef BufferName) {
90 return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName);
93 /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
94 /// copying the contents and taking ownership of it. This has no requirements
96 MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
97 StringRef BufferName) {
98 MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
100 memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
105 /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
106 /// that is not initialized. Note that the caller should initialize the
107 /// memory allocated by this method. The memory is owned by the MemoryBuffer
109 MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
110 StringRef BufferName) {
111 // Allocate space for the MemoryBuffer, the data and the name. It is important
112 // that MemoryBuffer and data are aligned so PointerIntPair works with them.
113 size_t AlignedStringLen =
114 RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
115 sizeof(void*)); // TODO: Is sizeof(void*) enough?
116 size_t RealLen = AlignedStringLen + Size + 1;
117 char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
120 // The name is stored after the class itself.
121 CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);
123 // The buffer begins after the name and must be aligned.
124 char *Buf = Mem + AlignedStringLen;
125 Buf[Size] = 0; // Null terminate buffer.
127 return new (Mem) MemoryBufferMem(StringRef(Buf, Size));
130 /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
131 /// is completely initialized to zeros. Note that the caller should
132 /// initialize the memory allocated by this method. The memory is owned by
133 /// the MemoryBuffer object.
134 MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
135 MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
137 memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
142 /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
143 /// if the Filename is "-". If an error occurs, this returns null and fills
144 /// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN)
145 /// returns an empty buffer.
146 MemoryBuffer *MemoryBuffer::getFileOrSTDIN(StringRef Filename,
151 return getFile(Filename, ec, FileSize);
154 MemoryBuffer *MemoryBuffer::getFileOrSTDIN(const char *Filename,
157 if (strcmp(Filename, "-") == 0)
159 return getFile(Filename, ec, FileSize);
162 //===----------------------------------------------------------------------===//
163 // MemoryBuffer::getFile implementation.
164 //===----------------------------------------------------------------------===//
167 /// MemoryBufferMMapFile - This represents a file that was mapped in with the
168 /// sys::Path::MapInFilePages method. When destroyed, it calls the
169 /// sys::Path::UnMapFilePages method.
170 class MemoryBufferMMapFile : public MemoryBufferMem {
172 MemoryBufferMMapFile(StringRef Buffer)
173 : MemoryBufferMem(Buffer) { }
175 ~MemoryBufferMMapFile() {
176 sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
180 /// FileCloser - RAII object to make sure an FD gets closed properly.
184 explicit FileCloser(int FD) : FD(FD) {}
185 ~FileCloser() { ::close(FD); }
189 MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, error_code &ec,
191 // Ensure the path is null terminated.
192 SmallString<256> PathBuf(Filename.begin(), Filename.end());
193 return MemoryBuffer::getFile(PathBuf.c_str(), ec, FileSize);
196 MemoryBuffer *MemoryBuffer::getFile(const char *Filename, error_code &ec,
198 int OpenFlags = O_RDONLY;
200 OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
202 int FD = ::open(Filename, OpenFlags);
204 ec = error_code(errno, posix_category());
208 return getOpenFile(FD, Filename, ec, FileSize);
211 MemoryBuffer *MemoryBuffer::getOpenFile(int FD, const char *Filename,
212 error_code &ec, int64_t FileSize) {
213 FileCloser FC(FD); // Close FD on return.
215 // If we don't know the file size, use fstat to find out. fstat on an open
216 // file descriptor is cheaper than stat on a random path.
217 if (FileSize == -1) {
218 struct stat FileInfo;
219 // TODO: This should use fstat64 when available.
220 if (fstat(FD, &FileInfo) == -1) {
221 ec = error_code(errno, posix_category());
224 FileSize = FileInfo.st_size;
228 // If the file is large, try to use mmap to read it in. We don't use mmap
229 // for small files, because this can severely fragment our address space. Also
230 // don't try to map files that are exactly a multiple of the system page size,
231 // as the file would not have the required null terminator.
233 // FIXME: Can we just mmap an extra page in the latter case?
234 if (FileSize >= 4096*4 &&
235 (FileSize & (sys::Process::GetPageSize()-1)) != 0) {
236 if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
237 return GetNamedBuffer<MemoryBufferMMapFile>(StringRef(Pages, FileSize),
242 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename);
244 // Failed to create a buffer. The only way it can fail is if
245 // new(std::nothrow) returns 0.
246 ec = make_error_code(errc::not_enough_memory);
250 OwningPtr<MemoryBuffer> SB(Buf);
251 char *BufPtr = const_cast<char*>(SB->getBufferStart());
253 size_t BytesLeft = FileSize;
255 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
259 // Error while reading.
260 ec = error_code(errno, posix_category());
262 } else if (NumRead == 0) {
263 // We hit EOF early, truncate and terminate buffer.
264 Buf->BufferEnd = BufPtr;
268 BytesLeft -= NumRead;
275 //===----------------------------------------------------------------------===//
276 // MemoryBuffer::getSTDIN implementation.
277 //===----------------------------------------------------------------------===//
279 MemoryBuffer *MemoryBuffer::getSTDIN(error_code &ec) {
280 // Read in all of the data from stdin, we cannot mmap stdin.
282 // FIXME: That isn't necessarily true, we should try to mmap stdin and
283 // fallback if it fails.
284 sys::Program::ChangeStdinToBinary();
286 const ssize_t ChunkSize = 4096*4;
287 SmallString<ChunkSize> Buffer;
289 // Read into Buffer until we hit EOF.
291 Buffer.reserve(Buffer.size() + ChunkSize);
292 ReadBytes = read(0, Buffer.end(), ChunkSize);
293 if (ReadBytes == -1) {
294 if (errno == EINTR) continue;
295 ec = error_code(errno, posix_category());
298 Buffer.set_size(Buffer.size() + ReadBytes);
299 } while (ReadBytes != 0);
301 return getMemBufferCopy(Buffer, "<stdin>");