1f8d79198SJustin Bogner //=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=//
2f8d79198SJustin Bogner //
3f8d79198SJustin Bogner //                     The LLVM Compiler Infrastructure
4f8d79198SJustin Bogner //
5f8d79198SJustin Bogner // This file is distributed under the University of Illinois Open Source
6f8d79198SJustin Bogner // License. See LICENSE.TXT for details.
7f8d79198SJustin Bogner //
8f8d79198SJustin Bogner //===----------------------------------------------------------------------===//
9f8d79198SJustin Bogner //
10f8d79198SJustin Bogner // This file contains support for reading profiling data for clang's
11f8d79198SJustin Bogner // instrumentation based PGO and coverage.
12f8d79198SJustin Bogner //
13f8d79198SJustin Bogner //===----------------------------------------------------------------------===//
14f8d79198SJustin Bogner 
15f8d79198SJustin Bogner #include "llvm/ProfileData/InstrProfReader.h"
160a446fd5SBenjamin Kramer #include "llvm/ADT/STLExtras.h"
17f8d79198SJustin Bogner #include <cassert>
18f8d79198SJustin Bogner 
19f8d79198SJustin Bogner using namespace llvm;
20f8d79198SJustin Bogner 
21fcd55607SDiego Novillo static ErrorOr<std::unique_ptr<MemoryBuffer>>
22fcd55607SDiego Novillo setupMemoryBuffer(std::string Path) {
23adf21f2aSRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
24adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(Path);
25adf21f2aSRafael Espindola   if (std::error_code EC = BufferOrErr.getError())
26f8d79198SJustin Bogner     return EC;
272b6c537bSJustin Bogner   return std::move(BufferOrErr.get());
28b7aa2630SJustin Bogner }
29b7aa2630SJustin Bogner 
30db4ed0bdSRafael Espindola static std::error_code initializeReader(InstrProfReader &Reader) {
31b7aa2630SJustin Bogner   return Reader.readHeader();
32b7aa2630SJustin Bogner }
33b7aa2630SJustin Bogner 
34fcd55607SDiego Novillo ErrorOr<std::unique_ptr<InstrProfReader>>
35fcd55607SDiego Novillo InstrProfReader::create(std::string Path) {
36b7aa2630SJustin Bogner   // Set up the buffer to read.
37fcd55607SDiego Novillo   auto BufferOrError = setupMemoryBuffer(Path);
38fcd55607SDiego Novillo   if (std::error_code EC = BufferOrError.getError())
39b7aa2630SJustin Bogner     return EC;
402b6c537bSJustin Bogner   return InstrProfReader::create(std::move(BufferOrError.get()));
412b6c537bSJustin Bogner }
42f8d79198SJustin Bogner 
432b6c537bSJustin Bogner ErrorOr<std::unique_ptr<InstrProfReader>>
442b6c537bSJustin Bogner InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
452b6c537bSJustin Bogner   // Sanity check the buffer.
462b6c537bSJustin Bogner   if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max())
472b6c537bSJustin Bogner     return instrprof_error::too_large;
482b6c537bSJustin Bogner 
49fcd55607SDiego Novillo   std::unique_ptr<InstrProfReader> Result;
5009a67f45SDuncan P. N. Exon Smith   // Create the reader.
51b7aa2630SJustin Bogner   if (IndexedInstrProfReader::hasFormat(*Buffer))
52b7aa2630SJustin Bogner     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
53b7aa2630SJustin Bogner   else if (RawInstrProfReader64::hasFormat(*Buffer))
544680361dSDuncan P. N. Exon Smith     Result.reset(new RawInstrProfReader64(std::move(Buffer)));
554680361dSDuncan P. N. Exon Smith   else if (RawInstrProfReader32::hasFormat(*Buffer))
564680361dSDuncan P. N. Exon Smith     Result.reset(new RawInstrProfReader32(std::move(Buffer)));
574f823667SNathan Slingerland   else if (TextInstrProfReader::hasFormat(*Buffer))
58911ced6bSNathan Slingerland     Result.reset(new TextInstrProfReader(std::move(Buffer)));
594f823667SNathan Slingerland   else
604f823667SNathan Slingerland     return instrprof_error::unrecognized_format;
6109a67f45SDuncan P. N. Exon Smith 
62b7aa2630SJustin Bogner   // Initialize the reader and return the result.
63fcd55607SDiego Novillo   if (std::error_code EC = initializeReader(*Result))
64fcd55607SDiego Novillo     return EC;
65fcd55607SDiego Novillo 
66fcd55607SDiego Novillo   return std::move(Result);
67b7aa2630SJustin Bogner }
68b7aa2630SJustin Bogner 
69ab89ed7dSJustin Bogner ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
70ab89ed7dSJustin Bogner IndexedInstrProfReader::create(std::string Path) {
71b7aa2630SJustin Bogner   // Set up the buffer to read.
72fcd55607SDiego Novillo   auto BufferOrError = setupMemoryBuffer(Path);
73fcd55607SDiego Novillo   if (std::error_code EC = BufferOrError.getError())
74b7aa2630SJustin Bogner     return EC;
752b6c537bSJustin Bogner   return IndexedInstrProfReader::create(std::move(BufferOrError.get()));
762b6c537bSJustin Bogner }
77b7aa2630SJustin Bogner 
782b6c537bSJustin Bogner 
792b6c537bSJustin Bogner ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
802b6c537bSJustin Bogner IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
812b6c537bSJustin Bogner   // Sanity check the buffer.
822b6c537bSJustin Bogner   if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max())
832b6c537bSJustin Bogner     return instrprof_error::too_large;
84ab89ed7dSJustin Bogner 
85b7aa2630SJustin Bogner   // Create the reader.
86b7aa2630SJustin Bogner   if (!IndexedInstrProfReader::hasFormat(*Buffer))
87b7aa2630SJustin Bogner     return instrprof_error::bad_magic;
882b6c537bSJustin Bogner   auto Result = llvm::make_unique<IndexedInstrProfReader>(std::move(Buffer));
89b7aa2630SJustin Bogner 
90b7aa2630SJustin Bogner   // Initialize the reader and return the result.
91ab89ed7dSJustin Bogner   if (std::error_code EC = initializeReader(*Result))
92ab89ed7dSJustin Bogner     return EC;
93ab89ed7dSJustin Bogner 
94ab89ed7dSJustin Bogner   return std::move(Result);
95f8d79198SJustin Bogner }
96f8d79198SJustin Bogner 
97f8d79198SJustin Bogner void InstrProfIterator::Increment() {
98f8d79198SJustin Bogner   if (Reader->readNextRecord(Record))
99f8d79198SJustin Bogner     *this = InstrProfIterator();
100f8d79198SJustin Bogner }
101f8d79198SJustin Bogner 
1024f823667SNathan Slingerland bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
1034f823667SNathan Slingerland   // Verify that this really looks like plain ASCII text by checking a
1044f823667SNathan Slingerland   // 'reasonable' number of characters (up to profile magic size).
1054f823667SNathan Slingerland   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
1064f823667SNathan Slingerland   StringRef buffer = Buffer.getBufferStart();
1072491dd11SVedant Kumar   return count == 0 ||
1082491dd11SVedant Kumar          std::all_of(buffer.begin(), buffer.begin() + count,
1094f823667SNathan Slingerland                      [](char c) { return ::isprint(c) || ::isspace(c); });
1104f823667SNathan Slingerland }
1114f823667SNathan Slingerland 
11233c76c0cSRong Xu // Read the profile variant flag from the header: ":FE" means this is a FE
11333c76c0cSRong Xu // generated profile. ":IR" means this is an IR level profile. Other strings
11433c76c0cSRong Xu // with a leading ':' will be reported an error format.
115a716cc5cSXinliang David Li std::error_code TextInstrProfReader::readHeader() {
116a716cc5cSXinliang David Li   Symtab.reset(new InstrProfSymtab());
11733c76c0cSRong Xu   bool IsIRInstr = false;
11833c76c0cSRong Xu   if (!Line->startswith(":")) {
11933c76c0cSRong Xu     IsIRLevelProfile = false;
12033c76c0cSRong Xu     return success();
12133c76c0cSRong Xu   }
12233c76c0cSRong Xu   StringRef Str = (Line)->substr(1);
12333c76c0cSRong Xu   if (Str.equals_lower("ir"))
12433c76c0cSRong Xu     IsIRInstr = true;
12533c76c0cSRong Xu   else if (Str.equals_lower("fe"))
12633c76c0cSRong Xu     IsIRInstr = false;
12733c76c0cSRong Xu   else
12833c76c0cSRong Xu     return instrprof_error::bad_header;
12933c76c0cSRong Xu 
13033c76c0cSRong Xu   ++Line;
13133c76c0cSRong Xu   IsIRLevelProfile = IsIRInstr;
132a716cc5cSXinliang David Li   return success();
133a716cc5cSXinliang David Li }
134a716cc5cSXinliang David Li 
135e3bf4fd3SXinliang David Li std::error_code
136e3bf4fd3SXinliang David Li TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
137e3bf4fd3SXinliang David Li 
138e3bf4fd3SXinliang David Li #define CHECK_LINE_END(Line)                                                   \
139e3bf4fd3SXinliang David Li   if (Line.is_at_end())                                                        \
140e3bf4fd3SXinliang David Li     return error(instrprof_error::truncated);
141e3bf4fd3SXinliang David Li #define READ_NUM(Str, Dst)                                                     \
142e3bf4fd3SXinliang David Li   if ((Str).getAsInteger(10, (Dst)))                                           \
143e3bf4fd3SXinliang David Li     return error(instrprof_error::malformed);
144e3bf4fd3SXinliang David Li #define VP_READ_ADVANCE(Val)                                                   \
145e3bf4fd3SXinliang David Li   CHECK_LINE_END(Line);                                                        \
146e3bf4fd3SXinliang David Li   uint32_t Val;                                                                \
147e3bf4fd3SXinliang David Li   READ_NUM((*Line), (Val));                                                    \
148e3bf4fd3SXinliang David Li   Line++;
149e3bf4fd3SXinliang David Li 
150e3bf4fd3SXinliang David Li   if (Line.is_at_end())
151e3bf4fd3SXinliang David Li     return success();
152a716cc5cSXinliang David Li 
153e3bf4fd3SXinliang David Li   uint32_t NumValueKinds;
154e3bf4fd3SXinliang David Li   if (Line->getAsInteger(10, NumValueKinds)) {
155e3bf4fd3SXinliang David Li     // No value profile data
156e3bf4fd3SXinliang David Li     return success();
157e3bf4fd3SXinliang David Li   }
158e3bf4fd3SXinliang David Li   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
159e3bf4fd3SXinliang David Li     return error(instrprof_error::malformed);
160e3bf4fd3SXinliang David Li   Line++;
161e3bf4fd3SXinliang David Li 
162e3bf4fd3SXinliang David Li   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
163e3bf4fd3SXinliang David Li     VP_READ_ADVANCE(ValueKind);
164e3bf4fd3SXinliang David Li     if (ValueKind > IPVK_Last)
165e3bf4fd3SXinliang David Li       return error(instrprof_error::malformed);
166e3bf4fd3SXinliang David Li     VP_READ_ADVANCE(NumValueSites);
167e3bf4fd3SXinliang David Li     if (!NumValueSites)
168e3bf4fd3SXinliang David Li       continue;
169e3bf4fd3SXinliang David Li 
170e3bf4fd3SXinliang David Li     Record.reserveSites(VK, NumValueSites);
171e3bf4fd3SXinliang David Li     for (uint32_t S = 0; S < NumValueSites; S++) {
172e3bf4fd3SXinliang David Li       VP_READ_ADVANCE(NumValueData);
173e3bf4fd3SXinliang David Li 
174e3bf4fd3SXinliang David Li       std::vector<InstrProfValueData> CurrentValues;
175e3bf4fd3SXinliang David Li       for (uint32_t V = 0; V < NumValueData; V++) {
176e3bf4fd3SXinliang David Li         CHECK_LINE_END(Line);
177e3bf4fd3SXinliang David Li         std::pair<StringRef, StringRef> VD = Line->split(':');
178e3bf4fd3SXinliang David Li         uint64_t TakenCount, Value;
179a716cc5cSXinliang David Li         if (VK == IPVK_IndirectCallTarget) {
180a716cc5cSXinliang David Li           Symtab->addFuncName(VD.first);
181a716cc5cSXinliang David Li           Value = IndexedInstrProf::ComputeHash(VD.first);
182a716cc5cSXinliang David Li         } else {
183e3bf4fd3SXinliang David Li           READ_NUM(VD.first, Value);
184e3bf4fd3SXinliang David Li         }
185a716cc5cSXinliang David Li         READ_NUM(VD.second, TakenCount);
186e3bf4fd3SXinliang David Li         CurrentValues.push_back({Value, TakenCount});
187e3bf4fd3SXinliang David Li         Line++;
188e3bf4fd3SXinliang David Li       }
189e3bf4fd3SXinliang David Li       Record.addValueData(VK, S, CurrentValues.data(), NumValueData, nullptr);
190e3bf4fd3SXinliang David Li     }
191e3bf4fd3SXinliang David Li   }
192e3bf4fd3SXinliang David Li   return success();
193e3bf4fd3SXinliang David Li 
194e3bf4fd3SXinliang David Li #undef CHECK_LINE_END
195e3bf4fd3SXinliang David Li #undef READ_NUM
196e3bf4fd3SXinliang David Li #undef VP_READ_ADVANCE
197e3bf4fd3SXinliang David Li }
198e3bf4fd3SXinliang David Li 
199db4ed0bdSRafael Espindola std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
200cf36a366SJustin Bogner   // Skip empty lines and comments.
201cf36a366SJustin Bogner   while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
202f8d79198SJustin Bogner     ++Line;
203f8d79198SJustin Bogner   // If we hit EOF while looking for a name, we're done.
204a716cc5cSXinliang David Li   if (Line.is_at_end()) {
205a716cc5cSXinliang David Li     Symtab->finalizeSymtab();
206f8d79198SJustin Bogner     return error(instrprof_error::eof);
207a716cc5cSXinliang David Li   }
208f8d79198SJustin Bogner 
209f8d79198SJustin Bogner   // Read the function name.
210f8d79198SJustin Bogner   Record.Name = *Line++;
211a716cc5cSXinliang David Li   Symtab->addFuncName(Record.Name);
212f8d79198SJustin Bogner 
213f8d79198SJustin Bogner   // Read the function hash.
214f8d79198SJustin Bogner   if (Line.is_at_end())
215f8d79198SJustin Bogner     return error(instrprof_error::truncated);
216f95ca075SJustin Bogner   if ((Line++)->getAsInteger(0, Record.Hash))
217f8d79198SJustin Bogner     return error(instrprof_error::malformed);
218f8d79198SJustin Bogner 
219f8d79198SJustin Bogner   // Read the number of counters.
220f8d79198SJustin Bogner   uint64_t NumCounters;
221f8d79198SJustin Bogner   if (Line.is_at_end())
222f8d79198SJustin Bogner     return error(instrprof_error::truncated);
223f8d79198SJustin Bogner   if ((Line++)->getAsInteger(10, NumCounters))
224f8d79198SJustin Bogner     return error(instrprof_error::malformed);
225b59d7c73SJustin Bogner   if (NumCounters == 0)
226b59d7c73SJustin Bogner     return error(instrprof_error::malformed);
227f8d79198SJustin Bogner 
228f8d79198SJustin Bogner   // Read each counter and fill our internal storage with the values.
2293a7d44cbSJustin Bogner   Record.Counts.clear();
2303a7d44cbSJustin Bogner   Record.Counts.reserve(NumCounters);
231f8d79198SJustin Bogner   for (uint64_t I = 0; I < NumCounters; ++I) {
232f8d79198SJustin Bogner     if (Line.is_at_end())
233f8d79198SJustin Bogner       return error(instrprof_error::truncated);
234f8d79198SJustin Bogner     uint64_t Count;
235f8d79198SJustin Bogner     if ((Line++)->getAsInteger(10, Count))
236f8d79198SJustin Bogner       return error(instrprof_error::malformed);
2373a7d44cbSJustin Bogner     Record.Counts.push_back(Count);
238f8d79198SJustin Bogner   }
239f8d79198SJustin Bogner 
240e3bf4fd3SXinliang David Li   // Check if value profile data exists and read it if so.
241e3bf4fd3SXinliang David Li   if (std::error_code EC = readValueProfileData(Record))
242e3bf4fd3SXinliang David Li     return EC;
243e3bf4fd3SXinliang David Li 
244a716cc5cSXinliang David Li   // This is needed to avoid two pass parsing because llvm-profdata
245a716cc5cSXinliang David Li   // does dumping while reading.
246a716cc5cSXinliang David Li   Symtab->finalizeSymtab();
247f8d79198SJustin Bogner   return success();
248f8d79198SJustin Bogner }
24924b4b653SDuncan P. N. Exon Smith 
2504680361dSDuncan P. N. Exon Smith template <class IntPtrT>
2514680361dSDuncan P. N. Exon Smith bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
252d7d83477SDuncan P. N. Exon Smith   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
2534680361dSDuncan P. N. Exon Smith     return false;
254d7d83477SDuncan P. N. Exon Smith   uint64_t Magic =
255d7d83477SDuncan P. N. Exon Smith     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
256dab183edSXinliang David Li   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
257dab183edSXinliang David Li          sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
2584680361dSDuncan P. N. Exon Smith }
2594680361dSDuncan P. N. Exon Smith 
2604680361dSDuncan P. N. Exon Smith template <class IntPtrT>
261db4ed0bdSRafael Espindola std::error_code RawInstrProfReader<IntPtrT>::readHeader() {
26209a67f45SDuncan P. N. Exon Smith   if (!hasFormat(*DataBuffer))
26309a67f45SDuncan P. N. Exon Smith     return error(instrprof_error::bad_magic);
264dab183edSXinliang David Li   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
265531bb481SDuncan P. N. Exon Smith     return error(instrprof_error::bad_header);
266dab183edSXinliang David Li   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
267dab183edSXinliang David Li       DataBuffer->getBufferStart());
268dab183edSXinliang David Li   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
26924b4b653SDuncan P. N. Exon Smith   return readHeader(*Header);
27024b4b653SDuncan P. N. Exon Smith }
27124b4b653SDuncan P. N. Exon Smith 
272a119f323SJustin Bogner template <class IntPtrT>
273db4ed0bdSRafael Espindola std::error_code
274db4ed0bdSRafael Espindola RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
275a119f323SJustin Bogner   const char *End = DataBuffer->getBufferEnd();
276a119f323SJustin Bogner   // Skip zero padding between profiles.
277a119f323SJustin Bogner   while (CurrentPos != End && *CurrentPos == 0)
278a119f323SJustin Bogner     ++CurrentPos;
279a119f323SJustin Bogner   // If there's nothing left, we're done.
280a119f323SJustin Bogner   if (CurrentPos == End)
281a119f323SJustin Bogner     return instrprof_error::eof;
282a119f323SJustin Bogner   // If there isn't enough space for another header, this is probably just
283a119f323SJustin Bogner   // garbage at the end of the file.
284dab183edSXinliang David Li   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
285a119f323SJustin Bogner     return instrprof_error::malformed;
28654b11282SJustin Bogner   // The writer ensures each profile is padded to start at an aligned address.
28754b11282SJustin Bogner   if (reinterpret_cast<size_t>(CurrentPos) % alignOf<uint64_t>())
28854b11282SJustin Bogner     return instrprof_error::malformed;
289a119f323SJustin Bogner   // The magic should have the same byte order as in the previous header.
290a119f323SJustin Bogner   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
291dab183edSXinliang David Li   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
292a119f323SJustin Bogner     return instrprof_error::bad_magic;
293a119f323SJustin Bogner 
294a119f323SJustin Bogner   // There's another profile to read, so we need to process the header.
295dab183edSXinliang David Li   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
296a119f323SJustin Bogner   return readHeader(*Header);
297a119f323SJustin Bogner }
298a119f323SJustin Bogner 
2994680361dSDuncan P. N. Exon Smith template <class IntPtrT>
300a716cc5cSXinliang David Li void RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
301a82d6c0aSXinliang David Li   Symtab.create(StringRef(NamesStart, NamesSize));
302a716cc5cSXinliang David Li   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
303a716cc5cSXinliang David Li     const IntPtrT FPtr = swap(I->FunctionPointer);
304a716cc5cSXinliang David Li     if (!FPtr)
305a716cc5cSXinliang David Li       continue;
306a82d6c0aSXinliang David Li     Symtab.mapAddress(FPtr, I->NameRef);
307a716cc5cSXinliang David Li   }
308a716cc5cSXinliang David Li   Symtab.finalizeSymtab();
309a716cc5cSXinliang David Li }
310a716cc5cSXinliang David Li 
311a716cc5cSXinliang David Li template <class IntPtrT>
312a716cc5cSXinliang David Li std::error_code
313a716cc5cSXinliang David Li RawInstrProfReader<IntPtrT>::readHeader(const RawInstrProf::Header &Header) {
31433c76c0cSRong Xu   Version = swap(Header.Version);
31533c76c0cSRong Xu   if (GET_VERSION(Version) != RawInstrProf::Version)
31624b4b653SDuncan P. N. Exon Smith     return error(instrprof_error::unsupported_version);
31724b4b653SDuncan P. N. Exon Smith 
31824b4b653SDuncan P. N. Exon Smith   CountersDelta = swap(Header.CountersDelta);
31924b4b653SDuncan P. N. Exon Smith   NamesDelta = swap(Header.NamesDelta);
32024b4b653SDuncan P. N. Exon Smith   auto DataSize = swap(Header.DataSize);
32124b4b653SDuncan P. N. Exon Smith   auto CountersSize = swap(Header.CountersSize);
322a82d6c0aSXinliang David Li   NamesSize = swap(Header.NamesSize);
3236fac1741SBetul Buyukkurt   auto ValueDataSize = swap(Header.ValueDataSize);
3246fac1741SBetul Buyukkurt   ValueKindLast = swap(Header.ValueKindLast);
3256fac1741SBetul Buyukkurt 
3266fac1741SBetul Buyukkurt   auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
3276fac1741SBetul Buyukkurt   auto PaddingSize = getNumPaddingBytes(NamesSize);
32824b4b653SDuncan P. N. Exon Smith 
329dab183edSXinliang David Li   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header);
3306fac1741SBetul Buyukkurt   ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes;
33124b4b653SDuncan P. N. Exon Smith   ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
3326fac1741SBetul Buyukkurt   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
3336fac1741SBetul Buyukkurt   size_t ProfileSize = ValueDataOffset + ValueDataSize;
33424b4b653SDuncan P. N. Exon Smith 
335a119f323SJustin Bogner   auto *Start = reinterpret_cast<const char *>(&Header);
336a119f323SJustin Bogner   if (Start + ProfileSize > DataBuffer->getBufferEnd())
337531bb481SDuncan P. N. Exon Smith     return error(instrprof_error::bad_header);
33824b4b653SDuncan P. N. Exon Smith 
339dab183edSXinliang David Li   Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
340dab183edSXinliang David Li       Start + DataOffset);
34124b4b653SDuncan P. N. Exon Smith   DataEnd = Data + DataSize;
342d7d83477SDuncan P. N. Exon Smith   CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
343d7d83477SDuncan P. N. Exon Smith   NamesStart = Start + NamesOffset;
3446fac1741SBetul Buyukkurt   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
345a119f323SJustin Bogner   ProfileEnd = Start + ProfileSize;
34624b4b653SDuncan P. N. Exon Smith 
347a716cc5cSXinliang David Li   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
348a716cc5cSXinliang David Li   createSymtab(*NewSymtab.get());
349a716cc5cSXinliang David Li   Symtab = std::move(NewSymtab);
35024b4b653SDuncan P. N. Exon Smith   return success();
35124b4b653SDuncan P. N. Exon Smith }
35224b4b653SDuncan P. N. Exon Smith 
3534680361dSDuncan P. N. Exon Smith template <class IntPtrT>
354cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) {
355a82d6c0aSXinliang David Li   Record.Name = getName(Data->NameRef);
356cf4a128cSXinliang David Li   return success();
357cf4a128cSXinliang David Li }
358cf4a128cSXinliang David Li 
359cf4a128cSXinliang David Li template <class IntPtrT>
360cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readFuncHash(
361cf4a128cSXinliang David Li     InstrProfRecord &Record) {
362cf4a128cSXinliang David Li   Record.Hash = swap(Data->FuncHash);
363cf4a128cSXinliang David Li   return success();
364cf4a128cSXinliang David Li }
365cf4a128cSXinliang David Li 
366cf4a128cSXinliang David Li template <class IntPtrT>
367cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readRawCounts(
368cf4a128cSXinliang David Li     InstrProfRecord &Record) {
369b59d7c73SJustin Bogner   uint32_t NumCounters = swap(Data->NumCounters);
370cf4a128cSXinliang David Li   IntPtrT CounterPtr = Data->CounterPtr;
371b59d7c73SJustin Bogner   if (NumCounters == 0)
372b59d7c73SJustin Bogner     return error(instrprof_error::malformed);
373cf4a128cSXinliang David Li 
374cf4a128cSXinliang David Li   auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters);
375cf4a128cSXinliang David Li   auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
37624b4b653SDuncan P. N. Exon Smith 
37724b4b653SDuncan P. N. Exon Smith   // Check bounds.
378cf4a128cSXinliang David Li   if (RawCounts.data() < CountersStart ||
379d7d83477SDuncan P. N. Exon Smith       RawCounts.data() + RawCounts.size() > NamesStartAsCounter)
38024b4b653SDuncan P. N. Exon Smith     return error(instrprof_error::malformed);
38124b4b653SDuncan P. N. Exon Smith 
38224b4b653SDuncan P. N. Exon Smith   if (ShouldSwapBytes) {
3833a7d44cbSJustin Bogner     Record.Counts.clear();
3843a7d44cbSJustin Bogner     Record.Counts.reserve(RawCounts.size());
38524b4b653SDuncan P. N. Exon Smith     for (uint64_t Count : RawCounts)
3863a7d44cbSJustin Bogner       Record.Counts.push_back(swap(Count));
38724b4b653SDuncan P. N. Exon Smith   } else
38824b4b653SDuncan P. N. Exon Smith     Record.Counts = RawCounts;
38924b4b653SDuncan P. N. Exon Smith 
390cf4a128cSXinliang David Li   return success();
391cf4a128cSXinliang David Li }
392cf4a128cSXinliang David Li 
393cf4a128cSXinliang David Li template <class IntPtrT>
39401cb9bd7SXinliang David Li std::error_code
39501cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readValueProfilingData(InstrProfRecord &Record) {
3966fac1741SBetul Buyukkurt 
3976fac1741SBetul Buyukkurt   Record.clearValueData();
398d922c26cSXinliang David Li   CurValueDataSize = 0;
399d922c26cSXinliang David Li   // Need to match the logic in value profile dumper code in compiler-rt:
400d922c26cSXinliang David Li   uint32_t NumValueKinds = 0;
401d922c26cSXinliang David Li   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
402d922c26cSXinliang David Li     NumValueKinds += (Data->NumValueSites[I] != 0);
403d922c26cSXinliang David Li 
404d922c26cSXinliang David Li   if (!NumValueKinds)
4056fac1741SBetul Buyukkurt     return success();
4066fac1741SBetul Buyukkurt 
40701cb9bd7SXinliang David Li   ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
408d922c26cSXinliang David Li       ValueProfData::getValueProfData(ValueDataStart,
40901cb9bd7SXinliang David Li                                       (const unsigned char *)ProfileEnd,
41001cb9bd7SXinliang David Li                                       getDataEndianness());
4116fac1741SBetul Buyukkurt 
41201cb9bd7SXinliang David Li   if (VDataPtrOrErr.getError())
41301cb9bd7SXinliang David Li     return VDataPtrOrErr.getError();
4146fac1741SBetul Buyukkurt 
415a716cc5cSXinliang David Li   VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap());
416d922c26cSXinliang David Li   CurValueDataSize = VDataPtrOrErr.get()->getSize();
4176fac1741SBetul Buyukkurt   return success();
4186fac1741SBetul Buyukkurt }
4196fac1741SBetul Buyukkurt 
4206fac1741SBetul Buyukkurt template <class IntPtrT>
42101cb9bd7SXinliang David Li std::error_code
42201cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
423cf4a128cSXinliang David Li   if (atEnd())
4244c3ab815SXinliang David Li     if (std::error_code EC = readNextHeader(ProfileEnd))
4254c3ab815SXinliang David Li       return EC;
426cf4a128cSXinliang David Li 
427cf4a128cSXinliang David Li   // Read name ad set it in Record.
4284c3ab815SXinliang David Li   if (std::error_code EC = readName(Record))
4294c3ab815SXinliang David Li     return EC;
430cf4a128cSXinliang David Li 
431cf4a128cSXinliang David Li   // Read FuncHash and set it in Record.
4324c3ab815SXinliang David Li   if (std::error_code EC = readFuncHash(Record))
4334c3ab815SXinliang David Li     return EC;
434cf4a128cSXinliang David Li 
435cf4a128cSXinliang David Li   // Read raw counts and set Record.
4364c3ab815SXinliang David Li   if (std::error_code EC = readRawCounts(Record))
4374c3ab815SXinliang David Li     return EC;
438cf4a128cSXinliang David Li 
4396fac1741SBetul Buyukkurt   // Read value data and set Record.
4402d4803e8SXinliang David Li   if (std::error_code EC = readValueProfilingData(Record))
4412d4803e8SXinliang David Li     return EC;
4426fac1741SBetul Buyukkurt 
44324b4b653SDuncan P. N. Exon Smith   // Iterate.
444cf4a128cSXinliang David Li   advanceData();
44524b4b653SDuncan P. N. Exon Smith   return success();
44624b4b653SDuncan P. N. Exon Smith }
4474680361dSDuncan P. N. Exon Smith 
4484680361dSDuncan P. N. Exon Smith namespace llvm {
4494680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint32_t>;
4504680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint64_t>;
4514680361dSDuncan P. N. Exon Smith }
452b7aa2630SJustin Bogner 
453b5d368e8SJustin Bogner InstrProfLookupTrait::hash_value_type
454b5d368e8SJustin Bogner InstrProfLookupTrait::ComputeHash(StringRef K) {
455b5d368e8SJustin Bogner   return IndexedInstrProf::ComputeHash(HashType, K);
456b5d368e8SJustin Bogner }
457b5d368e8SJustin Bogner 
4583a7d44cbSJustin Bogner typedef InstrProfLookupTrait::data_type data_type;
4593a7d44cbSJustin Bogner typedef InstrProfLookupTrait::offset_type offset_type;
4603a7d44cbSJustin Bogner 
461be969c29SXinliang David Li bool InstrProfLookupTrait::readValueProfilingData(
4629e9a057aSJustin Bogner     const unsigned char *&D, const unsigned char *const End) {
46399556877SXinliang David Li   ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
46499556877SXinliang David Li       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
4659e9a057aSJustin Bogner 
466ee415895SXinliang David Li   if (VDataPtrOrErr.getError())
4679e9a057aSJustin Bogner     return false;
4682004f003SXinliang David Li 
469a716cc5cSXinliang David Li   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
470ee415895SXinliang David Li   D += VDataPtrOrErr.get()->TotalSize;
4719e9a057aSJustin Bogner 
4729e9a057aSJustin Bogner   return true;
4739e9a057aSJustin Bogner }
4749e9a057aSJustin Bogner 
4753a7d44cbSJustin Bogner data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
4763a7d44cbSJustin Bogner                                          offset_type N) {
4773a7d44cbSJustin Bogner   // Check if the data is corrupt. If so, don't try to read it.
4783a7d44cbSJustin Bogner   if (N % sizeof(uint64_t))
4793a7d44cbSJustin Bogner     return data_type();
4803a7d44cbSJustin Bogner 
4813a7d44cbSJustin Bogner   DataBuffer.clear();
4823a7d44cbSJustin Bogner   std::vector<uint64_t> CounterBuffer;
4839e9a057aSJustin Bogner 
4843a7d44cbSJustin Bogner   using namespace support;
4859e9a057aSJustin Bogner   const unsigned char *End = D + N;
4869e9a057aSJustin Bogner   while (D < End) {
487c758387eSXinliang David Li     // Read hash.
4889e9a057aSJustin Bogner     if (D + sizeof(uint64_t) >= End)
4899e9a057aSJustin Bogner       return data_type();
4903a7d44cbSJustin Bogner     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
4913a7d44cbSJustin Bogner 
49233c76c0cSRong Xu     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
4939e9a057aSJustin Bogner     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
494c758387eSXinliang David Li     // If format version is different then read the number of counters.
49533c76c0cSRong Xu     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
4969e9a057aSJustin Bogner       if (D + sizeof(uint64_t) > End)
4973a7d44cbSJustin Bogner         return data_type();
4989e9a057aSJustin Bogner       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
4999e9a057aSJustin Bogner     }
500c758387eSXinliang David Li     // Read counter values.
5019e9a057aSJustin Bogner     if (D + CountsSize * sizeof(uint64_t) > End)
5023a7d44cbSJustin Bogner       return data_type();
5033a7d44cbSJustin Bogner 
5043a7d44cbSJustin Bogner     CounterBuffer.clear();
5059e9a057aSJustin Bogner     CounterBuffer.reserve(CountsSize);
5069e9a057aSJustin Bogner     for (uint64_t J = 0; J < CountsSize; ++J)
5073a7d44cbSJustin Bogner       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
5083a7d44cbSJustin Bogner 
5092004f003SXinliang David Li     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
5109e9a057aSJustin Bogner 
511c758387eSXinliang David Li     // Read value profiling data.
51233c76c0cSRong Xu     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
513a6b2c4f7SXinliang David Li         !readValueProfilingData(D, End)) {
5149e9a057aSJustin Bogner       DataBuffer.clear();
5159e9a057aSJustin Bogner       return data_type();
5169e9a057aSJustin Bogner     }
5173a7d44cbSJustin Bogner   }
5183a7d44cbSJustin Bogner   return DataBuffer;
5193a7d44cbSJustin Bogner }
5203a7d44cbSJustin Bogner 
521a28306dbSXinliang David Li template <typename HashTableImpl>
522a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords(
523a28306dbSXinliang David Li     StringRef FuncName, ArrayRef<InstrProfRecord> &Data) {
524a28306dbSXinliang David Li   auto Iter = HashTable->find(FuncName);
525a28306dbSXinliang David Li   if (Iter == HashTable->end())
5264c3ab815SXinliang David Li     return instrprof_error::unknown_function;
527140f4c4fSXinliang David Li 
528140f4c4fSXinliang David Li   Data = (*Iter);
5294c3ab815SXinliang David Li   if (Data.empty())
5304c3ab815SXinliang David Li     return instrprof_error::malformed;
531140f4c4fSXinliang David Li 
532140f4c4fSXinliang David Li   return instrprof_error::success;
533140f4c4fSXinliang David Li }
534140f4c4fSXinliang David Li 
535a28306dbSXinliang David Li template <typename HashTableImpl>
536a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords(
537140f4c4fSXinliang David Li     ArrayRef<InstrProfRecord> &Data) {
538a28306dbSXinliang David Li   if (atEnd())
539a28306dbSXinliang David Li     return instrprof_error::eof;
540140f4c4fSXinliang David Li 
541140f4c4fSXinliang David Li   Data = *RecordIterator;
542140f4c4fSXinliang David Li 
5432d4803e8SXinliang David Li   if (Data.empty())
5442d4803e8SXinliang David Li     return instrprof_error::malformed;
545140f4c4fSXinliang David Li 
546140f4c4fSXinliang David Li   return instrprof_error::success;
547140f4c4fSXinliang David Li }
548140f4c4fSXinliang David Li 
549a28306dbSXinliang David Li template <typename HashTableImpl>
550a28306dbSXinliang David Li InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
551a28306dbSXinliang David Li     const unsigned char *Buckets, const unsigned char *const Payload,
552a28306dbSXinliang David Li     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
553140f4c4fSXinliang David Li     uint64_t Version) {
554140f4c4fSXinliang David Li   FormatVersion = Version;
555a28306dbSXinliang David Li   HashTable.reset(HashTableImpl::Create(
556a28306dbSXinliang David Li       Buckets, Payload, Base,
557a28306dbSXinliang David Li       typename HashTableImpl::InfoType(HashType, Version)));
558a28306dbSXinliang David Li   RecordIterator = HashTable->data_begin();
559140f4c4fSXinliang David Li }
560140f4c4fSXinliang David Li 
561b7aa2630SJustin Bogner bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
5624c3ab815SXinliang David Li   if (DataBuffer.getBufferSize() < 8)
5634c3ab815SXinliang David Li     return false;
564b7aa2630SJustin Bogner   using namespace support;
565b7aa2630SJustin Bogner   uint64_t Magic =
566b7aa2630SJustin Bogner       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
567c758387eSXinliang David Li   // Verify that it's magical.
568b7aa2630SJustin Bogner   return Magic == IndexedInstrProf::Magic;
569b7aa2630SJustin Bogner }
570b7aa2630SJustin Bogner 
5716c93ee8dSXinliang David Li const unsigned char *
5726c93ee8dSXinliang David Li IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
5736c93ee8dSXinliang David Li                                     const unsigned char *Cur) {
5746c93ee8dSXinliang David Li   using namespace support;
5756c93ee8dSXinliang David Li   if (Version >= IndexedInstrProf::Version4) {
5766c93ee8dSXinliang David Li     const IndexedInstrProf::Summary *SummaryInLE =
5776c93ee8dSXinliang David Li         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
5786c93ee8dSXinliang David Li     uint64_t NFields =
5796c93ee8dSXinliang David Li         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
5806c93ee8dSXinliang David Li     uint64_t NEntries =
5816c93ee8dSXinliang David Li         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
5826c93ee8dSXinliang David Li     uint32_t SummarySize =
5836c93ee8dSXinliang David Li         IndexedInstrProf::Summary::getSize(NFields, NEntries);
5846c93ee8dSXinliang David Li     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
5856c93ee8dSXinliang David Li         IndexedInstrProf::allocSummary(SummarySize);
5866c93ee8dSXinliang David Li 
5876c93ee8dSXinliang David Li     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
5886c93ee8dSXinliang David Li     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
5896c93ee8dSXinliang David Li     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
5906c93ee8dSXinliang David Li       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
5916c93ee8dSXinliang David Li 
5924309570dSEaswaran Raman     // initialize InstrProfSummary using the SummaryData from disk.
5934309570dSEaswaran Raman     this->Summary = llvm::make_unique<InstrProfSummary>(*(SummaryData.get()));
5946c93ee8dSXinliang David Li     return Cur + SummarySize;
5956c93ee8dSXinliang David Li   } else {
5966c93ee8dSXinliang David Li     // For older version of profile data, we need to compute on the fly:
5976c93ee8dSXinliang David Li     using namespace IndexedInstrProf;
598*40ee23dbSEaswaran Raman     this->Summary =
599*40ee23dbSEaswaran Raman         llvm::make_unique<InstrProfSummary>(ProfileSummary::DefaultCutoffs);
6006c93ee8dSXinliang David Li     this->Summary->computeDetailedSummary();
6016c93ee8dSXinliang David Li     return Cur;
6026c93ee8dSXinliang David Li   }
6036c93ee8dSXinliang David Li }
6046c93ee8dSXinliang David Li 
605db4ed0bdSRafael Espindola std::error_code IndexedInstrProfReader::readHeader() {
606a7c9ed57SAaron Ballman   const unsigned char *Start =
607a7c9ed57SAaron Ballman       (const unsigned char *)DataBuffer->getBufferStart();
608b7aa2630SJustin Bogner   const unsigned char *Cur = Start;
609a7c9ed57SAaron Ballman   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
610b7aa2630SJustin Bogner     return error(instrprof_error::truncated);
611b7aa2630SJustin Bogner 
612b7aa2630SJustin Bogner   using namespace support;
613b7aa2630SJustin Bogner 
614dab183edSXinliang David Li   auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
615dab183edSXinliang David Li   Cur += sizeof(IndexedInstrProf::Header);
616dab183edSXinliang David Li 
617b7aa2630SJustin Bogner   // Check the magic number.
618dab183edSXinliang David Li   uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
619b7aa2630SJustin Bogner   if (Magic != IndexedInstrProf::Magic)
620b7aa2630SJustin Bogner     return error(instrprof_error::bad_magic);
621b7aa2630SJustin Bogner 
622b7aa2630SJustin Bogner   // Read the version.
623140f4c4fSXinliang David Li   uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
62433c76c0cSRong Xu   if (GET_VERSION(FormatVersion) >
62533c76c0cSRong Xu       IndexedInstrProf::ProfVersion::CurrentVersion)
626b7aa2630SJustin Bogner     return error(instrprof_error::unsupported_version);
627b7aa2630SJustin Bogner 
6286c93ee8dSXinliang David Li   Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
629b7aa2630SJustin Bogner 
630b7aa2630SJustin Bogner   // Read the hash type and start offset.
631b7aa2630SJustin Bogner   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
632dab183edSXinliang David Li       endian::byte_swap<uint64_t, little>(Header->HashType));
633b7aa2630SJustin Bogner   if (HashType > IndexedInstrProf::HashT::Last)
634b7aa2630SJustin Bogner     return error(instrprof_error::unsupported_hash_type);
635dab183edSXinliang David Li 
636dab183edSXinliang David Li   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
637b7aa2630SJustin Bogner 
638b7aa2630SJustin Bogner   // The rest of the file is an on disk hash table.
639a28306dbSXinliang David Li   InstrProfReaderIndexBase *IndexPtr = nullptr;
640a28306dbSXinliang David Li   IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>(
641a28306dbSXinliang David Li       Start + HashOffset, Cur, Start, HashType, FormatVersion);
642a28306dbSXinliang David Li   Index.reset(IndexPtr);
643b7aa2630SJustin Bogner   return success();
644b7aa2630SJustin Bogner }
645b7aa2630SJustin Bogner 
646a716cc5cSXinliang David Li InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
647a716cc5cSXinliang David Li   if (Symtab.get())
648a716cc5cSXinliang David Li     return *Symtab.get();
649a716cc5cSXinliang David Li 
650a716cc5cSXinliang David Li   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
651a716cc5cSXinliang David Li   Index->populateSymtab(*NewSymtab.get());
652a716cc5cSXinliang David Li 
653a716cc5cSXinliang David Li   Symtab = std::move(NewSymtab);
654a716cc5cSXinliang David Li   return *Symtab.get();
655a716cc5cSXinliang David Li }
656a716cc5cSXinliang David Li 
6576aa216c2SXinliang David Li ErrorOr<InstrProfRecord>
6586aa216c2SXinliang David Li IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
6596aa216c2SXinliang David Li                                            uint64_t FuncHash) {
660140f4c4fSXinliang David Li   ArrayRef<InstrProfRecord> Data;
661a28306dbSXinliang David Li   std::error_code EC = Index->getRecords(FuncName, Data);
6624c3ab815SXinliang David Li   if (EC != instrprof_error::success)
6634c3ab815SXinliang David Li     return EC;
664821d7471SJustin Bogner   // Found it. Look for counters with the right hash.
6653a7d44cbSJustin Bogner   for (unsigned I = 0, E = Data.size(); I < E; ++I) {
666821d7471SJustin Bogner     // Check for a match and fill the vector if there is one.
6673a7d44cbSJustin Bogner     if (Data[I].Hash == FuncHash) {
6682004f003SXinliang David Li       return std::move(Data[I]);
669b7aa2630SJustin Bogner     }
670821d7471SJustin Bogner   }
671821d7471SJustin Bogner   return error(instrprof_error::hash_mismatch);
672821d7471SJustin Bogner }
673b7aa2630SJustin Bogner 
6746aa216c2SXinliang David Li std::error_code
6756aa216c2SXinliang David Li IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
6766aa216c2SXinliang David Li                                           std::vector<uint64_t> &Counts) {
6772004f003SXinliang David Li   ErrorOr<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
6786aa216c2SXinliang David Li   if (std::error_code EC = Record.getError())
6796aa216c2SXinliang David Li     return EC;
6802004f003SXinliang David Li 
6812004f003SXinliang David Li   Counts = Record.get().Counts;
6822004f003SXinliang David Li   return success();
6832004f003SXinliang David Li }
6842004f003SXinliang David Li 
685140f4c4fSXinliang David Li std::error_code IndexedInstrProfReader::readNextRecord(
686140f4c4fSXinliang David Li     InstrProfRecord &Record) {
6873a7d44cbSJustin Bogner   static unsigned RecordIndex = 0;
688140f4c4fSXinliang David Li 
689140f4c4fSXinliang David Li   ArrayRef<InstrProfRecord> Data;
690140f4c4fSXinliang David Li 
691a28306dbSXinliang David Li   std::error_code EC = Index->getRecords(Data);
6924c3ab815SXinliang David Li   if (EC != instrprof_error::success)
6934c3ab815SXinliang David Li     return error(EC);
694140f4c4fSXinliang David Li 
6953a7d44cbSJustin Bogner   Record = Data[RecordIndex++];
6963a7d44cbSJustin Bogner   if (RecordIndex >= Data.size()) {
697a28306dbSXinliang David Li     Index->advanceToNextKey();
6983a7d44cbSJustin Bogner     RecordIndex = 0;
699821d7471SJustin Bogner   }
700b7aa2630SJustin Bogner   return success();
701b7aa2630SJustin Bogner }
702