xref: /aosp_15_r20/external/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
11*9880d681SAndroid Build Coastguard Worker 
12*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/CodeView.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamReader.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/TypeIndex.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/Hash.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawError.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Endian.h"
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker using namespace llvm::codeview;
29*9880d681SAndroid Build Coastguard Worker using namespace llvm::support;
30*9880d681SAndroid Build Coastguard Worker using namespace llvm::pdb;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker namespace {
33*9880d681SAndroid Build Coastguard Worker const uint32_t MinHashBuckets = 0x1000;
34*9880d681SAndroid Build Coastguard Worker const uint32_t MaxHashBuckets = 0x40000;
35*9880d681SAndroid Build Coastguard Worker }
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker // This corresponds to `HDR` in PDB/dbi/tpi.h.
38*9880d681SAndroid Build Coastguard Worker struct TpiStream::HeaderInfo {
39*9880d681SAndroid Build Coastguard Worker   struct EmbeddedBuf {
40*9880d681SAndroid Build Coastguard Worker     little32_t Off;
41*9880d681SAndroid Build Coastguard Worker     ulittle32_t Length;
42*9880d681SAndroid Build Coastguard Worker   };
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker   ulittle32_t Version;
45*9880d681SAndroid Build Coastguard Worker   ulittle32_t HeaderSize;
46*9880d681SAndroid Build Coastguard Worker   ulittle32_t TypeIndexBegin;
47*9880d681SAndroid Build Coastguard Worker   ulittle32_t TypeIndexEnd;
48*9880d681SAndroid Build Coastguard Worker   ulittle32_t TypeRecordBytes;
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker   // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
51*9880d681SAndroid Build Coastguard Worker   ulittle16_t HashStreamIndex;
52*9880d681SAndroid Build Coastguard Worker   ulittle16_t HashAuxStreamIndex;
53*9880d681SAndroid Build Coastguard Worker   ulittle32_t HashKeySize;
54*9880d681SAndroid Build Coastguard Worker   ulittle32_t NumHashBuckets;
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   EmbeddedBuf HashValueBuffer;
57*9880d681SAndroid Build Coastguard Worker   EmbeddedBuf IndexOffsetBuffer;
58*9880d681SAndroid Build Coastguard Worker   EmbeddedBuf HashAdjBuffer;
59*9880d681SAndroid Build Coastguard Worker };
60*9880d681SAndroid Build Coastguard Worker 
TpiStream(const PDBFile & File,std::unique_ptr<MappedBlockStream> Stream)61*9880d681SAndroid Build Coastguard Worker TpiStream::TpiStream(const PDBFile &File,
62*9880d681SAndroid Build Coastguard Worker                      std::unique_ptr<MappedBlockStream> Stream)
63*9880d681SAndroid Build Coastguard Worker     : Pdb(File), Stream(std::move(Stream)) {}
64*9880d681SAndroid Build Coastguard Worker 
~TpiStream()65*9880d681SAndroid Build Coastguard Worker TpiStream::~TpiStream() {}
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker // Corresponds to `fUDTAnon`.
isAnonymous(T & Rec)68*9880d681SAndroid Build Coastguard Worker template <typename T> static bool isAnonymous(T &Rec) {
69*9880d681SAndroid Build Coastguard Worker   StringRef Name = Rec.getName();
70*9880d681SAndroid Build Coastguard Worker   return Name == "<unnamed-tag>" || Name == "__unnamed" ||
71*9880d681SAndroid Build Coastguard Worker       Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
72*9880d681SAndroid Build Coastguard Worker }
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker // Computes a hash for a given TPI record.
75*9880d681SAndroid Build Coastguard Worker template <typename T>
getTpiHash(T & Rec,const CVRecord<TypeLeafKind> & RawRec)76*9880d681SAndroid Build Coastguard Worker static uint32_t getTpiHash(T &Rec, const CVRecord<TypeLeafKind> &RawRec) {
77*9880d681SAndroid Build Coastguard Worker   auto Opts = static_cast<uint16_t>(Rec.getOptions());
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   bool ForwardRef =
80*9880d681SAndroid Build Coastguard Worker       Opts & static_cast<uint16_t>(ClassOptions::ForwardReference);
81*9880d681SAndroid Build Coastguard Worker   bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped);
82*9880d681SAndroid Build Coastguard Worker   bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName);
83*9880d681SAndroid Build Coastguard Worker   bool IsAnon = UniqueName && isAnonymous(Rec);
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker   if (!ForwardRef && !Scoped && !IsAnon)
86*9880d681SAndroid Build Coastguard Worker     return hashStringV1(Rec.getName());
87*9880d681SAndroid Build Coastguard Worker   if (!ForwardRef && UniqueName && !IsAnon)
88*9880d681SAndroid Build Coastguard Worker     return hashStringV1(Rec.getUniqueName());
89*9880d681SAndroid Build Coastguard Worker   return hashBufferV8(RawRec.RawData);
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker namespace {
93*9880d681SAndroid Build Coastguard Worker class TpiHashVerifier : public TypeVisitorCallbacks {
94*9880d681SAndroid Build Coastguard Worker public:
TpiHashVerifier(FixedStreamArray<support::ulittle32_t> & HashValues,uint32_t NumHashBuckets)95*9880d681SAndroid Build Coastguard Worker   TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
96*9880d681SAndroid Build Coastguard Worker                   uint32_t NumHashBuckets)
97*9880d681SAndroid Build Coastguard Worker       : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
98*9880d681SAndroid Build Coastguard Worker 
visitUdtSourceLine(UdtSourceLineRecord & Rec)99*9880d681SAndroid Build Coastguard Worker   Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
100*9880d681SAndroid Build Coastguard Worker     return verifySourceLine(Rec);
101*9880d681SAndroid Build Coastguard Worker   }
102*9880d681SAndroid Build Coastguard Worker 
visitUdtModSourceLine(UdtModSourceLineRecord & Rec)103*9880d681SAndroid Build Coastguard Worker   Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
104*9880d681SAndroid Build Coastguard Worker     return verifySourceLine(Rec);
105*9880d681SAndroid Build Coastguard Worker   }
106*9880d681SAndroid Build Coastguard Worker 
visitClass(ClassRecord & Rec)107*9880d681SAndroid Build Coastguard Worker   Error visitClass(ClassRecord &Rec) override { return verify(Rec); }
visitEnum(EnumRecord & Rec)108*9880d681SAndroid Build Coastguard Worker   Error visitEnum(EnumRecord &Rec) override { return verify(Rec); }
visitUnion(UnionRecord & Rec)109*9880d681SAndroid Build Coastguard Worker   Error visitUnion(UnionRecord &Rec) override { return verify(Rec); }
110*9880d681SAndroid Build Coastguard Worker 
visitTypeBegin(const CVRecord<TypeLeafKind> & Rec)111*9880d681SAndroid Build Coastguard Worker   Error visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) override {
112*9880d681SAndroid Build Coastguard Worker     ++Index;
113*9880d681SAndroid Build Coastguard Worker     RawRecord = &Rec;
114*9880d681SAndroid Build Coastguard Worker     return Error::success();
115*9880d681SAndroid Build Coastguard Worker   }
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker private:
verify(T & Rec)118*9880d681SAndroid Build Coastguard Worker   template <typename T> Error verify(T &Rec) {
119*9880d681SAndroid Build Coastguard Worker     uint32_t Hash = getTpiHash(Rec, *RawRecord);
120*9880d681SAndroid Build Coastguard Worker     if (Hash % NumHashBuckets != HashValues[Index])
121*9880d681SAndroid Build Coastguard Worker       return errorInvalidHash();
122*9880d681SAndroid Build Coastguard Worker     return Error::success();
123*9880d681SAndroid Build Coastguard Worker   }
124*9880d681SAndroid Build Coastguard Worker 
verifySourceLine(T & Rec)125*9880d681SAndroid Build Coastguard Worker   template <typename T> Error verifySourceLine(T &Rec) {
126*9880d681SAndroid Build Coastguard Worker     char Buf[4];
127*9880d681SAndroid Build Coastguard Worker     support::endian::write32le(Buf, Rec.getUDT().getIndex());
128*9880d681SAndroid Build Coastguard Worker     uint32_t Hash = hashStringV1(StringRef(Buf, 4));
129*9880d681SAndroid Build Coastguard Worker     if (Hash % NumHashBuckets != HashValues[Index])
130*9880d681SAndroid Build Coastguard Worker       return errorInvalidHash();
131*9880d681SAndroid Build Coastguard Worker     return Error::success();
132*9880d681SAndroid Build Coastguard Worker   }
133*9880d681SAndroid Build Coastguard Worker 
errorInvalidHash()134*9880d681SAndroid Build Coastguard Worker   Error errorInvalidHash() {
135*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(
136*9880d681SAndroid Build Coastguard Worker         raw_error_code::invalid_tpi_hash,
137*9880d681SAndroid Build Coastguard Worker         "Type index is 0x" + utohexstr(TypeIndex::FirstNonSimpleIndex + Index));
138*9880d681SAndroid Build Coastguard Worker   }
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker   FixedStreamArray<support::ulittle32_t> HashValues;
141*9880d681SAndroid Build Coastguard Worker   const CVRecord<TypeLeafKind> *RawRecord;
142*9880d681SAndroid Build Coastguard Worker   uint32_t NumHashBuckets;
143*9880d681SAndroid Build Coastguard Worker   uint32_t Index = -1;
144*9880d681SAndroid Build Coastguard Worker };
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker // Verifies that a given type record matches with a given hash value.
148*9880d681SAndroid Build Coastguard Worker // Currently we only verify SRC_LINE records.
verifyHashValues()149*9880d681SAndroid Build Coastguard Worker Error TpiStream::verifyHashValues() {
150*9880d681SAndroid Build Coastguard Worker   TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
151*9880d681SAndroid Build Coastguard Worker   CVTypeVisitor Visitor(Verifier);
152*9880d681SAndroid Build Coastguard Worker   return Visitor.visitTypeStream(TypeRecords);
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker 
reload()155*9880d681SAndroid Build Coastguard Worker Error TpiStream::reload() {
156*9880d681SAndroid Build Coastguard Worker   StreamReader Reader(*Stream);
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker   if (Reader.bytesRemaining() < sizeof(HeaderInfo))
159*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
160*9880d681SAndroid Build Coastguard Worker                                 "TPI Stream does not contain a header.");
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker   if (Reader.readObject(Header))
163*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
164*9880d681SAndroid Build Coastguard Worker                                 "TPI Stream does not contain a header.");
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker   if (Header->Version != PdbTpiV80)
167*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
168*9880d681SAndroid Build Coastguard Worker                                 "Unsupported TPI Version.");
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   if (Header->HeaderSize != sizeof(HeaderInfo))
171*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
172*9880d681SAndroid Build Coastguard Worker                                 "Corrupt TPI Header size.");
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   if (Header->HashKeySize != sizeof(ulittle32_t))
175*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
176*9880d681SAndroid Build Coastguard Worker                                 "TPI Stream expected 4 byte hash key size.");
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker   if (Header->NumHashBuckets < MinHashBuckets ||
179*9880d681SAndroid Build Coastguard Worker       Header->NumHashBuckets > MaxHashBuckets)
180*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
181*9880d681SAndroid Build Coastguard Worker                                 "TPI Stream Invalid number of hash buckets.");
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker   // The actual type records themselves come from this stream
184*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes))
185*9880d681SAndroid Build Coastguard Worker     return EC;
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker   // Hash indices, hash values, etc come from the hash stream.
188*9880d681SAndroid Build Coastguard Worker   if (Header->HashStreamIndex >= Pdb.getNumStreams())
189*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
190*9880d681SAndroid Build Coastguard Worker                                 "Invalid TPI hash stream index.");
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker   auto HS =
193*9880d681SAndroid Build Coastguard Worker       MappedBlockStream::createIndexedStream(Header->HashStreamIndex, Pdb);
194*9880d681SAndroid Build Coastguard Worker   if (!HS)
195*9880d681SAndroid Build Coastguard Worker     return HS.takeError();
196*9880d681SAndroid Build Coastguard Worker   StreamReader HSR(**HS);
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t);
199*9880d681SAndroid Build Coastguard Worker   if (NumHashValues != NumTypeRecords())
200*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(
201*9880d681SAndroid Build Coastguard Worker         raw_error_code::corrupt_file,
202*9880d681SAndroid Build Coastguard Worker         "TPI hash count does not match with the number of type records.");
203*9880d681SAndroid Build Coastguard Worker   HSR.setOffset(Header->HashValueBuffer.Off);
204*9880d681SAndroid Build Coastguard Worker   if (auto EC = HSR.readArray(HashValues, NumHashValues))
205*9880d681SAndroid Build Coastguard Worker     return EC;
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker   HSR.setOffset(Header->IndexOffsetBuffer.Off);
208*9880d681SAndroid Build Coastguard Worker   uint32_t NumTypeIndexOffsets =
209*9880d681SAndroid Build Coastguard Worker       Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
210*9880d681SAndroid Build Coastguard Worker   if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
211*9880d681SAndroid Build Coastguard Worker     return EC;
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker   HSR.setOffset(Header->HashAdjBuffer.Off);
214*9880d681SAndroid Build Coastguard Worker   uint32_t NumHashAdjustments =
215*9880d681SAndroid Build Coastguard Worker       Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
216*9880d681SAndroid Build Coastguard Worker   if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
217*9880d681SAndroid Build Coastguard Worker     return EC;
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   HashStream = std::move(*HS);
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker   // TPI hash table is a parallel array for the type records.
222*9880d681SAndroid Build Coastguard Worker   // Verify that the hash values match with type records.
223*9880d681SAndroid Build Coastguard Worker   if (auto EC = verifyHashValues())
224*9880d681SAndroid Build Coastguard Worker     return EC;
225*9880d681SAndroid Build Coastguard Worker 
226*9880d681SAndroid Build Coastguard Worker   return Error::success();
227*9880d681SAndroid Build Coastguard Worker }
228*9880d681SAndroid Build Coastguard Worker 
getTpiVersion() const229*9880d681SAndroid Build Coastguard Worker PdbRaw_TpiVer TpiStream::getTpiVersion() const {
230*9880d681SAndroid Build Coastguard Worker   uint32_t Value = Header->Version;
231*9880d681SAndroid Build Coastguard Worker   return static_cast<PdbRaw_TpiVer>(Value);
232*9880d681SAndroid Build Coastguard Worker }
233*9880d681SAndroid Build Coastguard Worker 
TypeIndexBegin() const234*9880d681SAndroid Build Coastguard Worker uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
235*9880d681SAndroid Build Coastguard Worker 
TypeIndexEnd() const236*9880d681SAndroid Build Coastguard Worker uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
237*9880d681SAndroid Build Coastguard Worker 
NumTypeRecords() const238*9880d681SAndroid Build Coastguard Worker uint32_t TpiStream::NumTypeRecords() const {
239*9880d681SAndroid Build Coastguard Worker   return TypeIndexEnd() - TypeIndexBegin();
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker 
getTypeHashStreamIndex() const242*9880d681SAndroid Build Coastguard Worker uint16_t TpiStream::getTypeHashStreamIndex() const {
243*9880d681SAndroid Build Coastguard Worker   return Header->HashStreamIndex;
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker 
getTypeHashStreamAuxIndex() const246*9880d681SAndroid Build Coastguard Worker uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
247*9880d681SAndroid Build Coastguard Worker   return Header->HashAuxStreamIndex;
248*9880d681SAndroid Build Coastguard Worker }
249*9880d681SAndroid Build Coastguard Worker 
NumHashBuckets() const250*9880d681SAndroid Build Coastguard Worker uint32_t TpiStream::NumHashBuckets() const { return Header->NumHashBuckets; }
getHashKeySize() const251*9880d681SAndroid Build Coastguard Worker uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
252*9880d681SAndroid Build Coastguard Worker 
253*9880d681SAndroid Build Coastguard Worker FixedStreamArray<support::ulittle32_t>
getHashValues() const254*9880d681SAndroid Build Coastguard Worker TpiStream::getHashValues() const {
255*9880d681SAndroid Build Coastguard Worker   return HashValues;
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker FixedStreamArray<TypeIndexOffset>
getTypeIndexOffsets() const259*9880d681SAndroid Build Coastguard Worker TpiStream::getTypeIndexOffsets() const {
260*9880d681SAndroid Build Coastguard Worker   return TypeIndexOffsets;
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker FixedStreamArray<TypeIndexOffset>
getHashAdjustments() const264*9880d681SAndroid Build Coastguard Worker TpiStream::getHashAdjustments() const {
265*9880d681SAndroid Build Coastguard Worker   return HashAdjustments;
266*9880d681SAndroid Build Coastguard Worker }
267*9880d681SAndroid Build Coastguard Worker 
268*9880d681SAndroid Build Coastguard Worker iterator_range<CVTypeArray::Iterator>
types(bool * HadError) const269*9880d681SAndroid Build Coastguard Worker TpiStream::types(bool *HadError) const {
270*9880d681SAndroid Build Coastguard Worker   return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
271*9880d681SAndroid Build Coastguard Worker }
272*9880d681SAndroid Build Coastguard Worker 
commit()273*9880d681SAndroid Build Coastguard Worker Error TpiStream::commit() { return Error::success(); }
274