X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FMemoryBuffer.cpp;h=2b95089b5246f4620fb63fb354adf47fdfef6578;hb=21aa347c2816aa8fc635ad05c5ab786234b32c7e;hp=b170ea72670c20831e6e9fc40664e1263cf09609;hpb=a442006f4876be13b632ba1a4bee3ae827194eb1;p=oota-llvm.git diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index b170ea72670..2b95089b524 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" +#include "llvm/System/Errno.h" #include "llvm/System/Path.h" #include "llvm/System/Process.h" #include "llvm/System/Program.h" @@ -26,11 +27,10 @@ #if !defined(_MSC_VER) && !defined(__MINGW32__) #include #include -#include #else #include -#include #endif +#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -39,7 +39,7 @@ using namespace llvm; MemoryBuffer::~MemoryBuffer() { if (MustDeleteBuffer) - delete [] BufferStart; + free((void*)BufferStart); } /// initCopyOf - Initialize this source buffer with a copy of the specified @@ -47,7 +47,7 @@ MemoryBuffer::~MemoryBuffer() { /// successfully. void MemoryBuffer::initCopyOf(const char *BufStart, const char *BufEnd) { size_t Size = BufEnd-BufStart; - BufferStart = new char[Size+1]; + BufferStart = (char *)malloc(Size+1); BufferEnd = BufferStart+Size; memcpy(const_cast(BufferStart), BufStart, Size); *const_cast(BufferEnd) = 0; // Null terminate buffer. @@ -71,13 +71,12 @@ namespace { class MemoryBufferMem : public MemoryBuffer { std::string FileID; public: - MemoryBufferMem(const char *Start, const char *End, const char *FID, - bool Copy = false) + MemoryBufferMem(StringRef InputData, StringRef FID, bool Copy = false) : FileID(FID) { if (!Copy) - init(Start, End); + init(InputData.data(), InputData.data()+InputData.size()); else - initCopyOf(Start, End); + initCopyOf(InputData.data(), InputData.data()+InputData.size()); } virtual const char *getBufferIdentifier() const { @@ -88,30 +87,29 @@ public: /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that EndPtr[0] must be a null byte and be accessible! -MemoryBuffer *MemoryBuffer::getMemBuffer(const char *StartPtr, - const char *EndPtr, +MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, const char *BufferName) { - return new MemoryBufferMem(StartPtr, EndPtr, BufferName); + return new MemoryBufferMem(InputData, BufferName); } /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, /// copying the contents and taking ownership of it. This has no requirements /// on EndPtr[0]. -MemoryBuffer *MemoryBuffer::getMemBufferCopy(const char *StartPtr, - const char *EndPtr, +MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData, const char *BufferName) { - return new MemoryBufferMem(StartPtr, EndPtr, BufferName, true); + return new MemoryBufferMem(InputData, BufferName, true); } /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size /// that is completely initialized to zeros. Note that the caller should /// initialize the memory allocated by this method. The memory is owned by /// the MemoryBuffer object. -MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(unsigned Size, - const char *BufferName) { - char *Buf = new char[Size+1]; +MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, + StringRef BufferName) { + char *Buf = (char *)malloc(Size+1); + if (!Buf) return 0; Buf[Size] = 0; - MemoryBufferMem *SB = new MemoryBufferMem(Buf, Buf+Size, BufferName); + MemoryBufferMem *SB = new MemoryBufferMem(StringRef(Buf, Size), BufferName); // The memory for this buffer is owned by the MemoryBuffer. SB->MustDeleteBuffer = true; return SB; @@ -121,9 +119,10 @@ MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(unsigned Size, /// is completely initialized to zeros. Note that the caller should /// initialize the memory allocated by this method. The memory is owned by /// the MemoryBuffer object. -MemoryBuffer *MemoryBuffer::getNewMemBuffer(unsigned Size, +MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, const char *BufferName) { MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); + if (!SB) return 0; memset(const_cast(SB->getBufferStart()), 0, Size+1); return SB; } @@ -133,17 +132,13 @@ MemoryBuffer *MemoryBuffer::getNewMemBuffer(unsigned Size, /// if the Filename is "-". If an error occurs, this returns null and fills /// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN) /// returns an empty buffer. -MemoryBuffer *MemoryBuffer::getFileOrSTDIN(const char *Filename, +MemoryBuffer *MemoryBuffer::getFileOrSTDIN(StringRef Filename, std::string *ErrStr, - int64_t FileSize) { - if (Filename[0] != '-' || Filename[1] != 0) - return getFile(Filename, ErrStr, FileSize); - MemoryBuffer *M = getSTDIN(); - if (M) return M; - - // If stdin was empty, M is null. Cons up an empty memory buffer now. - const char *EmptyStr = ""; - return MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, ""); + int64_t FileSize, + struct stat *FileInfo) { + if (Filename == "-") + return getSTDIN(); + return getFile(Filename, ErrStr, FileSize, FileInfo); } //===----------------------------------------------------------------------===// @@ -157,7 +152,7 @@ namespace { class MemoryBufferMMapFile : public MemoryBuffer { std::string Filename; public: - MemoryBufferMMapFile(const char *filename, const char *Pages, uint64_t Size) + MemoryBufferMMapFile(StringRef filename, const char *Pages, uint64_t Size) : Filename(filename) { init(Pages, Pages+Size); } @@ -170,31 +165,42 @@ public: sys::Path::UnMapFilePages(getBufferStart(), getBufferSize()); } }; + +/// FileCloser - RAII object to make sure an FD gets closed properly. +class FileCloser { + int FD; +public: + FileCloser(int FD) : FD(FD) {} + ~FileCloser() { ::close(FD); } +}; } -MemoryBuffer *MemoryBuffer::getFile(const char *Filename, std::string *ErrStr, - int64_t FileSize) { +MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr, + int64_t FileSize, struct stat *FileInfo) { int OpenFlags = 0; #ifdef O_BINARY OpenFlags |= O_BINARY; // Open input file in binary mode on win32. #endif - int FD = ::open(Filename, O_RDONLY|OpenFlags); + SmallString<256> PathBuf(Filename.begin(), Filename.end()); + int FD = ::open(PathBuf.c_str(), O_RDONLY|OpenFlags); if (FD == -1) { - if (ErrStr) *ErrStr = "could not open file"; + if (ErrStr) *ErrStr = sys::StrError(); return 0; } + FileCloser FC(FD); // Close FD on return. // If we don't know the file size, use fstat to find out. fstat on an open // file descriptor is cheaper than stat on a random path. - if (FileSize == -1) { - struct stat FileInfo; + if (FileSize == -1 || FileInfo) { + struct stat MyFileInfo; + struct stat *FileInfoPtr = FileInfo? FileInfo : &MyFileInfo; + // TODO: This should use fstat64 when available. - if (fstat(FD, &FileInfo) == -1) { - if (ErrStr) *ErrStr = "could not get file length"; - ::close(FD); + if (fstat(FD, FileInfoPtr) == -1) { + if (ErrStr) *ErrStr = sys::StrError(); return 0; } - FileSize = FileInfo.st_size; + FileSize = FileInfoPtr->st_size; } @@ -202,36 +208,45 @@ MemoryBuffer *MemoryBuffer::getFile(const char *Filename, std::string *ErrStr, // for small files, because this can severely fragment our address space. Also // don't try to map files that are exactly a multiple of the system page size, // as the file would not have the required null terminator. + // + // FIXME: Can we just mmap an extra page in the latter case? if (FileSize >= 4096*4 && (FileSize & (sys::Process::GetPageSize()-1)) != 0) { if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) { // Close the file descriptor, now that the whole file is in memory. - ::close(FD); return new MemoryBufferMMapFile(Filename, Pages, FileSize); } } - - OwningPtr SB; - SB.reset(MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename)); + + MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename); + if (!Buf) { + // Failed to create a buffer. + if (ErrStr) *ErrStr = "could not allocate buffer"; + return 0; + } + + OwningPtr SB(Buf); char *BufPtr = const_cast(SB->getBufferStart()); - - unsigned BytesLeft = FileSize; + + size_t BytesLeft = FileSize; while (BytesLeft) { ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); - if (NumRead != -1) { - BytesLeft -= NumRead; - BufPtr += NumRead; - } else if (errno == EINTR) { - // try again - } else { - // error reading. - close(FD); - if (ErrStr) *ErrStr = "error reading file data"; + if (NumRead == -1) { + if (errno == EINTR) + continue; + // Error while reading. + if (ErrStr) *ErrStr = sys::StrError(); return 0; + } else if (NumRead == 0) { + // We hit EOF early, truncate and terminate buffer. + Buf->BufferEnd = BufPtr; + *BufPtr = 0; + return SB.take(); } + BytesLeft -= NumRead; + BufPtr += NumRead; } - close(FD); - + return SB.take(); } @@ -250,18 +265,22 @@ public: MemoryBuffer *MemoryBuffer::getSTDIN() { char Buffer[4096*4]; - + std::vector FileData; - + // Read in all of the data from stdin, we cannot mmap stdin. + // + // FIXME: That isn't necessarily true, we should try to mmap stdin and + // fallback if it fails. sys::Program::ChangeStdinToBinary(); - while (size_t ReadBytes = fread(Buffer, sizeof(char), 4096*4, stdin)) + size_t ReadBytes; + do { + ReadBytes = fread(Buffer, sizeof(char), sizeof(Buffer), stdin); FileData.insert(FileData.end(), Buffer, Buffer+ReadBytes); + } while (ReadBytes == sizeof(Buffer)); FileData.push_back(0); // &FileData[Size] is invalid. So is &*FileData.end(). size_t Size = FileData.size(); - if (Size <= 1) - return 0; MemoryBuffer *B = new STDINBufferFile(); B->initCopyOf(&FileData[0], &FileData[Size-1]); return B;