blob: d3c71b992889450156ab9e50d488db49fce4da53 [file] [log] [blame]
Chris Lattner333ffd42007-04-29 06:58:52 +00001//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattner333ffd42007-04-29 06:58:52 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the MemoryBuffer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Support/MemoryBuffer.h"
Chris Lattner11da4cf2008-04-01 06:05:21 +000015#include "llvm/ADT/OwningPtr.h"
16#include "llvm/ADT/SmallString.h"
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000017#include "llvm/Support/MathExtras.h"
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000018#include "llvm/Support/Errno.h"
19#include "llvm/Support/Path.h"
20#include "llvm/Support/Process.h"
21#include "llvm/Support/Program.h"
Michael J. Spencer333fb042010-12-09 17:36:48 +000022#include "llvm/Support/system_error.h"
Jeff Cohen9bc40602007-04-29 14:21:44 +000023#include <cassert>
Chris Lattner333ffd42007-04-29 06:58:52 +000024#include <cstdio>
25#include <cstring>
26#include <cerrno>
Chris Lattner11da4cf2008-04-01 06:05:21 +000027#include <sys/types.h>
28#include <sys/stat.h>
29#if !defined(_MSC_VER) && !defined(__MINGW32__)
30#include <unistd.h>
31#include <sys/uio.h>
Chris Lattner11da4cf2008-04-01 06:05:21 +000032#else
33#include <io.h>
34#endif
Gabor Greif88110802008-04-30 08:53:22 +000035#include <fcntl.h>
Chris Lattner333ffd42007-04-29 06:58:52 +000036using namespace llvm;
37
Michael J. Spencer3ff95632010-12-16 03:29:14 +000038namespace { const llvm::error_code success; }
39
Chris Lattner333ffd42007-04-29 06:58:52 +000040//===----------------------------------------------------------------------===//
41// MemoryBuffer implementation itself.
42//===----------------------------------------------------------------------===//
43
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000044MemoryBuffer::~MemoryBuffer() { }
Chris Lattner333ffd42007-04-29 06:58:52 +000045
46/// init - Initialize this MemoryBuffer as a reference to externally allocated
47/// memory, memory that we know is already null terminated.
48void MemoryBuffer::init(const char *BufStart, const char *BufEnd) {
49 assert(BufEnd[0] == 0 && "Buffer is not null terminated!");
50 BufferStart = BufStart;
51 BufferEnd = BufEnd;
Chris Lattner333ffd42007-04-29 06:58:52 +000052}
53
54//===----------------------------------------------------------------------===//
55// MemoryBufferMem implementation.
56//===----------------------------------------------------------------------===//
57
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000058/// CopyStringRef - Copies contents of a StringRef into a block of memory and
59/// null-terminates it.
60static void CopyStringRef(char *Memory, StringRef Data) {
61 memcpy(Memory, Data.data(), Data.size());
62 Memory[Data.size()] = 0; // Null terminate string.
63}
64
65/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
66template <typename T>
67static T* GetNamedBuffer(StringRef Buffer, StringRef Name) {
68 char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1));
69 CopyStringRef(Mem + sizeof(T), Name);
70 return new (Mem) T(Buffer);
71}
72
Chris Lattner333ffd42007-04-29 06:58:52 +000073namespace {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000074/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
Chris Lattner333ffd42007-04-29 06:58:52 +000075class MemoryBufferMem : public MemoryBuffer {
Chris Lattner333ffd42007-04-29 06:58:52 +000076public:
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000077 MemoryBufferMem(StringRef InputData) {
78 init(InputData.begin(), InputData.end());
Chris Lattner333ffd42007-04-29 06:58:52 +000079 }
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000080
Chris Lattner333ffd42007-04-29 06:58:52 +000081 virtual const char *getBufferIdentifier() const {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000082 // The name is stored after the class itself.
83 return reinterpret_cast<const char*>(this + 1);
Chris Lattner333ffd42007-04-29 06:58:52 +000084 }
85};
86}
87
88/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
89/// that EndPtr[0] must be a null byte and be accessible!
Chris Lattner4c842dd2010-04-05 22:42:30 +000090MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000091 StringRef BufferName) {
92 return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName);
Chris Lattner333ffd42007-04-29 06:58:52 +000093}
94
Chris Lattner3daae272007-10-09 21:46:38 +000095/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
96/// copying the contents and taking ownership of it. This has no requirements
97/// on EndPtr[0].
Chris Lattner4c842dd2010-04-05 22:42:30 +000098MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000099 StringRef BufferName) {
100 MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
101 if (!Buf) return 0;
102 memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
103 InputData.size());
104 return Buf;
Chris Lattner3daae272007-10-09 21:46:38 +0000105}
106
Chris Lattner333ffd42007-04-29 06:58:52 +0000107/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000108/// that is not initialized. Note that the caller should initialize the
109/// memory allocated by this method. The memory is owned by the MemoryBuffer
110/// object.
Evan Cheng34cd4a42008-05-05 18:30:58 +0000111MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
Daniel Dunbard65267e2009-11-10 00:43:58 +0000112 StringRef BufferName) {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000113 // Allocate space for the MemoryBuffer, the data and the name. It is important
114 // that MemoryBuffer and data are aligned so PointerIntPair works with them.
115 size_t AlignedStringLen =
116 RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
117 sizeof(void*)); // TODO: Is sizeof(void*) enough?
118 size_t RealLen = AlignedStringLen + Size + 1;
119 char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
120 if (!Mem) return 0;
121
122 // The name is stored after the class itself.
123 CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);
124
125 // The buffer begins after the name and must be aligned.
126 char *Buf = Mem + AlignedStringLen;
127 Buf[Size] = 0; // Null terminate buffer.
128
129 return new (Mem) MemoryBufferMem(StringRef(Buf, Size));
Chris Lattner333ffd42007-04-29 06:58:52 +0000130}
131
132/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
133/// is completely initialized to zeros. Note that the caller should
134/// initialize the memory allocated by this method. The memory is owned by
135/// the MemoryBuffer object.
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000136MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
Chris Lattner333ffd42007-04-29 06:58:52 +0000137 MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
Evan Cheng726135a2009-02-13 07:54:34 +0000138 if (!SB) return 0;
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000139 memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
Chris Lattner333ffd42007-04-29 06:58:52 +0000140 return SB;
141}
142
143
Chris Lattner2b1f1062007-11-18 18:52:28 +0000144/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
145/// if the Filename is "-". If an error occurs, this returns null and fills
146/// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN)
147/// returns an empty buffer.
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000148error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename,
149 OwningPtr<MemoryBuffer> &result,
150 int64_t FileSize) {
Daniel Dunbard65267e2009-11-10 00:43:58 +0000151 if (Filename == "-")
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000152 return getSTDIN(result);
153 return getFile(Filename, result, FileSize);
Chris Lattner2b1f1062007-11-18 18:52:28 +0000154}
155
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000156error_code MemoryBuffer::getFileOrSTDIN(const char *Filename,
157 OwningPtr<MemoryBuffer> &result,
158 int64_t FileSize) {
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000159 if (strcmp(Filename, "-") == 0)
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000160 return getSTDIN(result);
161 return getFile(Filename, result, FileSize);
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000162}
163
Chris Lattner333ffd42007-04-29 06:58:52 +0000164//===----------------------------------------------------------------------===//
Chris Lattner333ffd42007-04-29 06:58:52 +0000165// MemoryBuffer::getFile implementation.
166//===----------------------------------------------------------------------===//
167
Chris Lattner11da4cf2008-04-01 06:05:21 +0000168namespace {
169/// MemoryBufferMMapFile - This represents a file that was mapped in with the
170/// sys::Path::MapInFilePages method. When destroyed, it calls the
171/// sys::Path::UnMapFilePages method.
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000172class MemoryBufferMMapFile : public MemoryBufferMem {
Chris Lattner11da4cf2008-04-01 06:05:21 +0000173public:
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000174 MemoryBufferMMapFile(StringRef Buffer)
175 : MemoryBufferMem(Buffer) { }
176
Chris Lattner11da4cf2008-04-01 06:05:21 +0000177 ~MemoryBufferMMapFile() {
178 sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
179 }
180};
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000181
182/// FileCloser - RAII object to make sure an FD gets closed properly.
183class FileCloser {
184 int FD;
185public:
Dan Gohman455164b2010-06-22 13:53:29 +0000186 explicit FileCloser(int FD) : FD(FD) {}
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000187 ~FileCloser() { ::close(FD); }
188};
Chris Lattner11da4cf2008-04-01 06:05:21 +0000189}
190
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000191error_code MemoryBuffer::getFile(StringRef Filename,
192 OwningPtr<MemoryBuffer> &result,
193 int64_t FileSize) {
Chris Lattner7cf70542010-11-23 22:20:27 +0000194 // Ensure the path is null terminated.
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000195 SmallString<256> PathBuf(Filename.begin(), Filename.end());
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000196 return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize);
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000197}
198
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000199error_code MemoryBuffer::getFile(const char *Filename,
200 OwningPtr<MemoryBuffer> &result,
201 int64_t FileSize) {
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000202 int OpenFlags = O_RDONLY;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000203#ifdef O_BINARY
Bill Wendlinga4420062008-04-01 22:09:20 +0000204 OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
Chris Lattner11da4cf2008-04-01 06:05:21 +0000205#endif
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000206 int FD = ::open(Filename, OpenFlags);
Chris Lattner333ffd42007-04-29 06:58:52 +0000207 if (FD == -1) {
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000208 return error_code(errno, posix_category());
Chris Lattner333ffd42007-04-29 06:58:52 +0000209 }
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000210
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000211 return getOpenFile(FD, Filename, result, FileSize);
Chris Lattner7cf70542010-11-23 22:20:27 +0000212}
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000213
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000214error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
215 OwningPtr<MemoryBuffer> &result,
216 int64_t FileSize) {
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000217 FileCloser FC(FD); // Close FD on return.
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000218
Chris Lattner11da4cf2008-04-01 06:05:21 +0000219 // If we don't know the file size, use fstat to find out. fstat on an open
220 // file descriptor is cheaper than stat on a random path.
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000221 if (FileSize == -1) {
222 struct stat FileInfo;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000223 // TODO: This should use fstat64 when available.
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000224 if (fstat(FD, &FileInfo) == -1) {
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000225 return error_code(errno, posix_category());
Chris Lattner11da4cf2008-04-01 06:05:21 +0000226 }
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000227 FileSize = FileInfo.st_size;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000228 }
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000229
230
Chris Lattner11da4cf2008-04-01 06:05:21 +0000231 // If the file is large, try to use mmap to read it in. We don't use mmap
232 // for small files, because this can severely fragment our address space. Also
233 // don't try to map files that are exactly a multiple of the system page size,
234 // as the file would not have the required null terminator.
Daniel Dunbard65267e2009-11-10 00:43:58 +0000235 //
236 // FIXME: Can we just mmap an extra page in the latter case?
Chris Lattner11da4cf2008-04-01 06:05:21 +0000237 if (FileSize >= 4096*4 &&
238 (FileSize & (sys::Process::GetPageSize()-1)) != 0) {
239 if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000240 result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
241 StringRef(Pages, FileSize), Filename));
242 return success;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000243 }
244 }
Evan Cheng726135a2009-02-13 07:54:34 +0000245
246 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename);
247 if (!Buf) {
Michael J. Spencer333fb042010-12-09 17:36:48 +0000248 // Failed to create a buffer. The only way it can fail is if
249 // new(std::nothrow) returns 0.
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000250 return make_error_code(errc::not_enough_memory);
Evan Cheng726135a2009-02-13 07:54:34 +0000251 }
252
253 OwningPtr<MemoryBuffer> SB(Buf);
Chris Lattner11da4cf2008-04-01 06:05:21 +0000254 char *BufPtr = const_cast<char*>(SB->getBufferStart());
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000255
Evan Cheng34cd4a42008-05-05 18:30:58 +0000256 size_t BytesLeft = FileSize;
Chris Lattner333ffd42007-04-29 06:58:52 +0000257 while (BytesLeft) {
258 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000259 if (NumRead == -1) {
260 if (errno == EINTR)
261 continue;
262 // Error while reading.
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000263 return error_code(errno, posix_category());
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000264 } else if (NumRead == 0) {
Benjamin Kramerd48c1f92010-04-01 14:39:55 +0000265 // We hit EOF early, truncate and terminate buffer.
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000266 Buf->BufferEnd = BufPtr;
Benjamin Kramerd48c1f92010-04-01 14:39:55 +0000267 *BufPtr = 0;
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000268 result.swap(SB);
269 return success;
Chris Lattner333ffd42007-04-29 06:58:52 +0000270 }
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000271 BytesLeft -= NumRead;
272 BufPtr += NumRead;
Chris Lattner333ffd42007-04-29 06:58:52 +0000273 }
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000274
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000275 result.swap(SB);
276 return success;
Chris Lattner333ffd42007-04-29 06:58:52 +0000277}
278
Chris Lattner333ffd42007-04-29 06:58:52 +0000279//===----------------------------------------------------------------------===//
280// MemoryBuffer::getSTDIN implementation.
281//===----------------------------------------------------------------------===//
282
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000283error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) {
Chris Lattner333ffd42007-04-29 06:58:52 +0000284 // Read in all of the data from stdin, we cannot mmap stdin.
Daniel Dunbard65267e2009-11-10 00:43:58 +0000285 //
286 // FIXME: That isn't necessarily true, we should try to mmap stdin and
287 // fallback if it fails.
Jeff Cohen0fea8eb2007-05-07 15:21:46 +0000288 sys::Program::ChangeStdinToBinary();
Benjamin Kramer831338b2010-06-25 16:07:18 +0000289
290 const ssize_t ChunkSize = 4096*4;
291 SmallString<ChunkSize> Buffer;
292 ssize_t ReadBytes;
293 // Read into Buffer until we hit EOF.
Eli Friedman96cd7af2009-05-18 08:44:04 +0000294 do {
Benjamin Kramer831338b2010-06-25 16:07:18 +0000295 Buffer.reserve(Buffer.size() + ChunkSize);
296 ReadBytes = read(0, Buffer.end(), ChunkSize);
297 if (ReadBytes == -1) {
298 if (errno == EINTR) continue;
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000299 return error_code(errno, posix_category());
Benjamin Kramer831338b2010-06-25 16:07:18 +0000300 }
301 Buffer.set_size(Buffer.size() + ReadBytes);
302 } while (ReadBytes != 0);
Reid Spencer2372ccc2007-08-08 20:01:58 +0000303
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000304 result.reset(getMemBufferCopy(Buffer, "<stdin>"));
305 return success;
Chris Lattner333ffd42007-04-29 06:58:52 +0000306}