blob: 911a03f8088bd70f97352b36352f254e68c47d2b [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 Kramer5745fbc2011-11-22 12:31:53 +000017#include "llvm/Config/config.h"
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000018#include "llvm/Support/MathExtras.h"
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000019#include "llvm/Support/Errno.h"
20#include "llvm/Support/Path.h"
21#include "llvm/Support/Process.h"
22#include "llvm/Support/Program.h"
Michael J. Spencer333fb042010-12-09 17:36:48 +000023#include "llvm/Support/system_error.h"
Jeff Cohen9bc40602007-04-29 14:21:44 +000024#include <cassert>
Chris Lattner333ffd42007-04-29 06:58:52 +000025#include <cstdio>
26#include <cstring>
27#include <cerrno>
Nick Lewycky476b2422010-12-19 20:43:38 +000028#include <new>
Chris Lattner11da4cf2008-04-01 06:05:21 +000029#include <sys/types.h>
30#include <sys/stat.h>
31#if !defined(_MSC_VER) && !defined(__MINGW32__)
32#include <unistd.h>
Chris Lattner11da4cf2008-04-01 06:05:21 +000033#else
34#include <io.h>
35#endif
Gabor Greif88110802008-04-30 08:53:22 +000036#include <fcntl.h>
Chris Lattner333ffd42007-04-29 06:58:52 +000037using namespace llvm;
38
39//===----------------------------------------------------------------------===//
40// MemoryBuffer implementation itself.
41//===----------------------------------------------------------------------===//
42
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000043MemoryBuffer::~MemoryBuffer() { }
Chris Lattner333ffd42007-04-29 06:58:52 +000044
45/// init - Initialize this MemoryBuffer as a reference to externally allocated
46/// memory, memory that we know is already null terminated.
Rafael Espindolaf7fdad12011-03-10 18:33:29 +000047void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
48 bool RequiresNullTerminator) {
Rafael Espindola49ab1202011-03-18 02:55:51 +000049 assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
Rafael Espindolaf7fdad12011-03-10 18:33:29 +000050 "Buffer is not null terminated!");
Chris Lattner333ffd42007-04-29 06:58:52 +000051 BufferStart = BufStart;
52 BufferEnd = BufEnd;
Chris Lattner333ffd42007-04-29 06:58:52 +000053}
54
55//===----------------------------------------------------------------------===//
56// MemoryBufferMem implementation.
57//===----------------------------------------------------------------------===//
58
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000059/// CopyStringRef - Copies contents of a StringRef into a block of memory and
60/// null-terminates it.
61static void CopyStringRef(char *Memory, StringRef Data) {
62 memcpy(Memory, Data.data(), Data.size());
63 Memory[Data.size()] = 0; // Null terminate string.
64}
65
66/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
67template <typename T>
Chris Lattner9bb4a2a2011-05-22 00:50:53 +000068static T *GetNamedBuffer(StringRef Buffer, StringRef Name,
Rafael Espindolaf7fdad12011-03-10 18:33:29 +000069 bool RequiresNullTerminator) {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000070 char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1));
71 CopyStringRef(Mem + sizeof(T), Name);
Rafael Espindolaf7fdad12011-03-10 18:33:29 +000072 return new (Mem) T(Buffer, RequiresNullTerminator);
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000073}
74
Chris Lattner333ffd42007-04-29 06:58:52 +000075namespace {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000076/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
Chris Lattner333ffd42007-04-29 06:58:52 +000077class MemoryBufferMem : public MemoryBuffer {
Chris Lattner333ffd42007-04-29 06:58:52 +000078public:
Rafael Espindolaf7fdad12011-03-10 18:33:29 +000079 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
80 init(InputData.begin(), InputData.end(), RequiresNullTerminator);
Chris Lattner333ffd42007-04-29 06:58:52 +000081 }
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000082
Chris Lattner333ffd42007-04-29 06:58:52 +000083 virtual const char *getBufferIdentifier() const {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +000084 // The name is stored after the class itself.
85 return reinterpret_cast<const char*>(this + 1);
Chris Lattner333ffd42007-04-29 06:58:52 +000086 }
Ted Kremenek5d867592011-04-28 20:34:18 +000087
88 virtual BufferKind getBufferKind() const {
89 return MemoryBuffer_Malloc;
90 }
Chris Lattner333ffd42007-04-29 06:58:52 +000091};
92}
93
94/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
Chris Lattner9bb4a2a2011-05-22 00:50:53 +000095/// that InputData must be a null terminated if RequiresNullTerminator is true!
Chris Lattner4c842dd2010-04-05 22:42:30 +000096MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
Rafael Espindola9916d2a2011-03-17 22:18:42 +000097 StringRef BufferName,
98 bool RequiresNullTerminator) {
99 return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName,
100 RequiresNullTerminator);
Chris Lattner333ffd42007-04-29 06:58:52 +0000101}
102
Chris Lattner3daae272007-10-09 21:46:38 +0000103/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
104/// copying the contents and taking ownership of it. This has no requirements
105/// on EndPtr[0].
Chris Lattner4c842dd2010-04-05 22:42:30 +0000106MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000107 StringRef BufferName) {
108 MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
109 if (!Buf) return 0;
110 memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
111 InputData.size());
112 return Buf;
Chris Lattner3daae272007-10-09 21:46:38 +0000113}
114
Chris Lattner333ffd42007-04-29 06:58:52 +0000115/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000116/// that is not initialized. Note that the caller should initialize the
117/// memory allocated by this method. The memory is owned by the MemoryBuffer
118/// object.
Evan Cheng34cd4a42008-05-05 18:30:58 +0000119MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
Daniel Dunbard65267e2009-11-10 00:43:58 +0000120 StringRef BufferName) {
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000121 // Allocate space for the MemoryBuffer, the data and the name. It is important
122 // that MemoryBuffer and data are aligned so PointerIntPair works with them.
123 size_t AlignedStringLen =
124 RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
125 sizeof(void*)); // TODO: Is sizeof(void*) enough?
126 size_t RealLen = AlignedStringLen + Size + 1;
127 char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
128 if (!Mem) return 0;
129
130 // The name is stored after the class itself.
131 CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);
132
133 // The buffer begins after the name and must be aligned.
134 char *Buf = Mem + AlignedStringLen;
135 Buf[Size] = 0; // Null terminate buffer.
136
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000137 return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
Chris Lattner333ffd42007-04-29 06:58:52 +0000138}
139
140/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
141/// is completely initialized to zeros. Note that the caller should
142/// initialize the memory allocated by this method. The memory is owned by
143/// the MemoryBuffer object.
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000144MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
Chris Lattner333ffd42007-04-29 06:58:52 +0000145 MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
Evan Cheng726135a2009-02-13 07:54:34 +0000146 if (!SB) return 0;
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000147 memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
Chris Lattner333ffd42007-04-29 06:58:52 +0000148 return SB;
149}
150
151
Chris Lattner2b1f1062007-11-18 18:52:28 +0000152/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
153/// if the Filename is "-". If an error occurs, this returns null and fills
154/// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN)
155/// returns an empty buffer.
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000156error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename,
157 OwningPtr<MemoryBuffer> &result,
158 int64_t FileSize) {
Daniel Dunbard65267e2009-11-10 00:43:58 +0000159 if (Filename == "-")
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000160 return getSTDIN(result);
161 return getFile(Filename, result, FileSize);
Chris Lattner2b1f1062007-11-18 18:52:28 +0000162}
163
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000164error_code MemoryBuffer::getFileOrSTDIN(const char *Filename,
165 OwningPtr<MemoryBuffer> &result,
166 int64_t FileSize) {
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000167 if (strcmp(Filename, "-") == 0)
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000168 return getSTDIN(result);
169 return getFile(Filename, result, FileSize);
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000170}
171
Chris Lattner333ffd42007-04-29 06:58:52 +0000172//===----------------------------------------------------------------------===//
Chris Lattner333ffd42007-04-29 06:58:52 +0000173// MemoryBuffer::getFile implementation.
174//===----------------------------------------------------------------------===//
175
Chris Lattner11da4cf2008-04-01 06:05:21 +0000176namespace {
177/// MemoryBufferMMapFile - This represents a file that was mapped in with the
178/// sys::Path::MapInFilePages method. When destroyed, it calls the
179/// sys::Path::UnMapFilePages method.
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000180class MemoryBufferMMapFile : public MemoryBufferMem {
Chris Lattner11da4cf2008-04-01 06:05:21 +0000181public:
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000182 MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator)
183 : MemoryBufferMem(Buffer, RequiresNullTerminator) { }
Benjamin Kramerd4d1f852010-06-25 11:50:40 +0000184
Chris Lattner11da4cf2008-04-01 06:05:21 +0000185 ~MemoryBufferMMapFile() {
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000186 static int PageSize = sys::Process::GetPageSize();
187
188 uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart());
189 size_t Size = getBufferSize();
190 uintptr_t RealStart = Start & ~(PageSize - 1);
191 size_t RealSize = Size + (Start - RealStart);
192
193 sys::Path::UnMapFilePages(reinterpret_cast<const char*>(RealStart),
194 RealSize);
Chris Lattner11da4cf2008-04-01 06:05:21 +0000195 }
Ted Kremenek5d867592011-04-28 20:34:18 +0000196
197 virtual BufferKind getBufferKind() const {
198 return MemoryBuffer_MMap;
199 }
Chris Lattner11da4cf2008-04-01 06:05:21 +0000200};
201}
202
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000203error_code MemoryBuffer::getFile(StringRef Filename,
204 OwningPtr<MemoryBuffer> &result,
Rafael Espindola11d18032011-03-22 19:20:47 +0000205 int64_t FileSize,
206 bool RequiresNullTerminator) {
Chris Lattner7cf70542010-11-23 22:20:27 +0000207 // Ensure the path is null terminated.
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000208 SmallString<256> PathBuf(Filename.begin(), Filename.end());
Rafael Espindola11d18032011-03-22 19:20:47 +0000209 return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize,
210 RequiresNullTerminator);
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000211}
212
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000213error_code MemoryBuffer::getFile(const char *Filename,
214 OwningPtr<MemoryBuffer> &result,
Rafael Espindola11d18032011-03-22 19:20:47 +0000215 int64_t FileSize,
216 bool RequiresNullTerminator) {
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000217 int OpenFlags = O_RDONLY;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000218#ifdef O_BINARY
Bill Wendlinga4420062008-04-01 22:09:20 +0000219 OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
Chris Lattner11da4cf2008-04-01 06:05:21 +0000220#endif
Dan Gohman60e6f3d2010-06-24 16:25:50 +0000221 int FD = ::open(Filename, OpenFlags);
Chris Lattner9bb4a2a2011-05-22 00:50:53 +0000222 if (FD == -1)
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000223 return error_code(errno, posix_category());
Chris Lattner9bb4a2a2011-05-22 00:50:53 +0000224
Rafael Espindola11d18032011-03-22 19:20:47 +0000225 error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize,
226 0, RequiresNullTerminator);
Rafael Espindolab4cc0312011-02-08 22:40:47 +0000227 close(FD);
228 return ret;
Chris Lattner7cf70542010-11-23 22:20:27 +0000229}
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000230
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000231static bool shouldUseMmap(int FD,
232 size_t FileSize,
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000233 size_t MapSize,
234 off_t Offset,
235 bool RequiresNullTerminator,
236 int PageSize) {
237 // We don't use mmap for small files because this can severely fragment our
238 // address space.
239 if (MapSize < 4096*4)
240 return false;
241
242 if (!RequiresNullTerminator)
243 return true;
244
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000245
246 // If we don't know the file size, use fstat to find out. fstat on an open
247 // file descriptor is cheaper than stat on a random path.
248 // FIXME: this chunk of code is duplicated, but it avoids a fstat when
249 // RequiresNullTerminator = false and MapSize != -1.
250 if (FileSize == size_t(-1)) {
251 struct stat FileInfo;
252 // TODO: This should use fstat64 when available.
253 if (fstat(FD, &FileInfo) == -1) {
254 return error_code(errno, posix_category());
255 }
256 FileSize = FileInfo.st_size;
257 }
258
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000259 // If we need a null terminator and the end of the map is inside the file,
260 // we cannot use mmap.
261 size_t End = Offset + MapSize;
262 assert(End <= FileSize);
263 if (End != FileSize)
264 return false;
265
266 // Don't try to map files that are exactly a multiple of the system page size
267 // if we need a null terminator.
268 if ((FileSize & (PageSize -1)) == 0)
269 return false;
270
271 return true;
272}
273
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000274error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
275 OwningPtr<MemoryBuffer> &result,
Ivan Krasin71280b52011-09-15 23:13:00 +0000276 uint64_t FileSize, uint64_t MapSize,
277 int64_t Offset,
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000278 bool RequiresNullTerminator) {
279 static int PageSize = sys::Process::GetPageSize();
280
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000281 // Default is to map the full file.
Ivan Krasin71280b52011-09-15 23:13:00 +0000282 if (MapSize == uint64_t(-1)) {
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000283 // If we don't know the file size, use fstat to find out. fstat on an open
284 // file descriptor is cheaper than stat on a random path.
Ivan Krasin71280b52011-09-15 23:13:00 +0000285 if (FileSize == uint64_t(-1)) {
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000286 struct stat FileInfo;
287 // TODO: This should use fstat64 when available.
288 if (fstat(FD, &FileInfo) == -1) {
289 return error_code(errno, posix_category());
290 }
291 FileSize = FileInfo.st_size;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000292 }
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000293 MapSize = FileSize;
Chris Lattner11da4cf2008-04-01 06:05:21 +0000294 }
Michael J. Spencer1f6efa32010-11-29 18:16:10 +0000295
Rafael Espindola9d2234d2011-03-10 20:54:07 +0000296 if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000297 PageSize)) {
298 off_t RealMapOffset = Offset & ~(PageSize - 1);
299 off_t Delta = Offset - RealMapOffset;
300 size_t RealMapSize = MapSize + Delta;
301
302 if (const char *Pages = sys::Path::MapInFilePages(FD,
303 RealMapSize,
304 RealMapOffset)) {
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000305 result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000306 StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
David Blaikie58604cd2012-02-09 19:24:12 +0000307 return error_code::success();
Chris Lattner11da4cf2008-04-01 06:05:21 +0000308 }
309 }
Evan Cheng726135a2009-02-13 07:54:34 +0000310
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000311 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
Evan Cheng726135a2009-02-13 07:54:34 +0000312 if (!Buf) {
Michael J. Spencer333fb042010-12-09 17:36:48 +0000313 // Failed to create a buffer. The only way it can fail is if
314 // new(std::nothrow) returns 0.
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000315 return make_error_code(errc::not_enough_memory);
Evan Cheng726135a2009-02-13 07:54:34 +0000316 }
317
318 OwningPtr<MemoryBuffer> SB(Buf);
Chris Lattner11da4cf2008-04-01 06:05:21 +0000319 char *BufPtr = const_cast<char*>(SB->getBufferStart());
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000320
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000321 size_t BytesLeft = MapSize;
Benjamin Kramer5745fbc2011-11-22 12:31:53 +0000322#ifndef HAVE_PREAD
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000323 if (lseek(FD, Offset, SEEK_SET) == -1)
324 return error_code(errno, posix_category());
Benjamin Kramer5745fbc2011-11-22 12:31:53 +0000325#endif
Rafael Espindolaf7fdad12011-03-10 18:33:29 +0000326
Chris Lattner333ffd42007-04-29 06:58:52 +0000327 while (BytesLeft) {
Benjamin Kramer5745fbc2011-11-22 12:31:53 +0000328#ifdef HAVE_PREAD
329 ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
330#else
Chris Lattner333ffd42007-04-29 06:58:52 +0000331 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
Benjamin Kramer5745fbc2011-11-22 12:31:53 +0000332#endif
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000333 if (NumRead == -1) {
334 if (errno == EINTR)
335 continue;
336 // Error while reading.
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000337 return error_code(errno, posix_category());
Chris Lattner333ffd42007-04-29 06:58:52 +0000338 }
Argyrios Kyrtzidisb9153ba2012-03-13 20:18:42 +0000339 if (NumRead == 0) {
340 assert(0 && "We got inaccurate FileSize value or fstat reported an "
341 "invalid file size.");
342 break;
343 }
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000344 BytesLeft -= NumRead;
345 BufPtr += NumRead;
Chris Lattner333ffd42007-04-29 06:58:52 +0000346 }
Benjamin Kramer6a9cd412010-04-01 14:35:22 +0000347
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000348 result.swap(SB);
David Blaikie58604cd2012-02-09 19:24:12 +0000349 return error_code::success();
Chris Lattner333ffd42007-04-29 06:58:52 +0000350}
351
Chris Lattner333ffd42007-04-29 06:58:52 +0000352//===----------------------------------------------------------------------===//
353// MemoryBuffer::getSTDIN implementation.
354//===----------------------------------------------------------------------===//
355
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000356error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) {
Chris Lattner333ffd42007-04-29 06:58:52 +0000357 // Read in all of the data from stdin, we cannot mmap stdin.
Daniel Dunbard65267e2009-11-10 00:43:58 +0000358 //
359 // FIXME: That isn't necessarily true, we should try to mmap stdin and
360 // fallback if it fails.
Jeff Cohen0fea8eb2007-05-07 15:21:46 +0000361 sys::Program::ChangeStdinToBinary();
Benjamin Kramer831338b2010-06-25 16:07:18 +0000362
363 const ssize_t ChunkSize = 4096*4;
364 SmallString<ChunkSize> Buffer;
365 ssize_t ReadBytes;
366 // Read into Buffer until we hit EOF.
Eli Friedman96cd7af2009-05-18 08:44:04 +0000367 do {
Benjamin Kramer831338b2010-06-25 16:07:18 +0000368 Buffer.reserve(Buffer.size() + ChunkSize);
369 ReadBytes = read(0, Buffer.end(), ChunkSize);
370 if (ReadBytes == -1) {
371 if (errno == EINTR) continue;
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000372 return error_code(errno, posix_category());
Benjamin Kramer831338b2010-06-25 16:07:18 +0000373 }
374 Buffer.set_size(Buffer.size() + ReadBytes);
375 } while (ReadBytes != 0);
Reid Spencer2372ccc2007-08-08 20:01:58 +0000376
Michael J. Spencer3ff95632010-12-16 03:29:14 +0000377 result.reset(getMemBufferCopy(Buffer, "<stdin>"));
David Blaikie58604cd2012-02-09 19:24:12 +0000378 return error_code::success();
Chris Lattner333ffd42007-04-29 06:58:52 +0000379}