llvm.org GIT mirror llvm / 2e0acd1
[BinaryStream] Reduce the amount of boiler plate needed to use. Often you have an array and you just want to use it. With the current design, you have to first construct a `BinaryByteStream`, and then create a `BinaryStreamRef` from it. Worse, the `BinaryStreamRef` holds a pointer to the `BinaryByteStream`, so you can't just create a temporary one to appease the compiler, you have to actually hold onto both the `ArrayRef` as well as the `BinaryByteStream` *AND* the `BinaryStreamReader` on top of that. This makes for very cumbersome code, often requiring one to store a `BinaryByteStream` in a class just to circumvent this. At the cost of some added complexity (not exposed to users, but internal to the library), we can do better than this. This patch allows us to construct `BinaryStreamReaders` and `BinaryStreamWriters` directly from source data (e.g. `StringRef`, `MutableArrayRef<uint8_t>`, etc). Not only does this reduce the amount of code you have to type and make it more obvious how to use it, but it solves real lifetime issues when it's inconvenient to hold onto a `BinaryByteStream` for a long time. The additional complexity is in the form of an added layer of indirection. Whereas before we simply stored a `BinaryStream*` in the ref, we now store both a `BinaryStream*` **and** a `std::shared_ptr<BinaryStream>`. When the user wants to construct a `BinaryStreamRef` directly from an `ArrayRef` etc, we allocate an internal object that holds ownership over a `BinaryByteStream` and forwards all calls, and store this in the `shared_ptr<>`. This also maintains the ref semantics, as you can copy it by value and references refer to the same underlying stream -- the one being held in the object stored in the `shared_ptr`. Differential Revision: https://reviews.llvm.org/D33293 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303294 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
8 changed file(s) with 268 addition(s) and 88 deletion(s). Raw diff Collapse all Expand all
3131 class BinaryStreamReader {
3232 public:
3333 BinaryStreamReader() = default;
34 explicit BinaryStreamReader(BinaryStreamRef Stream);
34 explicit BinaryStreamReader(BinaryStreamRef Ref);
35 explicit BinaryStreamReader(BinaryStream &Stream);
36 explicit BinaryStreamReader(ArrayRef Data,
37 llvm::support::endianness Endian);
38 explicit BinaryStreamReader(StringRef Data, llvm::support::endianness Endian);
39
40 BinaryStreamReader(const BinaryStreamReader &Other)
41 : Stream(Other.Stream), Offset(Other.Offset) {}
42
43 BinaryStreamReader &operator=(const BinaryStreamReader &Other) {
44 Stream = Other.Stream;
45 Offset = Other.Offset;
46 return *this;
47 }
48
3549 virtual ~BinaryStreamReader() {}
3650
3751 /// Read as much as possible from the underlying string at the current offset
248262
249263 private:
250264 BinaryStreamRef Stream;
251 uint32_t Offset;
265 uint32_t Offset = 0;
252266 };
253267 } // namespace llvm
254268
1515 #include "llvm/Support/Error.h"
1616 #include
1717 #include
18 #include
1819
1920 namespace llvm {
2021
2122 /// Common stuff for mutable and immutable StreamRefs.
22 template StreamType, class RefType> class BinaryStreamRefBase {
23 template RefType, class StreamType> class BinaryStreamRefBase {
24 protected:
25 BinaryStreamRefBase() = default;
26 BinaryStreamRefBase(std::shared_ptr SharedImpl, uint32_t Offset,
27 uint32_t Length)
28 : SharedImpl(SharedImpl), BorrowedImpl(SharedImpl.get()),
29 ViewOffset(Offset), Length(Length) {}
30 BinaryStreamRefBase(StreamType &BorrowedImpl, uint32_t Offset,
31 uint32_t Length)
32 : BorrowedImpl(&BorrowedImpl), ViewOffset(Offset), Length(Length) {}
33 BinaryStreamRefBase(const BinaryStreamRefBase &Other) {
34 SharedImpl = Other.SharedImpl;
35 BorrowedImpl = Other.BorrowedImpl;
36 ViewOffset = Other.ViewOffset;
37 Length = Other.Length;
38 }
39
2340 public:
24 BinaryStreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {}
25 BinaryStreamRefBase(StreamType &Stream, uint32_t Offset, uint32_t Length)
26 : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
27
28 llvm::support::endianness getEndian() const { return Stream->getEndian(); }
41 llvm::support::endianness getEndian() const {
42 return BorrowedImpl->getEndian();
43 }
2944
3045 uint32_t getLength() const { return Length; }
31 const StreamType *getStream() const { return Stream; }
3246
3347 /// Return a new BinaryStreamRef with the first \p N elements removed.
3448 RefType drop_front(uint32_t N) const {
35 if (!Stream)
49 if (!BorrowedImpl)
3650 return RefType();
3751
3852 N = std::min(N, Length);
39 return RefType(*Stream, ViewOffset + N, Length - N);
53 RefType Result(static_cast(*this));
54 Result.ViewOffset += N;
55 Result.Length -= N;
56 return Result;
4057 }
4158
4259 /// Return a new BinaryStreamRef with only the first \p N elements remaining.
4360 RefType keep_front(uint32_t N) const {
44 if (!Stream)
61 if (!BorrowedImpl)
4562 return RefType();
4663 N = std::min(N, Length);
47 return RefType(*Stream, ViewOffset, N);
64 RefType Result(static_cast(*this));
65 Result.Length = N;
66 return Result;
4867 }
4968
5069 /// Return a new BinaryStreamRef with the first \p Offset elements removed,
5372 return drop_front(Offset).keep_front(Len);
5473 }
5574
75 bool valid() const { return BorrowedImpl != nullptr; }
76
5677 bool operator==(const RefType &Other) const {
57 if (Stream != Other.Stream)
78 if (BorrowedImpl != Other.BorrowedImpl)
5879 return false;
5980 if (ViewOffset != Other.ViewOffset)
6081 return false;
7293 return Error::success();
7394 }
7495
75 StreamType *Stream;
76 uint32_t ViewOffset;
77 uint32_t Length;
96 std::shared_ptr SharedImpl;
97 StreamType *BorrowedImpl = nullptr;
98 uint32_t ViewOffset = 0;
99 uint32_t Length = 0;
78100 };
79101
80102 /// \brief BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
85107 /// and use inheritance to achieve polymorphism. Instead, you should pass
86108 /// around BinaryStreamRefs by value and achieve polymorphism that way.
87109 class BinaryStreamRef
88 : public BinaryStreamRefBase, BinaryStreamRef> {
110 : public BinaryStreamRefBaseRef, BinaryStream> {
111 friend BinaryStreamRefBase;
112 friend class WritableBinaryStreamRef;
113 BinaryStreamRef(std::shared_ptr Impl, uint32_t ViewOffset,
114 uint32_t Length)
115 : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
116
89117 public:
90118 BinaryStreamRef() = default;
91 BinaryStreamRef(BinaryStream &Stream)
92 : BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
93 BinaryStreamRef(BinaryStream &Stream, uint32_t Offset, uint32_t Length)
94 : BinaryStreamRefBase(Stream, Offset, Length) {}
119 BinaryStreamRef(BinaryStream &Stream);
120 BinaryStreamRef(BinaryStream &Stream, uint32_t Offset, uint32_t Length);
121 explicit BinaryStreamRef(ArrayRef Data,
122 llvm::support::endianness Endian);
123 explicit BinaryStreamRef(StringRef Data, llvm::support::endianness Endian);
124
125 BinaryStreamRef(const BinaryStreamRef &Other);
95126
96127 // Use BinaryStreamRef.slice() instead.
97128 BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset,
98129 uint32_t Length) = delete;
99
100 /// Check if a Stream is valid.
101 bool valid() const { return Stream != nullptr; }
102130
103131 /// Given an Offset into this StreamRef and a Size, return a reference to a
104132 /// buffer owned by the stream.
107135 /// bounds of this BinaryStreamRef's view and the implementation could read
108136 /// the data, and an appropriate error code otherwise.
109137 Error readBytes(uint32_t Offset, uint32_t Size,
110 ArrayRef &Buffer) const {
111 if (auto EC = checkOffset(Offset, Size))
112 return EC;
113
114 return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
115 }
138 ArrayRef &Buffer) const;
116139
117140 /// Given an Offset into this BinaryStreamRef, return a reference to the
118141 /// largest buffer the stream could support without necessitating a copy.
120143 /// \returns a success error code if implementation could read the data,
121144 /// and an appropriate error code otherwise.
122145 Error readLongestContiguousChunk(uint32_t Offset,
123 ArrayRef &Buffer) const {
124 if (auto EC = checkOffset(Offset, 1))
125 return EC;
126
127 if (auto EC =
128 Stream->readLongestContiguousChunk(ViewOffset + Offset, Buffer))
129 return EC;
130 // This StreamRef might refer to a smaller window over a larger stream. In
131 // that case we will have read out more bytes than we should return, because
132 // we should not read past the end of the current view.
133 uint32_t MaxLength = Length - Offset;
134 if (Buffer.size() > MaxLength)
135 Buffer = Buffer.slice(0, MaxLength);
136 return Error::success();
137 }
146 ArrayRef &Buffer) const;
138147 };
139148
140149 class WritableBinaryStreamRef
141 : public BinaryStreamRefBase
142 WritableBinaryStreamRef> {
150 : public BinaryStreamRefBase
151 WritableBinaryStream> {
152 friend BinaryStreamRefBase;
153 WritableBinaryStreamRef(std::shared_ptr Impl,
154 uint32_t ViewOffset, uint32_t Length)
155 : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
156
143157 public:
144158 WritableBinaryStreamRef() = default;
145 WritableBinaryStreamRef(WritableBinaryStream &Stream)
146 : BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
159 WritableBinaryStreamRef(WritableBinaryStream &Stream);
147160 WritableBinaryStreamRef(WritableBinaryStream &Stream, uint32_t Offset,
148 uint32_t Length)
149 : BinaryStreamRefBase(Stream, Offset, Length) {}
161 uint32_t Length);
162 explicit WritableBinaryStreamRef(MutableArrayRef Data,
163 llvm::support::endianness Endian);
164 WritableBinaryStreamRef(const WritableBinaryStreamRef &Other);
150165
151166 // Use WritableBinaryStreamRef.slice() instead.
152167 WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint32_t Offset,
158173 /// \returns a success error code if the data could fit within the underlying
159174 /// stream at the specified location and the implementation could write the
160175 /// data, and an appropriate error code otherwise.
161 Error writeBytes(uint32_t Offset, ArrayRef Data) const {
162 if (auto EC = checkOffset(Offset, Data.size()))
163 return EC;
176 Error writeBytes(uint32_t Offset, ArrayRef Data) const;
164177
165 return Stream->writeBytes(ViewOffset + Offset, Data);
166 }
167
168 operator BinaryStreamRef() { return BinaryStreamRef(*Stream); }
178 /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
179 operator BinaryStreamRef() const;
169180
170181 /// \brief For buffered streams, commits changes to the backing store.
171 Error commit() { return Stream->commit(); }
182 Error commit();
172183 };
173184
174185 } // end namespace llvm
3131 class BinaryStreamWriter {
3232 public:
3333 BinaryStreamWriter() = default;
34 explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
34 explicit BinaryStreamWriter(WritableBinaryStreamRef Ref);
35 explicit BinaryStreamWriter(WritableBinaryStream &Stream);
36 explicit BinaryStreamWriter(MutableArrayRef Data,
37 llvm::support::endianness Endian);
38
39 BinaryStreamWriter(const BinaryStreamWriter &Other)
40 : Stream(Other.Stream), Offset(Other.Offset) {}
41
42 BinaryStreamWriter &operator=(const BinaryStreamWriter &Other) {
43 Stream = Other.Stream;
44 Offset = Other.Offset;
45 return *this;
46 }
47
3548 virtual ~BinaryStreamWriter() {}
3649
3750 /// Write the bytes specified in \p Buffer to the underlying stream.
1212 #include "llvm/Support/BinaryStreamRef.h"
1313
1414 using namespace llvm;
15 using endianness = llvm::support::endianness;
1516
16 BinaryStreamReader::BinaryStreamReader(BinaryStreamRef S)
17 : Stream(S), Offset(0) {}
17 BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
18
19 BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
20
21 BinaryStreamReader::BinaryStreamReader(ArrayRef Data,
22 endianness Endian)
23 : Stream(Data, Endian) {}
24
25 BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
26 : Stream(Data, Endian) {}
1827
1928 Error BinaryStreamReader::readLongestContiguousChunk(
2029 ArrayRef &Buffer) {
0 //===- BinaryStreamRef.cpp - ----------------------------------------------===//
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 #include "llvm/Support/BinaryStreamRef.h"
10 #include "llvm/Support/BinaryByteStream.h"
11
12 using namespace llvm;
13 using namespace llvm::support;
14
15 namespace {
16
17 class ArrayRefImpl : public BinaryStream {
18 public:
19 ArrayRefImpl(ArrayRef Data, endianness Endian) : BBS(Data, Endian) {}
20
21 llvm::support::endianness getEndian() const override {
22 return BBS.getEndian();
23 }
24 Error readBytes(uint32_t Offset, uint32_t Size,
25 ArrayRef &Buffer) override {
26 return BBS.readBytes(Offset, Size, Buffer);
27 }
28 Error readLongestContiguousChunk(uint32_t Offset,
29 ArrayRef &Buffer) override {
30 return BBS.readLongestContiguousChunk(Offset, Buffer);
31 }
32 uint32_t getLength() override { return BBS.getLength(); }
33
34 private:
35 BinaryByteStream BBS;
36 };
37
38 class MutableArrayRefImpl : public WritableBinaryStream {
39 public:
40 MutableArrayRefImpl(MutableArrayRef Data, endianness Endian)
41 : BBS(Data, Endian) {}
42
43 // Inherited via WritableBinaryStream
44 llvm::support::endianness getEndian() const override {
45 return BBS.getEndian();
46 }
47 Error readBytes(uint32_t Offset, uint32_t Size,
48 ArrayRef &Buffer) override {
49 return BBS.readBytes(Offset, Size, Buffer);
50 }
51 Error readLongestContiguousChunk(uint32_t Offset,
52 ArrayRef &Buffer) override {
53 return BBS.readLongestContiguousChunk(Offset, Buffer);
54 }
55 uint32_t getLength() override { return BBS.getLength(); }
56
57 Error writeBytes(uint32_t Offset, ArrayRef Data) override {
58 return BBS.writeBytes(Offset, Data);
59 }
60 Error commit() override { return BBS.commit(); }
61
62 private:
63 MutableBinaryByteStream BBS;
64 };
65 }
66
67 BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream)
68 : BinaryStreamRef(Stream, 0, Stream.getLength()) {}
69 BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint32_t Offset,
70 uint32_t Length)
71 : BinaryStreamRefBase(Stream, Offset, Length) {}
72 BinaryStreamRef::BinaryStreamRef(ArrayRef Data, endianness Endian)
73 : BinaryStreamRefBase(std::make_shared(Data, Endian), 0,
74 Data.size()) {}
75 BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian)
76 : BinaryStreamRef(makeArrayRef(Data.bytes_begin(), Data.bytes_end()),
77 Endian) {}
78
79 BinaryStreamRef::BinaryStreamRef(const BinaryStreamRef &Other)
80 : BinaryStreamRefBase(Other) {}
81
82 Error BinaryStreamRef::readBytes(uint32_t Offset, uint32_t Size,
83 ArrayRef &Buffer) const {
84 if (auto EC = checkOffset(Offset, Size))
85 return EC;
86 return BorrowedImpl->readBytes(ViewOffset + Offset, Size, Buffer);
87 }
88
89 Error BinaryStreamRef::readLongestContiguousChunk(
90 uint32_t Offset, ArrayRef &Buffer) const {
91 if (auto EC = checkOffset(Offset, 1))
92 return EC;
93
94 if (auto EC =
95 BorrowedImpl->readLongestContiguousChunk(ViewOffset + Offset, Buffer))
96 return EC;
97 // This StreamRef might refer to a smaller window over a larger stream. In
98 // that case we will have read out more bytes than we should return, because
99 // we should not read past the end of the current view.
100 uint32_t MaxLength = Length - Offset;
101 if (Buffer.size() > MaxLength)
102 Buffer = Buffer.slice(0, MaxLength);
103 return Error::success();
104 }
105
106 WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream)
107 : WritableBinaryStreamRef(Stream, 0, Stream.getLength()) {}
108
109 WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream,
110 uint32_t Offset,
111 uint32_t Length)
112 : BinaryStreamRefBase(Stream, Offset, Length) {}
113
114 WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef Data,
115 endianness Endian)
116 : BinaryStreamRefBase(std::make_shared(Data, Endian),
117 0, Data.size()) {}
118
119 WritableBinaryStreamRef::WritableBinaryStreamRef(
120 const WritableBinaryStreamRef &Other)
121 : BinaryStreamRefBase(Other) {}
122
123 Error WritableBinaryStreamRef::writeBytes(uint32_t Offset,
124 ArrayRef Data) const {
125 if (auto EC = checkOffset(Offset, Data.size()))
126 return EC;
127
128 return BorrowedImpl->writeBytes(ViewOffset + Offset, Data);
129 }
130
131 WritableBinaryStreamRef::operator BinaryStreamRef() const {
132 return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length);
133 }
134
135 /// \brief For buffered streams, commits changes to the backing store.
136 Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); }
1414
1515 using namespace llvm;
1616
17 BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef S)
18 : Stream(S), Offset(0) {}
17 BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef Ref)
18 : Stream(Ref) {}
19
20 BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStream &Stream)
21 : Stream(Stream) {}
22
23 BinaryStreamWriter::BinaryStreamWriter(MutableArrayRef Data,
24 llvm::support::endianness Endian)
25 : Stream(Data, Endian) {}
1926
2027 Error BinaryStreamWriter::writeBytes(ArrayRef Buffer) {
2128 if (auto EC = Stream.writeBytes(Offset, Buffer))
3838 Allocator.cpp
3939 BinaryStreamError.cpp
4040 BinaryStreamReader.cpp
41 BinaryStreamRef.cpp
4142 BinaryStreamWriter.cpp
4243 BlockFrequency.cpp
4344 BranchProbability.cpp
4040 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
4141 #include "llvm/Object/COFF.h"
4242 #include "llvm/Object/ObjectFile.h"
43 #include "llvm/Support/BinaryByteStream.h"
4443 #include "llvm/Support/BinaryStreamReader.h"
4544 #include "llvm/Support/COFF.h"
4645 #include "llvm/Support/ConvertUTF.h"
154153 bool RelocCached = false;
155154 RelocMapTy RelocMap;
156155
157 BinaryByteStream ChecksumContents;
158156 VarStreamArray CVFileChecksumTable;
159157
160 BinaryByteStream StringTableContents;
161158 StringTableRef CVStringTable;
162159
163160 ScopedPrinter &Writer;
774771
775772 switch (ModuleDebugFragmentKind(SubType)) {
776773 case ModuleDebugFragmentKind::FileChecksums: {
777 ChecksumContents = BinaryByteStream(Contents, support::little);
778 BinaryStreamReader CSR(ChecksumContents);
774 BinaryStreamReader CSR(Contents, support::little);
779775 error(CSR.readArray(CVFileChecksumTable, CSR.getLength()));
780776 break;
781777 }
782778 case ModuleDebugFragmentKind::StringTable: {
783 StringTableContents = BinaryByteStream(Contents, support::little);
784 error(CVStringTable.initialize(StringTableContents));
779 BinaryStreamRef ST(Contents, support::little);
780 error(CVStringTable.initialize(ST));
785781 } break;
786782 default:
787783 break;
811807 if (Magic != COFF::DEBUG_SECTION_MAGIC)
812808 return error(object_error::parse_failed);
813809
814 BinaryByteStream FileAndStrings(Data, support::little);
815 BinaryStreamReader FSReader(FileAndStrings);
810 BinaryStreamReader FSReader(Data, support::little);
816811 initializeFileAndStringTables(FSReader);
817812
818813 // TODO: Convert this over to using ModuleSubstreamVisitor.
888883 }
889884 case ModuleDebugFragmentKind::FrameData: {
890885 // First four bytes is a relocation against the function.
891 BinaryByteStream S(Contents, llvm::support::little);
892 BinaryStreamReader SR(S);
886 BinaryStreamReader SR(Contents, llvm::support::little);
893887 const uint32_t *CodePtr;
894888 error(SR.readObject(CodePtr));
895889 StringRef LinkageName;
933927 ListScope S(W, "FunctionLineTable");
934928 W.printString("LinkageName", Name);
935929
936 BinaryByteStream LineTableInfo(FunctionLineTables[Name], support::little);
937 BinaryStreamReader Reader(LineTableInfo);
930 BinaryStreamReader Reader(FunctionLineTables[Name], support::little);
938931
939932 ModuleDebugLineFragmentRef LineInfo;
940933 error(LineInfo.initialize(Reader));
984977
985978 CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
986979 opts::CodeViewSubsectionBytes);
987 BinaryByteStream Stream(BinaryData, llvm::support::little);
988980 CVSymbolArray Symbols;
989 BinaryStreamReader Reader(Stream);
981 BinaryStreamReader Reader(BinaryData, llvm::support::little);
990982 if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
991983 consumeError(std::move(EC));
992984 W.flush();
1001993 }
1002994
1003995 void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
1004 BinaryByteStream S(Subsection, llvm::support::little);
1005 BinaryStreamReader SR(S);
996 BinaryStreamReader SR(Subsection, llvm::support::little);
1006997 ModuleDebugFileChecksumFragmentRef Checksums;
1007998 error(Checksums.initialize(SR));
1008999
10201011 }
10211012
10221013 void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
1023 BinaryByteStream S(Subsection, llvm::support::little);
1024 BinaryStreamReader SR(S);
1014 BinaryStreamReader SR(Subsection, llvm::support::little);
10251015 ModuleDebugInlineeLineFragmentRef Lines;
10261016 error(Lines.initialize(SR));
10271017
10711061 error(consume(Data, Magic));
10721062 if (Magic != 4)
10731063 error(object_error::parse_failed);
1074 ArrayRef Bytes(reinterpret_cast(Data.data()),
1075 Data.size());
1076 BinaryByteStream Stream(Bytes, llvm::support::little);
1064
10771065 CVTypeArray Types;
1078 BinaryStreamReader Reader(Stream);
1066 BinaryStreamReader Reader(Data, llvm::support::little);
10791067 if (auto EC = Reader.readArray(Types, Reader.getLength())) {
10801068 consumeError(std::move(EC));
10811069 W.flush();