llvm.org GIT mirror llvm / d48932a
Remove svn:eol-style property from 2 files. There are still over 3400 files remaining with this property set, but there are tens of thousands more with the property not set. Until we decide what to do on a global scale, this at least unblocks me temporarily. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295756 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
2 changed file(s) with 640 addition(s) and 640 deletion(s). Raw diff Collapse all Expand all
None //===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the MemoryBuffer interface.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_SUPPORT_MEMORYBUFFER_H
14 #define LLVM_SUPPORT_MEMORYBUFFER_H
15
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Support/CBindingWrapping.h"
19 #include "llvm/Support/ErrorOr.h"
20 #include "llvm-c/Types.h"
21 #include
22 #include
23 #include
24
25 namespace llvm {
26
27 class MemoryBufferRef;
28
29 /// This interface provides simple read-only access to a block of memory, and
30 /// provides simple methods for reading files and standard input into a memory
31 /// buffer. In addition to basic access to the characters in the file, this
32 /// interface guarantees you can read one character past the end of the file,
33 /// and that this character will read as '\0'.
34 ///
35 /// The '\0' guarantee is needed to support an optimization -- it's intended to
36 /// be more efficient for clients which are reading all the data to stop
37 /// reading when they encounter a '\0' than to continually check the file
38 /// position to see if it has reached the end of the file.
39 class MemoryBuffer {
40 const char *BufferStart; // Start of the buffer.
41 const char *BufferEnd; // End of the buffer.
42
43
44 protected:
45 MemoryBuffer() = default;
46
47 void init(const char *BufStart, const char *BufEnd,
48 bool RequiresNullTerminator);
49 public:
50 MemoryBuffer(const MemoryBuffer &) = delete;
51 MemoryBuffer &operator=(const MemoryBuffer &) = delete;
52 virtual ~MemoryBuffer();
53
54 const char *getBufferStart() const { return BufferStart; }
55 const char *getBufferEnd() const { return BufferEnd; }
56 size_t getBufferSize() const { return BufferEnd-BufferStart; }
57
58 StringRef getBuffer() const {
59 return StringRef(BufferStart, getBufferSize());
60 }
61
62 /// Return an identifier for this buffer, typically the filename it was read
63 /// from.
64 virtual StringRef getBufferIdentifier() const { return "Unknown buffer"; }
65
66 /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer
67 /// if successful, otherwise returning null. If FileSize is specified, this
68 /// means that the client knows that the file exists and that it has the
69 /// specified size.
70 ///
71 /// \param IsVolatileSize Set to true to indicate that the file size may be
72 /// changing, e.g. when libclang tries to parse while the user is
73 /// editing/updating the file.
74 static ErrorOr>
75 getFile(const Twine &Filename, int64_t FileSize = -1,
76 bool RequiresNullTerminator = true, bool IsVolatileSize = false);
77
78 /// Read all of the specified file into a MemoryBuffer as a stream
79 /// (i.e. until EOF reached). This is useful for special files that
80 /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
81 static ErrorOr>
82 getFileAsStream(const Twine &Filename);
83
84 /// Given an already-open file descriptor, map some slice of it into a
85 /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
86 /// Since this is in the middle of a file, the buffer is not null terminated.
87 static ErrorOr>
88 getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
89 int64_t Offset);
90
91 /// Given an already-open file descriptor, read the file and return a
92 /// MemoryBuffer.
93 ///
94 /// \param IsVolatileSize Set to true to indicate that the file size may be
95 /// changing, e.g. when libclang tries to parse while the user is
96 /// editing/updating the file.
97 static ErrorOr>
98 getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
99 bool RequiresNullTerminator = true, bool IsVolatileSize = false);
100
101 /// Open the specified memory range as a MemoryBuffer. Note that InputData
102 /// must be null terminated if RequiresNullTerminator is true.
103 static std::unique_ptr
104 getMemBuffer(StringRef InputData, StringRef BufferName = "",
105 bool RequiresNullTerminator = true);
106
107 static std::unique_ptr
108 getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true);
109
110 /// Open the specified memory range as a MemoryBuffer, copying the contents
111 /// and taking ownership of it. InputData does not have to be null terminated.
112 static std::unique_ptr
113 getMemBufferCopy(StringRef InputData, const Twine &BufferName = "");
114
115 /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
116 /// that the caller need not initialize the memory allocated by this method.
117 /// The memory is owned by the MemoryBuffer object.
118 static std::unique_ptr
119 getNewMemBuffer(size_t Size, StringRef BufferName = "");
120
121 /// Allocate a new MemoryBuffer of the specified size that is not initialized.
122 /// Note that the caller should initialize the memory allocated by this
123 /// method. The memory is owned by the MemoryBuffer object.
124 static std::unique_ptr
125 getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "");
126
127 /// Read all of stdin into a file buffer, and return it.
128 static ErrorOr> getSTDIN();
129
130 /// Open the specified file as a MemoryBuffer, or open stdin if the Filename
131 /// is "-".
132 static ErrorOr>
133 getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1,
134 bool RequiresNullTerminator = true);
135
136 /// Map a subrange of the specified file as a MemoryBuffer.
137 static ErrorOr>
138 getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
139
140 //===--------------------------------------------------------------------===//
141 // Provided for performance analysis.
142 //===--------------------------------------------------------------------===//
143
144 /// The kind of memory backing used to support the MemoryBuffer.
145 enum BufferKind {
146 MemoryBuffer_Malloc,
147 MemoryBuffer_MMap
148 };
149
150 /// Return information on the memory mechanism used to support the
151 /// MemoryBuffer.
152 virtual BufferKind getBufferKind() const = 0;
153
154 MemoryBufferRef getMemBufferRef() const;
155 };
156
157 class MemoryBufferRef {
158 StringRef Buffer;
159 StringRef Identifier;
160
161 public:
162 MemoryBufferRef() = default;
163 MemoryBufferRef(MemoryBuffer& Buffer)
164 : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {}
165 MemoryBufferRef(StringRef Buffer, StringRef Identifier)
166 : Buffer(Buffer), Identifier(Identifier) {}
167
168 StringRef getBuffer() const { return Buffer; }
169
170 StringRef getBufferIdentifier() const { return Identifier; }
171
172 const char *getBufferStart() const { return Buffer.begin(); }
173 const char *getBufferEnd() const { return Buffer.end(); }
174 size_t getBufferSize() const { return Buffer.size(); }
175 };
176
177 // Create wrappers for C Binding types (see CBindingWrapping.h).
178 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
179
180 } // end namespace llvm
181
182 #endif // LLVM_SUPPORT_MEMORYBUFFER_H
0 //===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the MemoryBuffer interface.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_SUPPORT_MEMORYBUFFER_H
14 #define LLVM_SUPPORT_MEMORYBUFFER_H
15
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Support/CBindingWrapping.h"
19 #include "llvm/Support/ErrorOr.h"
20 #include "llvm-c/Types.h"
21 #include
22 #include
23 #include
24
25 namespace llvm {
26
27 class MemoryBufferRef;
28
29 /// This interface provides simple read-only access to a block of memory, and
30 /// provides simple methods for reading files and standard input into a memory
31 /// buffer. In addition to basic access to the characters in the file, this
32 /// interface guarantees you can read one character past the end of the file,
33 /// and that this character will read as '\0'.
34 ///
35 /// The '\0' guarantee is needed to support an optimization -- it's intended to
36 /// be more efficient for clients which are reading all the data to stop
37 /// reading when they encounter a '\0' than to continually check the file
38 /// position to see if it has reached the end of the file.
39 class MemoryBuffer {
40 const char *BufferStart; // Start of the buffer.
41 const char *BufferEnd; // End of the buffer.
42
43
44 protected:
45 MemoryBuffer() = default;
46
47 void init(const char *BufStart, const char *BufEnd,
48 bool RequiresNullTerminator);
49 public:
50 MemoryBuffer(const MemoryBuffer &) = delete;
51 MemoryBuffer &operator=(const MemoryBuffer &) = delete;
52 virtual ~MemoryBuffer();
53
54 const char *getBufferStart() const { return BufferStart; }
55 const char *getBufferEnd() const { return BufferEnd; }
56 size_t getBufferSize() const { return BufferEnd-BufferStart; }
57
58 StringRef getBuffer() const {
59 return StringRef(BufferStart, getBufferSize());
60 }
61
62 /// Return an identifier for this buffer, typically the filename it was read
63 /// from.
64 virtual StringRef getBufferIdentifier() const { return "Unknown buffer"; }
65
66 /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer
67 /// if successful, otherwise returning null. If FileSize is specified, this
68 /// means that the client knows that the file exists and that it has the
69 /// specified size.
70 ///
71 /// \param IsVolatileSize Set to true to indicate that the file size may be
72 /// changing, e.g. when libclang tries to parse while the user is
73 /// editing/updating the file.
74 static ErrorOr>
75 getFile(const Twine &Filename, int64_t FileSize = -1,
76 bool RequiresNullTerminator = true, bool IsVolatileSize = false);
77
78 /// Read all of the specified file into a MemoryBuffer as a stream
79 /// (i.e. until EOF reached). This is useful for special files that
80 /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
81 static ErrorOr>
82 getFileAsStream(const Twine &Filename);
83
84 /// Given an already-open file descriptor, map some slice of it into a
85 /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
86 /// Since this is in the middle of a file, the buffer is not null terminated.
87 static ErrorOr>
88 getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
89 int64_t Offset);
90
91 /// Given an already-open file descriptor, read the file and return a
92 /// MemoryBuffer.
93 ///
94 /// \param IsVolatileSize Set to true to indicate that the file size may be
95 /// changing, e.g. when libclang tries to parse while the user is
96 /// editing/updating the file.
97 static ErrorOr>
98 getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
99 bool RequiresNullTerminator = true, bool IsVolatileSize = false);
100
101 /// Open the specified memory range as a MemoryBuffer. Note that InputData
102 /// must be null terminated if RequiresNullTerminator is true.
103 static std::unique_ptr
104 getMemBuffer(StringRef InputData, StringRef BufferName = "",
105 bool RequiresNullTerminator = true);
106
107 static std::unique_ptr
108 getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true);
109
110 /// Open the specified memory range as a MemoryBuffer, copying the contents
111 /// and taking ownership of it. InputData does not have to be null terminated.
112 static std::unique_ptr
113 getMemBufferCopy(StringRef InputData, const Twine &BufferName = "");
114
115 /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
116 /// that the caller need not initialize the memory allocated by this method.
117 /// The memory is owned by the MemoryBuffer object.
118 static std::unique_ptr
119 getNewMemBuffer(size_t Size, StringRef BufferName = "");
120
121 /// Allocate a new MemoryBuffer of the specified size that is not initialized.
122 /// Note that the caller should initialize the memory allocated by this
123 /// method. The memory is owned by the MemoryBuffer object.
124 static std::unique_ptr
125 getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "");
126
127 /// Read all of stdin into a file buffer, and return it.
128 static ErrorOr> getSTDIN();
129
130 /// Open the specified file as a MemoryBuffer, or open stdin if the Filename
131 /// is "-".
132 static ErrorOr>
133 getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1,
134 bool RequiresNullTerminator = true);
135
136 /// Map a subrange of the specified file as a MemoryBuffer.
137 static ErrorOr>
138 getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
139
140 //===--------------------------------------------------------------------===//
141 // Provided for performance analysis.
142 //===--------------------------------------------------------------------===//
143
144 /// The kind of memory backing used to support the MemoryBuffer.
145 enum BufferKind {
146 MemoryBuffer_Malloc,
147 MemoryBuffer_MMap
148 };
149
150 /// Return information on the memory mechanism used to support the
151 /// MemoryBuffer.
152 virtual BufferKind getBufferKind() const = 0;
153
154 MemoryBufferRef getMemBufferRef() const;
155 };
156
157 class MemoryBufferRef {
158 StringRef Buffer;
159 StringRef Identifier;
160
161 public:
162 MemoryBufferRef() = default;
163 MemoryBufferRef(MemoryBuffer& Buffer)
164 : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {}
165 MemoryBufferRef(StringRef Buffer, StringRef Identifier)
166 : Buffer(Buffer), Identifier(Identifier) {}
167
168 StringRef getBuffer() const { return Buffer; }
169
170 StringRef getBufferIdentifier() const { return Identifier; }
171
172 const char *getBufferStart() const { return Buffer.begin(); }
173 const char *getBufferEnd() const { return Buffer.end(); }
174 size_t getBufferSize() const { return Buffer.size(); }
175 };
176
177 // Create wrappers for C Binding types (see CBindingWrapping.h).
178 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
179
180 } // end namespace llvm
181
182 #endif // LLVM_SUPPORT_MEMORYBUFFER_H
None //===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the MemoryBuffer interface.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Support/MemoryBuffer.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/Config/config.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/Errno.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/Process.h"
22 #include "llvm/Support/Program.h"
23 #include
24 #include
25 #include
26 #include
27 #include
28 #include
29 #if !defined(_MSC_VER) && !defined(__MINGW32__)
30 #include
31 #else
32 #include
33 #endif
34 using namespace llvm;
35
36 //===----------------------------------------------------------------------===//
37 // MemoryBuffer implementation itself.
38 //===----------------------------------------------------------------------===//
39
40 MemoryBuffer::~MemoryBuffer() { }
41
42 /// init - Initialize this MemoryBuffer as a reference to externally allocated
43 /// memory, memory that we know is already null terminated.
44 void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
45 bool RequiresNullTerminator) {
46 assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
47 "Buffer is not null terminated!");
48 BufferStart = BufStart;
49 BufferEnd = BufEnd;
50 }
51
52 //===----------------------------------------------------------------------===//
53 // MemoryBufferMem implementation.
54 //===----------------------------------------------------------------------===//
55
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 if (!Data.empty())
60 memcpy(Memory, Data.data(), Data.size());
61 Memory[Data.size()] = 0; // Null terminate string.
62 }
63
64 namespace {
65 struct NamedBufferAlloc {
66 const Twine &Name;
67 NamedBufferAlloc(const Twine &Name) : Name(Name) {}
68 };
69 }
70
71 void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
72 SmallString<256> NameBuf;
73 StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
74
75 char *Mem = static_cast(operator new(N + NameRef.size() + 1));
76 CopyStringRef(Mem + N, NameRef);
77 return Mem;
78 }
79
80 namespace {
81 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
82 class MemoryBufferMem : public MemoryBuffer {
83 public:
84 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
85 init(InputData.begin(), InputData.end(), RequiresNullTerminator);
86 }
87
88 /// Disable sized deallocation for MemoryBufferMem, because it has
89 /// tail-allocated data.
90 void operator delete(void *p) { ::operator delete(p); }
91
92 StringRef getBufferIdentifier() const override {
93 // The name is stored after the class itself.
94 return StringRef(reinterpret_cast(this + 1));
95 }
96
97 BufferKind getBufferKind() const override {
98 return MemoryBuffer_Malloc;
99 }
100 };
101 }
102
103 static ErrorOr>
104 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
105 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
106
107 std::unique_ptr
108 MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
109 bool RequiresNullTerminator) {
110 auto *Ret = new (NamedBufferAlloc(BufferName))
111 MemoryBufferMem(InputData, RequiresNullTerminator);
112 return std::unique_ptr(Ret);
113 }
114
115 std::unique_ptr
116 MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) {
117 return std::unique_ptr(getMemBuffer(
118 Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
119 }
120
121 std::unique_ptr
122 MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) {
123 std::unique_ptr Buf =
124 getNewUninitMemBuffer(InputData.size(), BufferName);
125 if (!Buf)
126 return nullptr;
127 memcpy(const_cast(Buf->getBufferStart()), InputData.data(),
128 InputData.size());
129 return Buf;
130 }
131
132 std::unique_ptr
133 MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
134 // Allocate space for the MemoryBuffer, the data and the name. It is important
135 // that MemoryBuffer and data are aligned so PointerIntPair works with them.
136 // TODO: Is 16-byte alignment enough? We copy small object files with large
137 // alignment expectations into this buffer.
138 SmallString<256> NameBuf;
139 StringRef NameRef = BufferName.toStringRef(NameBuf);
140 size_t AlignedStringLen =
141 alignTo(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);
142 size_t RealLen = AlignedStringLen + Size + 1;
143 char *Mem = static_cast(operator new(RealLen, std::nothrow));
144 if (!Mem)
145 return nullptr;
146
147 // The name is stored after the class itself.
148 CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef);
149
150 // The buffer begins after the name and must be aligned.
151 char *Buf = Mem + AlignedStringLen;
152 Buf[Size] = 0; // Null terminate buffer.
153
154 auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
155 return std::unique_ptr(Ret);
156 }
157
158 std::unique_ptr
159 MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
160 std::unique_ptr SB = getNewUninitMemBuffer(Size, BufferName);
161 if (!SB)
162 return nullptr;
163 memset(const_cast(SB->getBufferStart()), 0, Size);
164 return SB;
165 }
166
167 ErrorOr>
168 MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize,
169 bool RequiresNullTerminator) {
170 SmallString<256> NameBuf;
171 StringRef NameRef = Filename.toStringRef(NameBuf);
172
173 if (NameRef == "-")
174 return getSTDIN();
175 return getFile(Filename, FileSize, RequiresNullTerminator);
176 }
177
178 ErrorOr>
179 MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
180 uint64_t Offset) {
181 return getFileAux(FilePath, -1, MapSize, Offset, false, false);
182 }
183
184
185 //===----------------------------------------------------------------------===//
186 // MemoryBuffer::getFile implementation.
187 //===----------------------------------------------------------------------===//
188
189 namespace {
190 /// \brief Memory maps a file descriptor using sys::fs::mapped_file_region.
191 ///
192 /// This handles converting the offset into a legal offset on the platform.
193 class MemoryBufferMMapFile : public MemoryBuffer {
194 sys::fs::mapped_file_region MFR;
195
196 static uint64_t getLegalMapOffset(uint64_t Offset) {
197 return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
198 }
199
200 static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
201 return Len + (Offset - getLegalMapOffset(Offset));
202 }
203
204 const char *getStart(uint64_t Len, uint64_t Offset) {
205 return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
206 }
207
208 public:
209 MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
210 uint64_t Offset, std::error_code &EC)
211 : MFR(FD, sys::fs::mapped_file_region::readonly,
212 getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
213 if (!EC) {
214 const char *Start = getStart(Len, Offset);
215 init(Start, Start + Len, RequiresNullTerminator);
216 }
217 }
218
219 /// Disable sized deallocation for MemoryBufferMMapFile, because it has
220 /// tail-allocated data.
221 void operator delete(void *p) { ::operator delete(p); }
222
223 StringRef getBufferIdentifier() const override {
224 // The name is stored after the class itself.
225 return StringRef(reinterpret_cast(this + 1));
226 }
227
228 BufferKind getBufferKind() const override {
229 return MemoryBuffer_MMap;
230 }
231 };
232 }
233
234 static ErrorOr>
235 getMemoryBufferForStream(int FD, const Twine &BufferName) {
236 const ssize_t ChunkSize = 4096*4;
237 SmallString Buffer;
238 ssize_t ReadBytes;
239 // Read into Buffer until we hit EOF.
240 do {
241 Buffer.reserve(Buffer.size() + ChunkSize);
242 ReadBytes = read(FD, Buffer.end(), ChunkSize);
243 if (ReadBytes == -1) {
244 if (errno == EINTR) continue;
245 return std::error_code(errno, std::generic_category());
246 }
247 Buffer.set_size(Buffer.size() + ReadBytes);
248 } while (ReadBytes != 0);
249
250 return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);
251 }
252
253
254 ErrorOr>
255 MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
256 bool RequiresNullTerminator, bool IsVolatileSize) {
257 return getFileAux(Filename, FileSize, FileSize, 0,
258 RequiresNullTerminator, IsVolatileSize);
259 }
260
261 static ErrorOr>
262 getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
263 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
264 bool IsVolatileSize);
265
266 static ErrorOr>
267 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
268 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
269 int FD;
270 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
271 if (EC)
272 return EC;
273
274 ErrorOr> Ret =
275 getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
276 RequiresNullTerminator, IsVolatileSize);
277 close(FD);
278 return Ret;
279 }
280
281 static bool shouldUseMmap(int FD,
282 size_t FileSize,
283 size_t MapSize,
284 off_t Offset,
285 bool RequiresNullTerminator,
286 int PageSize,
287 bool IsVolatileSize) {
288 // mmap may leave the buffer without null terminator if the file size changed
289 // by the time the last page is mapped in, so avoid it if the file size is
290 // likely to change.
291 if (IsVolatileSize)
292 return false;
293
294 // We don't use mmap for small files because this can severely fragment our
295 // address space.
296 if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
297 return false;
298
299 if (!RequiresNullTerminator)
300 return true;
301
302
303 // If we don't know the file size, use fstat to find out. fstat on an open
304 // file descriptor is cheaper than stat on a random path.
305 // FIXME: this chunk of code is duplicated, but it avoids a fstat when
306 // RequiresNullTerminator = false and MapSize != -1.
307 if (FileSize == size_t(-1)) {
308 sys::fs::file_status Status;
309 if (sys::fs::status(FD, Status))
310 return false;
311 FileSize = Status.getSize();
312 }
313
314 // If we need a null terminator and the end of the map is inside the file,
315 // we cannot use mmap.
316 size_t End = Offset + MapSize;
317 assert(End <= FileSize);
318 if (End != FileSize)
319 return false;
320
321 // Don't try to map files that are exactly a multiple of the system page size
322 // if we need a null terminator.
323 if ((FileSize & (PageSize -1)) == 0)
324 return false;
325
326 #if defined(__CYGWIN__)
327 // Don't try to map files that are exactly a multiple of the physical page size
328 // if we need a null terminator.
329 // FIXME: We should reorganize again getPageSize() on Win32.
330 if ((FileSize & (4096 - 1)) == 0)
331 return false;
332 #endif
333
334 return true;
335 }
336
337 static ErrorOr>
338 getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
339 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
340 bool IsVolatileSize) {
341 static int PageSize = sys::Process::getPageSize();
342
343 // Default is to map the full file.
344 if (MapSize == uint64_t(-1)) {
345 // If we don't know the file size, use fstat to find out. fstat on an open
346 // file descriptor is cheaper than stat on a random path.
347 if (FileSize == uint64_t(-1)) {
348 sys::fs::file_status Status;
349 std::error_code EC = sys::fs::status(FD, Status);
350 if (EC)
351 return EC;
352
353 // If this not a file or a block device (e.g. it's a named pipe
354 // or character device), we can't trust the size. Create the memory
355 // buffer by copying off the stream.
356 sys::fs::file_type Type = Status.type();
357 if (Type != sys::fs::file_type::regular_file &&
358 Type != sys::fs::file_type::block_file)
359 return getMemoryBufferForStream(FD, Filename);
360
361 FileSize = Status.getSize();
362 }
363 MapSize = FileSize;
364 }
365
366 if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
367 PageSize, IsVolatileSize)) {
368 std::error_code EC;
369 std::unique_ptr Result(
370 new (NamedBufferAlloc(Filename))
371 MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC));
372 if (!EC)
373 return std::move(Result);
374 }
375
376 std::unique_ptr Buf =
377 MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
378 if (!Buf) {
379 // Failed to create a buffer. The only way it can fail is if
380 // new(std::nothrow) returns 0.
381 return make_error_code(errc::not_enough_memory);
382 }
383
384 char *BufPtr = const_cast(Buf->getBufferStart());
385
386 size_t BytesLeft = MapSize;
387 #ifndef HAVE_PREAD
388 if (lseek(FD, Offset, SEEK_SET) == -1)
389 return std::error_code(errno, std::generic_category());
390 #endif
391
392 while (BytesLeft) {
393 #ifdef HAVE_PREAD
394 ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
395 #else
396 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
397 #endif
398 if (NumRead == -1) {
399 if (errno == EINTR)
400 continue;
401 // Error while reading.
402 return std::error_code(errno, std::generic_category());
403 }
404 if (NumRead == 0) {
405 memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.
406 break;
407 }
408 BytesLeft -= NumRead;
409 BufPtr += NumRead;
410 }
411
412 return std::move(Buf);
413 }
414
415 ErrorOr>
416 MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
417 bool RequiresNullTerminator, bool IsVolatileSize) {
418 return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
419 RequiresNullTerminator, IsVolatileSize);
420 }
421
422 ErrorOr>
423 MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
424 int64_t Offset) {
425 assert(MapSize != uint64_t(-1));
426 return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false,
427 /*IsVolatileSize*/ false);
428 }
429
430 ErrorOr> MemoryBuffer::getSTDIN() {
431 // Read in all of the data from stdin, we cannot mmap stdin.
432 //
433 // FIXME: That isn't necessarily true, we should try to mmap stdin and
434 // fallback if it fails.
435 sys::ChangeStdinToBinary();
436
437 return getMemoryBufferForStream(0, "");
438 }
439
440 ErrorOr>
441 MemoryBuffer::getFileAsStream(const Twine &Filename) {
442 int FD;
443 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
444 if (EC)
445 return EC;
446 ErrorOr> Ret =
447 getMemoryBufferForStream(FD, Filename);
448 close(FD);
449 return Ret;
450 }
451
452 MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
453 StringRef Data = getBuffer();
454 StringRef Identifier = getBufferIdentifier();
455 return MemoryBufferRef(Data, Identifier);
456 }
0 //===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the MemoryBuffer interface.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Support/MemoryBuffer.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/Config/config.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/Errno.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/Process.h"
22 #include "llvm/Support/Program.h"
23 #include
24 #include
25 #include
26 #include
27 #include
28 #include
29 #if !defined(_MSC_VER) && !defined(__MINGW32__)
30 #include
31 #else
32 #include
33 #endif
34 using namespace llvm;
35
36 //===----------------------------------------------------------------------===//
37 // MemoryBuffer implementation itself.
38 //===----------------------------------------------------------------------===//
39
40 MemoryBuffer::~MemoryBuffer() { }
41
42 /// init - Initialize this MemoryBuffer as a reference to externally allocated
43 /// memory, memory that we know is already null terminated.
44 void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
45 bool RequiresNullTerminator) {
46 assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
47 "Buffer is not null terminated!");
48 BufferStart = BufStart;
49 BufferEnd = BufEnd;
50 }
51
52 //===----------------------------------------------------------------------===//
53 // MemoryBufferMem implementation.
54 //===----------------------------------------------------------------------===//
55
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 if (!Data.empty())
60 memcpy(Memory, Data.data(), Data.size());
61 Memory[Data.size()] = 0; // Null terminate string.
62 }
63
64 namespace {
65 struct NamedBufferAlloc {
66 const Twine &Name;
67 NamedBufferAlloc(const Twine &Name) : Name(Name) {}
68 };
69 }
70
71 void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
72 SmallString<256> NameBuf;
73 StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
74
75 char *Mem = static_cast(operator new(N + NameRef.size() + 1));
76 CopyStringRef(Mem + N, NameRef);
77 return Mem;
78 }
79
80 namespace {
81 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
82 class MemoryBufferMem : public MemoryBuffer {
83 public:
84 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
85 init(InputData.begin(), InputData.end(), RequiresNullTerminator);
86 }
87
88 /// Disable sized deallocation for MemoryBufferMem, because it has
89 /// tail-allocated data.
90 void operator delete(void *p) { ::operator delete(p); }
91
92 StringRef getBufferIdentifier() const override {
93 // The name is stored after the class itself.
94 return StringRef(reinterpret_cast(this + 1));
95 }
96
97 BufferKind getBufferKind() const override {
98 return MemoryBuffer_Malloc;
99 }
100 };
101 }
102
103 static ErrorOr>
104 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
105 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
106
107 std::unique_ptr
108 MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
109 bool RequiresNullTerminator) {
110 auto *Ret = new (NamedBufferAlloc(BufferName))
111 MemoryBufferMem(InputData, RequiresNullTerminator);
112 return std::unique_ptr(Ret);
113 }
114
115 std::unique_ptr
116 MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) {
117 return std::unique_ptr(getMemBuffer(
118 Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
119 }
120
121 std::unique_ptr
122 MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) {
123 std::unique_ptr Buf =
124 getNewUninitMemBuffer(InputData.size(), BufferName);
125 if (!Buf)
126 return nullptr;
127 memcpy(const_cast(Buf->getBufferStart()), InputData.data(),
128 InputData.size());
129 return Buf;
130 }
131
132 std::unique_ptr
133 MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
134 // Allocate space for the MemoryBuffer, the data and the name. It is important
135 // that MemoryBuffer and data are aligned so PointerIntPair works with them.
136 // TODO: Is 16-byte alignment enough? We copy small object files with large
137 // alignment expectations into this buffer.
138 SmallString<256> NameBuf;
139 StringRef NameRef = BufferName.toStringRef(NameBuf);
140 size_t AlignedStringLen =
141 alignTo(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);
142 size_t RealLen = AlignedStringLen + Size + 1;
143 char *Mem = static_cast(operator new(RealLen, std::nothrow));
144 if (!Mem)
145 return nullptr;
146
147 // The name is stored after the class itself.
148 CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef);
149
150 // The buffer begins after the name and must be aligned.
151 char *Buf = Mem + AlignedStringLen;
152 Buf[Size] = 0; // Null terminate buffer.
153
154 auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
155 return std::unique_ptr(Ret);
156 }
157
158 std::unique_ptr
159 MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
160 std::unique_ptr SB = getNewUninitMemBuffer(Size, BufferName);
161 if (!SB)
162 return nullptr;
163 memset(const_cast(SB->getBufferStart()), 0, Size);
164 return SB;
165 }
166
167 ErrorOr>
168 MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize,
169 bool RequiresNullTerminator) {
170 SmallString<256> NameBuf;
171 StringRef NameRef = Filename.toStringRef(NameBuf);
172
173 if (NameRef == "-")
174 return getSTDIN();
175 return getFile(Filename, FileSize, RequiresNullTerminator);
176 }
177
178 ErrorOr>
179 MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
180 uint64_t Offset) {
181 return getFileAux(FilePath, -1, MapSize, Offset, false, false);
182 }
183
184
185 //===----------------------------------------------------------------------===//
186 // MemoryBuffer::getFile implementation.
187 //===----------------------------------------------------------------------===//
188
189 namespace {
190 /// \brief Memory maps a file descriptor using sys::fs::mapped_file_region.
191 ///
192 /// This handles converting the offset into a legal offset on the platform.
193 class MemoryBufferMMapFile : public MemoryBuffer {
194 sys::fs::mapped_file_region MFR;
195
196 static uint64_t getLegalMapOffset(uint64_t Offset) {
197 return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
198 }
199
200 static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
201 return Len + (Offset - getLegalMapOffset(Offset));
202 }
203
204 const char *getStart(uint64_t Len, uint64_t Offset) {
205 return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
206 }
207
208 public:
209 MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
210 uint64_t Offset, std::error_code &EC)
211 : MFR(FD, sys::fs::mapped_file_region::readonly,
212 getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
213 if (!EC) {
214 const char *Start = getStart(Len, Offset);
215 init(Start, Start + Len, RequiresNullTerminator);
216 }
217 }
218
219 /// Disable sized deallocation for MemoryBufferMMapFile, because it has
220 /// tail-allocated data.
221 void operator delete(void *p) { ::operator delete(p); }
222
223 StringRef getBufferIdentifier() const override {
224 // The name is stored after the class itself.
225 return StringRef(reinterpret_cast(this + 1));
226 }
227
228 BufferKind getBufferKind() const override {
229 return MemoryBuffer_MMap;
230 }
231 };
232 }
233
234 static ErrorOr>
235 getMemoryBufferForStream(int FD, const Twine &BufferName) {
236 const ssize_t ChunkSize = 4096*4;
237 SmallString Buffer;
238 ssize_t ReadBytes;
239 // Read into Buffer until we hit EOF.
240 do {
241 Buffer.reserve(Buffer.size() + ChunkSize);
242 ReadBytes = read(FD, Buffer.end(), ChunkSize);
243 if (ReadBytes == -1) {
244 if (errno == EINTR) continue;
245 return std::error_code(errno, std::generic_category());
246 }
247 Buffer.set_size(Buffer.size() + ReadBytes);
248 } while (ReadBytes != 0);
249
250 return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);
251 }
252
253
254 ErrorOr>
255 MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
256 bool RequiresNullTerminator, bool IsVolatileSize) {
257 return getFileAux(Filename, FileSize, FileSize, 0,
258 RequiresNullTerminator, IsVolatileSize);
259 }
260
261 static ErrorOr>
262 getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
263 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
264 bool IsVolatileSize);
265
266 static ErrorOr>
267 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
268 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
269 int FD;
270 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
271 if (EC)
272 return EC;
273
274 ErrorOr> Ret =
275 getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
276 RequiresNullTerminator, IsVolatileSize);
277 close(FD);
278 return Ret;
279 }
280
281 static bool shouldUseMmap(int FD,
282 size_t FileSize,
283 size_t MapSize,
284 off_t Offset,
285 bool RequiresNullTerminator,
286 int PageSize,
287 bool IsVolatileSize) {
288 // mmap may leave the buffer without null terminator if the file size changed
289 // by the time the last page is mapped in, so avoid it if the file size is
290 // likely to change.
291 if (IsVolatileSize)
292 return false;
293
294 // We don't use mmap for small files because this can severely fragment our
295 // address space.
296 if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
297 return false;
298
299 if (!RequiresNullTerminator)
300 return true;
301
302
303 // If we don't know the file size, use fstat to find out. fstat on an open
304 // file descriptor is cheaper than stat on a random path.
305 // FIXME: this chunk of code is duplicated, but it avoids a fstat when
306 // RequiresNullTerminator = false and MapSize != -1.
307 if (FileSize == size_t(-1)) {
308 sys::fs::file_status Status;
309 if (sys::fs::status(FD, Status))
310 return false;
311 FileSize = Status.getSize();
312 }
313
314 // If we need a null terminator and the end of the map is inside the file,
315 // we cannot use mmap.
316 size_t End = Offset + MapSize;
317 assert(End <= FileSize);
318 if (End != FileSize)
319 return false;
320
321 // Don't try to map files that are exactly a multiple of the system page size
322 // if we need a null terminator.
323 if ((FileSize & (PageSize -1)) == 0)
324 return false;
325
326 #if defined(__CYGWIN__)
327 // Don't try to map files that are exactly a multiple of the physical page size
328 // if we need a null terminator.
329 // FIXME: We should reorganize again getPageSize() on Win32.
330 if ((FileSize & (4096 - 1)) == 0)
331 return false;
332 #endif
333
334 return true;
335 }
336
337 static ErrorOr>
338 getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
339 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
340 bool IsVolatileSize) {
341 static int PageSize = sys::Process::getPageSize();
342
343 // Default is to map the full file.
344 if (MapSize == uint64_t(-1)) {
345 // If we don't know the file size, use fstat to find out. fstat on an open
346 // file descriptor is cheaper than stat on a random path.
347 if (FileSize == uint64_t(-1)) {
348 sys::fs::file_status Status;
349 std::error_code EC = sys::fs::status(FD, Status);
350 if (EC)
351 return EC;
352
353 // If this not a file or a block device (e.g. it's a named pipe
354 // or character device), we can't trust the size. Create the memory
355 // buffer by copying off the stream.
356 sys::fs::file_type Type = Status.type();
357 if (Type != sys::fs::file_type::regular_file &&
358 Type != sys::fs::file_type::block_file)
359 return getMemoryBufferForStream(FD, Filename);
360
361 FileSize = Status.getSize();
362 }
363 MapSize = FileSize;
364 }
365
366 if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
367 PageSize, IsVolatileSize)) {
368 std::error_code EC;
369 std::unique_ptr Result(
370 new (NamedBufferAlloc(Filename))
371 MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC));
372 if (!EC)
373 return std::move(Result);
374 }
375
376 std::unique_ptr Buf =
377 MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
378 if (!Buf) {
379 // Failed to create a buffer. The only way it can fail is if
380 // new(std::nothrow) returns 0.
381 return make_error_code(errc::not_enough_memory);
382 }
383
384 char *BufPtr = const_cast(Buf->getBufferStart());
385
386 size_t BytesLeft = MapSize;
387 #ifndef HAVE_PREAD
388 if (lseek(FD, Offset, SEEK_SET) == -1)
389 return std::error_code(errno, std::generic_category());
390 #endif
391
392 while (BytesLeft) {
393 #ifdef HAVE_PREAD
394 ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
395 #else
396 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
397 #endif
398 if (NumRead == -1) {
399 if (errno == EINTR)
400 continue;
401 // Error while reading.
402 return std::error_code(errno, std::generic_category());
403 }
404 if (NumRead == 0) {
405 memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.
406 break;
407 }
408 BytesLeft -= NumRead;
409 BufPtr += NumRead;
410 }
411
412 return std::move(Buf);
413 }
414
415 ErrorOr>
416 MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
417 bool RequiresNullTerminator, bool IsVolatileSize) {
418 return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
419 RequiresNullTerminator, IsVolatileSize);
420 }
421
422 ErrorOr>
423 MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
424 int64_t Offset) {
425 assert(MapSize != uint64_t(-1));
426 return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false,
427 /*IsVolatileSize*/ false);
428 }
429
430 ErrorOr> MemoryBuffer::getSTDIN() {
431 // Read in all of the data from stdin, we cannot mmap stdin.
432 //
433 // FIXME: That isn't necessarily true, we should try to mmap stdin and
434 // fallback if it fails.
435 sys::ChangeStdinToBinary();
436
437 return getMemoryBufferForStream(0, "");
438 }
439
440 ErrorOr>
441 MemoryBuffer::getFileAsStream(const Twine &Filename) {
442 int FD;
443 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
444 if (EC)
445 return EC;
446 ErrorOr> Ret =
447 getMemoryBufferForStream(FD, Filename);
448 close(FD);
449 return Ret;
450 }
451
452 MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
453 StringRef Data = getBuffer();
454 StringRef Identifier = getBufferIdentifier();
455 return MemoryBufferRef(Data, Identifier);
456 }