LLVM  14.0.0git
BinaryByteStream.h
Go to the documentation of this file.
1 //===- BinaryByteStream.h ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //===----------------------------------------------------------------------===//
7 // A BinaryStream which stores data in a single continguous memory buffer.
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
11 #define LLVM_SUPPORT_BINARYBYTESTREAM_H
12 
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Error.h"
20 #include <algorithm>
21 #include <cstdint>
22 #include <cstring>
23 #include <memory>
24 
25 namespace llvm {
26 
27 /// An implementation of BinaryStream which holds its entire data set
28 /// in a single contiguous buffer. BinaryByteStream guarantees that no read
29 /// operation will ever incur a copy. Note that BinaryByteStream does not
30 /// own the underlying buffer.
32 public:
33  BinaryByteStream() = default;
35  : Endian(Endian), Data(Data) {}
37  : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
38 
39  llvm::support::endianness getEndian() const override { return Endian; }
40 
42  ArrayRef<uint8_t> &Buffer) override {
43  if (auto EC = checkOffsetForRead(Offset, Size))
44  return EC;
45  Buffer = Data.slice(Offset, Size);
46  return Error::success();
47  }
48 
50  ArrayRef<uint8_t> &Buffer) override {
51  if (auto EC = checkOffsetForRead(Offset, 1))
52  return EC;
53  Buffer = Data.slice(Offset);
54  return Error::success();
55  }
56 
57  uint32_t getLength() override { return Data.size(); }
58 
59  ArrayRef<uint8_t> data() const { return Data; }
60 
61  StringRef str() const {
62  const char *CharData = reinterpret_cast<const char *>(Data.data());
63  return StringRef(CharData, Data.size());
64  }
65 
66 protected:
69 };
70 
71 /// An implementation of BinaryStream whose data is backed by an llvm
72 /// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
73 /// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
74 /// will never cause a copy.
76 public:
77  MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
79  : BinaryByteStream(Buffer->getBuffer(), Endian),
80  MemBuffer(std::move(Buffer)) {}
81 
82  std::unique_ptr<MemoryBuffer> MemBuffer;
83 };
84 
85 /// An implementation of BinaryStream which holds its entire data set
86 /// in a single contiguous buffer. As with BinaryByteStream, the mutable
87 /// version also guarantees that no read operation will ever incur a copy,
88 /// and similarly it does not own the underlying buffer.
90 public:
91  MutableBinaryByteStream() = default;
94  : Data(Data), ImmutableStream(Data, Endian) {}
95 
97  return ImmutableStream.getEndian();
98  }
99 
101  ArrayRef<uint8_t> &Buffer) override {
102  return ImmutableStream.readBytes(Offset, Size, Buffer);
103  }
104 
106  ArrayRef<uint8_t> &Buffer) override {
107  return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
108  }
109 
110  uint32_t getLength() override { return ImmutableStream.getLength(); }
111 
113  if (Buffer.empty())
114  return Error::success();
115 
116  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
117  return EC;
118 
119  uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
120  ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
121  return Error::success();
122  }
123 
124  Error commit() override { return Error::success(); }
125 
126  MutableArrayRef<uint8_t> data() const { return Data; }
127 
128 private:
130  BinaryByteStream ImmutableStream;
131 };
132 
133 /// An implementation of WritableBinaryStream which can write at its end
134 /// causing the underlying data to grow. This class owns the underlying data.
136  std::vector<uint8_t> Data;
138 
139 public:
140  AppendingBinaryByteStream() = default;
142  : Endian(Endian) {}
143 
144  void clear() { Data.clear(); }
145 
146  llvm::support::endianness getEndian() const override { return Endian; }
147 
149  ArrayRef<uint8_t> &Buffer) override {
150  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
151  return EC;
152 
153  Buffer = makeArrayRef(Data).slice(Offset, Size);
154  return Error::success();
155  }
156 
158  Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
159  }
160 
162  ArrayRef<uint8_t> &Buffer) override {
163  if (auto EC = checkOffsetForWrite(Offset, 1))
164  return EC;
165 
166  Buffer = makeArrayRef(Data).slice(Offset);
167  return Error::success();
168  }
169 
170  uint32_t getLength() override { return Data.size(); }
171 
173  if (Buffer.empty())
174  return Error::success();
175 
176  // This is well-defined for any case except where offset is strictly
177  // greater than the current length. If offset is equal to the current
178  // length, we can still grow. If offset is beyond the current length, we
179  // would have to decide how to deal with the intermediate uninitialized
180  // bytes. So we punt on that case for simplicity and just say it's an
181  // error.
182  if (Offset > getLength())
183  return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
184 
185  uint32_t RequiredSize = Offset + Buffer.size();
186  if (RequiredSize > Data.size())
187  Data.resize(RequiredSize);
188 
189  ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
190  return Error::success();
191  }
192 
193  Error commit() override { return Error::success(); }
194 
195  /// Return the properties of this stream.
196  virtual BinaryStreamFlags getFlags() const override {
197  return BSF_Write | BSF_Append;
198  }
199 
201 };
202 
203 /// An implementation of WritableBinaryStream backed by an llvm
204 /// FileOutputBuffer.
206 private:
207  class StreamImpl : public MutableBinaryByteStream {
208  public:
209  StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
212  MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
213  Buffer->getBufferEnd()),
214  Endian),
215  FileBuffer(std::move(Buffer)) {}
216 
217  Error commit() override {
218  if (FileBuffer->commit())
219  return make_error<BinaryStreamError>(
221  return Error::success();
222  }
223 
224  /// Returns a pointer to the start of the buffer.
225  uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
226 
227  /// Returns a pointer to the end of the buffer.
228  uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
229 
230  private:
231  std::unique_ptr<FileOutputBuffer> FileBuffer;
232  };
233 
234 public:
235  FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
237  : Impl(std::move(Buffer), Endian) {}
238 
240  return Impl.getEndian();
241  }
242 
244  ArrayRef<uint8_t> &Buffer) override {
245  return Impl.readBytes(Offset, Size, Buffer);
246  }
247 
249  ArrayRef<uint8_t> &Buffer) override {
250  return Impl.readLongestContiguousChunk(Offset, Buffer);
251  }
252 
253  uint32_t getLength() override { return Impl.getLength(); }
254 
256  return Impl.writeBytes(Offset, Data);
257  }
258 
259  Error commit() override { return Impl.commit(); }
260 
261  /// Returns a pointer to the start of the buffer.
262  uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
263 
264  /// Returns a pointer to the end of the buffer.
265  uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
266 
267 private:
268  StreamImpl Impl;
269 };
270 
271 } // end namespace llvm
272 
273 #endif // LLVM_SUPPORT_BINARYBYTESTREAM_H
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
MemoryBuffer.h
llvm::BinaryStream
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:35
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::MutableBinaryByteStream
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Definition: BinaryByteStream.h:89
llvm::AppendingBinaryByteStream::AppendingBinaryByteStream
AppendingBinaryByteStream(llvm::support::endianness Endian)
Definition: BinaryByteStream.h:141
llvm::BinaryByteStream::getLength
uint32_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:57
BinaryStream.h
StringRef.h
llvm::AppendingBinaryByteStream::clear
void clear()
Definition: BinaryByteStream.h:144
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::MutableBinaryByteStream::MutableBinaryByteStream
MutableBinaryByteStream()=default
Error.h
llvm::BinaryByteStream::str
StringRef str() const
Definition: BinaryByteStream.h:61
llvm::FileBufferByteStream::FileBufferByteStream
FileBufferByteStream(std::unique_ptr< FileOutputBuffer > Buffer, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:235
llvm::FileBufferByteStream::writeBytes
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Data) override
Attempt to write the given bytes into the stream at the desired offset.
Definition: BinaryByteStream.h:255
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
FileOutputBuffer.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:56
llvm::AppendingBinaryByteStream::getFlags
virtual BinaryStreamFlags getFlags() const override
Return the properties of this stream.
Definition: BinaryByteStream.h:196
llvm::ArrayRef::empty
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:162
llvm::stream_error_code::invalid_offset
@ invalid_offset
llvm::BinaryByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Definition: BinaryByteStream.h:49
llvm::AppendingBinaryByteStream::AppendingBinaryByteStream
AppendingBinaryByteStream()=default
llvm::MutableArrayRef< uint8_t >
llvm::MutableBinaryByteStream::getLength
uint32_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:110
llvm::support::little
@ little
Definition: Endian.h:27
llvm::BinaryByteStream::BinaryByteStream
BinaryByteStream()=default
llvm::BinaryStreamFlags
BinaryStreamFlags
Definition: BinaryStream.h:21
llvm::BinaryByteStream
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Definition: BinaryByteStream.h:31
llvm::AppendingBinaryByteStream::readBytes
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
Definition: BinaryByteStream.h:148
llvm::AppendingBinaryByteStream
An implementation of WritableBinaryStream which can write at its end causing the underlying data to g...
Definition: BinaryByteStream.h:135
BinaryStreamError.h
llvm::AppendingBinaryByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:146
llvm::AppendingBinaryByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Definition: BinaryByteStream.h:161
llvm::BinaryByteStream::data
ArrayRef< uint8_t > data() const
Definition: BinaryByteStream.h:59
llvm::MutableBinaryByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Definition: BinaryByteStream.h:105
llvm::AppendingBinaryByteStream::data
MutableArrayRef< uint8_t > data()
Definition: BinaryByteStream.h:200
llvm::MutableBinaryByteStream::MutableBinaryByteStream
MutableBinaryByteStream(MutableArrayRef< uint8_t > Data, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:92
llvm::MemoryBufferByteStream::MemBuffer
std::unique_ptr< MemoryBuffer > MemBuffer
Definition: BinaryByteStream.h:82
llvm::ArrayRef::slice
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Definition: ArrayRef.h:195
llvm::BinaryByteStream::readBytes
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
Definition: BinaryByteStream.h:41
llvm::AppendingBinaryByteStream::commit
Error commit() override
For buffered streams, commits changes to the backing store.
Definition: BinaryByteStream.h:193
llvm::MutableBinaryByteStream::writeBytes
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Definition: BinaryByteStream.h:112
llvm::AppendingBinaryByteStream::writeBytes
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Definition: BinaryByteStream.h:172
llvm::BSF_Append
@ BSF_Append
Definition: BinaryStream.h:24
llvm::BinaryStream::checkOffsetForRead
Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize)
Definition: BinaryStream.h:59
llvm::WritableBinaryStream::checkOffsetForWrite
Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize)
Definition: BinaryStream.h:89
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
ArrayRef.h
llvm::AppendingBinaryByteStream::insert
void insert(uint32_t Offset, ArrayRef< uint8_t > Bytes)
Definition: BinaryByteStream.h:157
llvm::AppendingBinaryByteStream::getLength
uint32_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:170
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1605
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::MutableBinaryByteStream::commit
Error commit() override
For buffered streams, commits changes to the backing store.
Definition: BinaryByteStream.h:124
llvm::BinaryByteStream::Endian
llvm::support::endianness Endian
Definition: BinaryByteStream.h:67
llvm::BinaryByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:39
llvm::MemoryBufferByteStream
An implementation of BinaryStream whose data is backed by an llvm MemoryBuffer object.
Definition: BinaryByteStream.h:75
llvm::ArrayRef< uint8_t >
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
llvm::MutableArrayRef::data
T * data() const
Definition: ArrayRef.h:354
llvm::FileBufferByteStream::commit
Error commit() override
For buffered streams, commits changes to the backing store.
Definition: BinaryByteStream.h:259
llvm::BSF_Write
@ BSF_Write
Definition: BinaryStream.h:23
llvm::FileBufferByteStream
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
Definition: BinaryByteStream.h:205
std
Definition: BitVector.h:838
llvm::ArrayRef::begin
iterator begin() const
Definition: ArrayRef.h:153
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::BinaryByteStream::Data
ArrayRef< uint8_t > Data
Definition: BinaryByteStream.h:68
llvm::FileBufferByteStream::getBufferEnd
uint8_t * getBufferEnd() const
Returns a pointer to the end of the buffer.
Definition: BinaryByteStream.h:265
llvm::FileBufferByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:239
llvm::makeArrayRef
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:476
llvm::BinaryByteStream::BinaryByteStream
BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:36
llvm::BinaryByteStream::BinaryByteStream
BinaryByteStream(ArrayRef< uint8_t > Data, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:34
llvm::FileBufferByteStream::getLength
uint32_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:253
llvm::FileBufferByteStream::getBufferStart
uint8_t * getBufferStart() const
Returns a pointer to the start of the buffer.
Definition: BinaryByteStream.h:262
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
llvm::stream_error_code::filesystem_error
@ filesystem_error
llvm::support::endianness
endianness
Definition: Endian.h:27
llvm::FileBufferByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Definition: BinaryByteStream.h:248
llvm::MutableBinaryByteStream::readBytes
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
Definition: BinaryByteStream.h:100
llvm::MemoryBufferByteStream::MemoryBufferByteStream
MemoryBufferByteStream(std::unique_ptr< MemoryBuffer > Buffer, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:77
llvm::WritableBinaryStream
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:73
llvm::FileBufferByteStream::readBytes
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
Definition: BinaryByteStream.h:243
llvm::MutableBinaryByteStream::data
MutableArrayRef< uint8_t > data() const
Definition: BinaryByteStream.h:126
llvm::ArrayRef::end
iterator end() const
Definition: ArrayRef.h:154
llvm::MutableBinaryByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:96