blob: 0966f9069f2d8b0fcfd954a2d9e205acba3a831a [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
38//===----------------------------------------------------------------------===//
39// MemoryBuffer implementation itself.
40//===----------------------------------------------------------------------===//
41
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000042MemoryBuffer::~MemoryBuffer() { }
Chris Lattner333ffd42007-04-29 06:58:52 +000043
44/// init - Initialize this MemoryBuffer as a reference to externally allocated
45/// memory, memory that we know is already null terminated.
46void MemoryBuffer::init(const char *BufStart, const char *BufEnd) {
47 assert(BufEnd[0] == 0 && "Buffer is not null terminated!");
48 BufferStart = BufStart;
49 BufferEnd = BufEnd;
Chris Lattner333ffd42007-04-29 06:58:52 +000050}
51
52//===----------------------------------------------------------------------===//
53// MemoryBufferMem implementation.
54//===----------------------------------------------------------------------===//
55
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000056/// CopyStringRef - Copies contents of a StringRef into a block of memory and
57/// null-terminates it.
58static void CopyStringRef(char *Memory, StringRef Data) {
59 memcpy(Memory, Data.data(), Data.size());
60 Memory[Data.size()] = 0; // Null terminate string.
61}
62
63/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
64template <typename T>
65static 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);
69}
70
Chris Lattner333ffd42007-04-29 06:58:52 +000071namespace {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000072/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
Chris Lattner333ffd42007-04-29 06:58:52 +000073class MemoryBufferMem : public MemoryBuffer {
Chris Lattner333ffd42007-04-29 06:58:52 +000074public:
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000075 MemoryBufferMem(StringRef InputData) {
76 init(InputData.begin(), InputData.end());
Chris Lattner333ffd42007-04-29 06:58:52 +000077 }
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000078
Chris Lattner333ffd42007-04-29 06:58:52 +000079 virtual const char *getBufferIdentifier() const {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000080 // The name is stored after the class itself.
81 return reinterpret_cast<const char*>(this + 1);
Chris Lattner333ffd42007-04-29 06:58:52 +000082 }
83};
84}
85
86/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
87/// that EndPtr[0] must be a null byte and be accessible!
Chris Lattner4c842dd2010-04-05 22:42:30 +000088MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000089 StringRef BufferName) {
90 return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName);
Chris Lattner333ffd42007-04-29 06:58:52 +000091}
92
Chris Lattner3daae272007-10-09 21:46:38 +000093/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
94/// copying the contents and taking ownership of it. This has no requirements
95/// on EndPtr[0].
Chris Lattner4c842dd2010-04-05 22:42:30 +000096MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000097 StringRef BufferName) {
98 MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
99 if (!Buf) return 0;
100 memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
101 InputData.size());
102 return Buf;
Chris Lattner3daae272007-10-09 21:46:38 +0000103}
104
Chris Lattner333ffd42007-04-29 06:58:52 +0000105/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000106/// that is not initialized. Note that the caller should initialize the
107/// memory allocated by this method. The memory is owned by the MemoryBuffer
108/// object.
Evan Cheng34cd4a42008-05-05 18:30:58 +0000109MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
Daniel Dunbard65267e2009-11-10 00:43:58 +0000110 StringRef BufferName) {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000111 // 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));
118 if (!Mem) return 0;
119
120 // The name is stored after the class itself.
121 CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);
122
123 // The buffer begins after the name and must be aligned.
124 char *Buf = Mem + AlignedStringLen;
125 Buf[Size] = 0; // Null terminate buffer.
126
127 return new (Mem) MemoryBufferMem(StringRef(Buf, Size));
Chris Lattner333ffd42007-04-29 06:58:52 +0000128}
129
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.
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000134MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
Chris Lattner333ffd42007-04-29 06:58:52 +0000135 MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
Evan Cheng726135a2009-02-13 07:54:34 +0000136 if (!SB) return 0;
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000137 memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
Chris Lattner333ffd42007-04-29 06:58:52 +0000138 return SB;
139}
140
141
Chris Lattner2b1f1062007-11-18 18:52:28 +0000142/// 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.
Daniel Dunbard65267e2009-11-10 00:43:58 +0000146MemoryBuffer *MemoryBuffer::getFileOrSTDIN(StringRef Filename,
Michael J. Spencer333fb042010-12-09 17:36:48 +0000147 error_code &ec,
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000148 int64_t FileSize) {
Daniel Dunbard65267e2009-11-10 00:43:58 +0000149 if (Filename == "-")
Michael J. Spencer333fb042010-12-09 17:36:48 +0000150 return getSTDIN(ec);
151 return getFile(Filename, ec, FileSize);
Chris Lattner2b1f1062007-11-18 18:52:28 +0000152}
153
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000154MemoryBuffer *MemoryBuffer::getFileOrSTDIN(const char *Filename,
Michael J. Spencer333fb042010-12-09 17:36:48 +0000155 error_code &ec,
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000156 int64_t FileSize) {
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000157 if (strcmp(Filename, "-") == 0)
Michael J. Spencer333fb042010-12-09 17:36:48 +0000158 return getSTDIN(ec);
159 return getFile(Filename, ec, FileSize);
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000160}
161
Chris Lattner333ffd42007-04-29 06:58:52 +0000162//===----------------------------------------------------------------------===//
Chris Lattner333ffd42007-04-29 06:58:52 +0000163// MemoryBuffer::getFile implementation.
164//===----------------------------------------------------------------------===//
165
Chris Lattner11da4cf2008-04-01 06:05:21 +0000166namespace {
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.
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000170class MemoryBufferMMapFile : public MemoryBufferMem {
Chris Lattner11da4cf2008-04-01 06:05:21 +0000171public:
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000172 MemoryBufferMMapFile(StringRef Buffer)
173 : MemoryBufferMem(Buffer) { }
174
Chris Lattner11da4cf2008-04-01 06:05:21 +0000175 ~MemoryBufferMMapFile() {
176 sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
177 }
178};
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000179
180/// FileCloser - RAII object to make sure an FD gets closed properly.
181class FileCloser {
182 int FD;
183public:
Dan Gohman455164b2010-06-22 13:53:29 +0000184 explicit FileCloser(int FD) : FD(FD) {}
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000185 ~FileCloser() { ::close(FD); }
186};
Chris Lattner11da4cf2008-04-01 06:05:21 +0000187}
188
Michael J. Spencer333fb042010-12-09 17:36:48 +0000189MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, error_code &ec,
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000190 int64_t FileSize) {
Chris Lattner7cf70542010-11-23 22:20:27 +0000191 // Ensure the path is null terminated.
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000192 SmallString<256> PathBuf(Filename.begin(), Filename.end());
Michael J. Spencer333fb042010-12-09 17:36:48 +0000193 return MemoryBuffer::getFile(PathBuf.c_str(), ec, FileSize);
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000194}
195
Michael J. Spencer333fb042010-12-09 17:36:48 +0000196MemoryBuffer *MemoryBuffer::getFile(const char *Filename, error_code &ec,
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000197 int64_t FileSize) {
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000198 int OpenFlags = O_RDONLY;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000199#ifdef O_BINARY
Bill Wendlinga4420062008-04-01 22:09:20 +0000200 OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
Chris Lattner11da4cf2008-04-01 06:05:21 +0000201#endif
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000202 int FD = ::open(Filename, OpenFlags);
Chris Lattner333ffd42007-04-29 06:58:52 +0000203 if (FD == -1) {
Michael J. Spencer333fb042010-12-09 17:36:48 +0000204 ec = error_code(errno, posix_category());
Chris Lattner333ffd42007-04-29 06:58:52 +0000205 return 0;
206 }
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000207
Michael J. Spencer333fb042010-12-09 17:36:48 +0000208 return getOpenFile(FD, Filename, ec, FileSize);
Chris Lattner7cf70542010-11-23 22:20:27 +0000209}
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000210
Chris Lattner7cf70542010-11-23 22:20:27 +0000211MemoryBuffer *MemoryBuffer::getOpenFile(int FD, const char *Filename,
Michael J. Spencer333fb042010-12-09 17:36:48 +0000212 error_code &ec, int64_t FileSize) {
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000213 FileCloser FC(FD); // Close FD on return.
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000214
Chris Lattner11da4cf2008-04-01 06:05:21 +0000215 // 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.
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000217 if (FileSize == -1) {
218 struct stat FileInfo;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000219 // TODO: This should use fstat64 when available.
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000220 if (fstat(FD, &FileInfo) == -1) {
Michael J. Spencer333fb042010-12-09 17:36:48 +0000221 ec = error_code(errno, posix_category());
Chris Lattner11da4cf2008-04-01 06:05:21 +0000222 return 0;
223 }
Chris Lattner9f9bd8e2010-11-23 06:09:51 +0000224 FileSize = FileInfo.st_size;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000225 }
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000226
227
Chris Lattner11da4cf2008-04-01 06:05:21 +0000228 // 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.
Daniel Dunbard65267e2009-11-10 00:43:58 +0000232 //
233 // FIXME: Can we just mmap an extra page in the latter case?
Chris Lattner11da4cf2008-04-01 06:05:21 +0000234 if (FileSize >= 4096*4 &&
235 (FileSize & (sys::Process::GetPageSize()-1)) != 0) {
236 if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000237 return GetNamedBuffer<MemoryBufferMMapFile>(StringRef(Pages, FileSize),
238 Filename);
Chris Lattner11da4cf2008-04-01 06:05:21 +0000239 }
240 }
Evan Cheng726135a2009-02-13 07:54:34 +0000241
242 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename);
243 if (!Buf) {
Michael J. Spencer333fb042010-12-09 17:36:48 +0000244 // 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);
Evan Cheng726135a2009-02-13 07:54:34 +0000247 return 0;
248 }
249
250 OwningPtr<MemoryBuffer> SB(Buf);
Chris Lattner11da4cf2008-04-01 06:05:21 +0000251 char *BufPtr = const_cast<char*>(SB->getBufferStart());
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000252
Evan Cheng34cd4a42008-05-05 18:30:58 +0000253 size_t BytesLeft = FileSize;
Chris Lattner333ffd42007-04-29 06:58:52 +0000254 while (BytesLeft) {
255 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000256 if (NumRead == -1) {
257 if (errno == EINTR)
258 continue;
259 // Error while reading.
Michael J. Spencer333fb042010-12-09 17:36:48 +0000260 ec = error_code(errno, posix_category());
Chris Lattner333ffd42007-04-29 06:58:52 +0000261 return 0;
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000262 } else if (NumRead == 0) {
Benjamin Kramerd48c1f92010-04-01 14:39:55 +0000263 // We hit EOF early, truncate and terminate buffer.
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000264 Buf->BufferEnd = BufPtr;
Benjamin Kramerd48c1f92010-04-01 14:39:55 +0000265 *BufPtr = 0;
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000266 return SB.take();
Chris Lattner333ffd42007-04-29 06:58:52 +0000267 }
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000268 BytesLeft -= NumRead;
269 BufPtr += NumRead;
Chris Lattner333ffd42007-04-29 06:58:52 +0000270 }
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000271
Chris Lattner11da4cf2008-04-01 06:05:21 +0000272 return SB.take();
Chris Lattner333ffd42007-04-29 06:58:52 +0000273}
274
Chris Lattner333ffd42007-04-29 06:58:52 +0000275//===----------------------------------------------------------------------===//
276// MemoryBuffer::getSTDIN implementation.
277//===----------------------------------------------------------------------===//
278
Michael J. Spencer333fb042010-12-09 17:36:48 +0000279MemoryBuffer *MemoryBuffer::getSTDIN(error_code &ec) {
Chris Lattner333ffd42007-04-29 06:58:52 +0000280 // Read in all of the data from stdin, we cannot mmap stdin.
Daniel Dunbard65267e2009-11-10 00:43:58 +0000281 //
282 // FIXME: That isn't necessarily true, we should try to mmap stdin and
283 // fallback if it fails.
Jeff Cohen0fea8eb2007-05-07 15:21:46 +0000284 sys::Program::ChangeStdinToBinary();
Benjamin Kramer831338b2010-06-25 16:07:18 +0000285
286 const ssize_t ChunkSize = 4096*4;
287 SmallString<ChunkSize> Buffer;
288 ssize_t ReadBytes;
289 // Read into Buffer until we hit EOF.
Eli Friedman96cd7af2009-05-18 08:44:04 +0000290 do {
Benjamin Kramer831338b2010-06-25 16:07:18 +0000291 Buffer.reserve(Buffer.size() + ChunkSize);
292 ReadBytes = read(0, Buffer.end(), ChunkSize);
293 if (ReadBytes == -1) {
294 if (errno == EINTR) continue;
Michael J. Spencer333fb042010-12-09 17:36:48 +0000295 ec = error_code(errno, posix_category());
Benjamin Kramer831338b2010-06-25 16:07:18 +0000296 return 0;
297 }
298 Buffer.set_size(Buffer.size() + ReadBytes);
299 } while (ReadBytes != 0);
Reid Spencer2372ccc2007-08-08 20:01:58 +0000300
Benjamin Kramer831338b2010-06-25 16:07:18 +0000301 return getMemBufferCopy(Buffer, "<stdin>");
Chris Lattner333ffd42007-04-29 06:58:52 +0000302}