LLVM  15.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 <cstdint>
21 #include <cstring>
22 #include <memory>
23 
24 namespace llvm {
25 
26 /// An implementation of BinaryStream which holds its entire data set
27 /// in a single contiguous buffer. BinaryByteStream guarantees that no read
28 /// operation will ever incur a copy. Note that BinaryByteStream does not
29 /// own the underlying buffer.
31 public:
32  BinaryByteStream() = default;
34  : Endian(Endian), Data(Data) {}
36  : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
37 
38  llvm::support::endianness getEndian() const override { return Endian; }
39 
41  ArrayRef<uint8_t> &Buffer) override {
42  if (auto EC = checkOffsetForRead(Offset, Size))
43  return EC;
44  Buffer = Data.slice(Offset, Size);
45  return Error::success();
46  }
47 
49  ArrayRef<uint8_t> &Buffer) override {
50  if (auto EC = checkOffsetForRead(Offset, 1))
51  return EC;
52  Buffer = Data.slice(Offset);
53  return Error::success();
54  }
55 
56  uint64_t getLength() override { return Data.size(); }
57 
58  ArrayRef<uint8_t> data() const { return Data; }
59 
60  StringRef str() const {
61  const char *CharData = reinterpret_cast<const char *>(Data.data());
62  return StringRef(CharData, Data.size());
63  }
64 
65 protected:
68 };
69 
70 /// An implementation of BinaryStream whose data is backed by an llvm
71 /// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
72 /// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
73 /// will never cause a copy.
75 public:
76  MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
78  : BinaryByteStream(Buffer->getBuffer(), Endian),
79  MemBuffer(std::move(Buffer)) {}
80 
81  std::unique_ptr<MemoryBuffer> MemBuffer;
82 };
83 
84 /// An implementation of BinaryStream which holds its entire data set
85 /// in a single contiguous buffer. As with BinaryByteStream, the mutable
86 /// version also guarantees that no read operation will ever incur a copy,
87 /// and similarly it does not own the underlying buffer.
89 public:
90  MutableBinaryByteStream() = default;
93  : Data(Data), ImmutableStream(Data, Endian) {}
94 
96  return ImmutableStream.getEndian();
97  }
98 
100  ArrayRef<uint8_t> &Buffer) override {
101  return ImmutableStream.readBytes(Offset, Size, Buffer);
102  }
103 
105  ArrayRef<uint8_t> &Buffer) override {
106  return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
107  }
108 
109  uint64_t getLength() override { return ImmutableStream.getLength(); }
110 
111  Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override {
112  if (Buffer.empty())
113  return Error::success();
114 
115  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
116  return EC;
117 
118  uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
119  ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
120  return Error::success();
121  }
122 
123  Error commit() override { return Error::success(); }
124 
125  MutableArrayRef<uint8_t> data() const { return Data; }
126 
127 private:
129  BinaryByteStream ImmutableStream;
130 };
131 
132 /// An implementation of WritableBinaryStream which can write at its end
133 /// causing the underlying data to grow. This class owns the underlying data.
135  std::vector<uint8_t> Data;
137 
138 public:
139  AppendingBinaryByteStream() = default;
141  : Endian(Endian) {}
142 
143  void clear() { Data.clear(); }
144 
145  llvm::support::endianness getEndian() const override { return Endian; }
146 
148  ArrayRef<uint8_t> &Buffer) override {
149  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
150  return EC;
151 
152  Buffer = makeArrayRef(Data).slice(Offset, Size);
153  return Error::success();
154  }
155 
156  void insert(uint64_t Offset, ArrayRef<uint8_t> Bytes) {
157  Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
158  }
159 
161  ArrayRef<uint8_t> &Buffer) override {
162  if (auto EC = checkOffsetForWrite(Offset, 1))
163  return EC;
164 
165  Buffer = makeArrayRef(Data).slice(Offset);
166  return Error::success();
167  }
168 
169  uint64_t getLength() override { return Data.size(); }
170 
171  Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override {
172  if (Buffer.empty())
173  return Error::success();
174 
175  // This is well-defined for any case except where offset is strictly
176  // greater than the current length. If offset is equal to the current
177  // length, we can still grow. If offset is beyond the current length, we
178  // would have to decide how to deal with the intermediate uninitialized
179  // bytes. So we punt on that case for simplicity and just say it's an
180  // error.
181  if (Offset > getLength())
182  return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
183 
184  uint64_t RequiredSize = Offset + Buffer.size();
185  if (RequiredSize > Data.size())
186  Data.resize(RequiredSize);
187 
188  ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
189  return Error::success();
190  }
191 
192  Error commit() override { return Error::success(); }
193 
194  /// Return the properties of this stream.
195  virtual BinaryStreamFlags getFlags() const override {
196  return BSF_Write | BSF_Append;
197  }
198 
200 };
201 
202 /// An implementation of WritableBinaryStream backed by an llvm
203 /// FileOutputBuffer.
205 private:
206  class StreamImpl : public MutableBinaryByteStream {
207  public:
208  StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
211  MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
212  Buffer->getBufferEnd()),
213  Endian),
214  FileBuffer(std::move(Buffer)) {}
215 
216  Error commit() override {
217  if (FileBuffer->commit())
218  return make_error<BinaryStreamError>(
220  return Error::success();
221  }
222 
223  /// Returns a pointer to the start of the buffer.
224  uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
225 
226  /// Returns a pointer to the end of the buffer.
227  uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
228 
229  private:
230  std::unique_ptr<FileOutputBuffer> FileBuffer;
231  };
232 
233 public:
234  FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
236  : Impl(std::move(Buffer), Endian) {}
237 
239  return Impl.getEndian();
240  }
241 
243  ArrayRef<uint8_t> &Buffer) override {
244  return Impl.readBytes(Offset, Size, Buffer);
245  }
246 
248  ArrayRef<uint8_t> &Buffer) override {
249  return Impl.readLongestContiguousChunk(Offset, Buffer);
250  }
251 
252  uint64_t getLength() override { return Impl.getLength(); }
253 
255  return Impl.writeBytes(Offset, Data);
256  }
257 
258  Error commit() override { return Impl.commit(); }
259 
260  /// Returns a pointer to the start of the buffer.
261  uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
262 
263  /// Returns a pointer to the end of the buffer.
264  uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
265 
266 private:
267  StreamImpl Impl;
268 };
269 
270 } // end namespace llvm
271 
272 #endif // LLVM_SUPPORT_BINARYBYTESTREAM_H
MemoryBuffer.h
llvm::BinaryByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint64_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:48
llvm::BinaryStream
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:35
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::FileBufferByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint64_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:247
llvm::MutableBinaryByteStream
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Definition: BinaryByteStream.h:88
llvm::AppendingBinaryByteStream::AppendingBinaryByteStream
AppendingBinaryByteStream(llvm::support::endianness Endian)
Definition: BinaryByteStream.h:140
llvm::AppendingBinaryByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint64_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:160
BinaryStream.h
StringRef.h
llvm::AppendingBinaryByteStream::clear
void clear()
Definition: BinaryByteStream.h:143
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::MutableBinaryByteStream::MutableBinaryByteStream
MutableBinaryByteStream()=default
Error.h
llvm::AppendingBinaryByteStream::getLength
uint64_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:169
llvm::BinaryByteStream::str
StringRef str() const
Definition: BinaryByteStream.h:60
llvm::FileBufferByteStream::FileBufferByteStream
FileBufferByteStream(std::unique_ptr< FileOutputBuffer > Buffer, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:234
llvm::BinaryStream::checkOffsetForRead
Error checkOffsetForRead(uint64_t Offset, uint64_t DataSize)
Definition: BinaryStream.h:59
FileOutputBuffer.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::AppendingBinaryByteStream::getFlags
virtual BinaryStreamFlags getFlags() const override
Return the properties of this stream.
Definition: BinaryByteStream.h:195
llvm::ArrayRef::empty
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:159
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:161
llvm::stream_error_code::invalid_offset
@ invalid_offset
llvm::AppendingBinaryByteStream::AppendingBinaryByteStream
AppendingBinaryByteStream()=default
llvm::MutableArrayRef< uint8_t >
llvm::support::little
@ little
Definition: Endian.h:27
llvm::BinaryByteStream::BinaryByteStream
BinaryByteStream()=default
llvm::BinaryByteStream::readBytes
Error readBytes(uint64_t Offset, uint64_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:40
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:30
llvm::AppendingBinaryByteStream
An implementation of WritableBinaryStream which can write at its end causing the underlying data to g...
Definition: BinaryByteStream.h:134
BinaryStreamError.h
llvm::MutableBinaryByteStream::getLength
uint64_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:109
llvm::MutableBinaryByteStream::readLongestContiguousChunk
Error readLongestContiguousChunk(uint64_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:104
llvm::AppendingBinaryByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:145
llvm::BinaryByteStream::data
ArrayRef< uint8_t > data() const
Definition: BinaryByteStream.h:58
llvm::AppendingBinaryByteStream::data
MutableArrayRef< uint8_t > data()
Definition: BinaryByteStream.h:199
llvm::AppendingBinaryByteStream::writeBytes
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Definition: BinaryByteStream.h:171
llvm::MutableBinaryByteStream::MutableBinaryByteStream
MutableBinaryByteStream(MutableArrayRef< uint8_t > Data, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:91
llvm::MemoryBufferByteStream::MemBuffer
std::unique_ptr< MemoryBuffer > MemBuffer
Definition: BinaryByteStream.h:81
llvm::AppendingBinaryByteStream::readBytes
Error readBytes(uint64_t Offset, uint64_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:147
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:194
llvm::AppendingBinaryByteStream::commit
Error commit() override
For buffered streams, commits changes to the backing store.
Definition: BinaryByteStream.h:192
uint64_t
llvm::BSF_Append
@ BSF_Append
Definition: BinaryStream.h:24
llvm::FileBufferByteStream::getLength
uint64_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:252
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
llvm::AppendingBinaryByteStream::insert
void insert(uint64_t Offset, ArrayRef< uint8_t > Bytes)
Definition: BinaryByteStream.h:156
ArrayRef.h
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:1675
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:123
llvm::BinaryByteStream::Endian
llvm::support::endianness Endian
Definition: BinaryByteStream.h:66
llvm::FileBufferByteStream::readBytes
Error readBytes(uint64_t Offset, uint64_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:242
llvm::BinaryByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:38
llvm::MemoryBufferByteStream
An implementation of BinaryStream whose data is backed by an llvm MemoryBuffer object.
Definition: BinaryByteStream.h:74
llvm::ArrayRef< uint8_t >
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MutableArrayRef::data
T * data() const
Definition: ArrayRef.h:353
llvm::FileBufferByteStream::commit
Error commit() override
For buffered streams, commits changes to the backing store.
Definition: BinaryByteStream.h:258
llvm::BSF_Write
@ BSF_Write
Definition: BinaryStream.h:23
llvm::FileBufferByteStream
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
Definition: BinaryByteStream.h:204
std
Definition: BitVector.h:851
llvm::MutableBinaryByteStream::readBytes
Error readBytes(uint64_t Offset, uint64_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:99
llvm::ArrayRef::begin
iterator begin() const
Definition: ArrayRef.h:152
llvm::FileBufferByteStream::writeBytes
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Data) override
Attempt to write the given bytes into the stream at the desired offset.
Definition: BinaryByteStream.h:254
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::BinaryByteStream::Data
ArrayRef< uint8_t > Data
Definition: BinaryByteStream.h:67
llvm::FileBufferByteStream::getBufferEnd
uint8_t * getBufferEnd() const
Returns a pointer to the end of the buffer.
Definition: BinaryByteStream.h:264
llvm::FileBufferByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:238
llvm::makeArrayRef
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:475
llvm::BinaryByteStream::BinaryByteStream
BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:35
llvm::WritableBinaryStream::checkOffsetForWrite
Error checkOffsetForWrite(uint64_t Offset, uint64_t DataSize)
Definition: BinaryStream.h:89
llvm::BinaryByteStream::BinaryByteStream
BinaryByteStream(ArrayRef< uint8_t > Data, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:33
llvm::FileBufferByteStream::getBufferStart
uint8_t * getBufferStart() const
Returns a pointer to the start of the buffer.
Definition: BinaryByteStream.h:261
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::stream_error_code::filesystem_error
@ filesystem_error
llvm::support::endianness
endianness
Definition: Endian.h:27
llvm::MutableBinaryByteStream::writeBytes
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Definition: BinaryByteStream.h:111
llvm::MemoryBufferByteStream::MemoryBufferByteStream
MemoryBufferByteStream(std::unique_ptr< MemoryBuffer > Buffer, llvm::support::endianness Endian)
Definition: BinaryByteStream.h:76
llvm::BinaryByteStream::getLength
uint64_t getLength() override
Return the number of bytes of data in this stream.
Definition: BinaryByteStream.h:56
llvm::WritableBinaryStream
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:73
llvm::MutableBinaryByteStream::data
MutableArrayRef< uint8_t > data() const
Definition: BinaryByteStream.h:125
llvm::ArrayRef::end
iterator end() const
Definition: ArrayRef.h:153
llvm::MutableBinaryByteStream::getEndian
llvm::support::endianness getEndian() const override
Definition: BinaryByteStream.h:95