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>
300*e44482feSVedant Kumar std::error_code
301*e44482feSVedant Kumar RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
302*e44482feSVedant Kumar   std::error_code EC = Symtab.create(StringRef(NamesStart, NamesSize));
303*e44482feSVedant Kumar   if (EC)
304*e44482feSVedant Kumar     return EC;
305a716cc5cSXinliang David Li   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
306a716cc5cSXinliang David Li     const IntPtrT FPtr = swap(I->FunctionPointer);
307a716cc5cSXinliang David Li     if (!FPtr)
308a716cc5cSXinliang David Li       continue;
309a82d6c0aSXinliang David Li     Symtab.mapAddress(FPtr, I->NameRef);
310a716cc5cSXinliang David Li   }
311a716cc5cSXinliang David Li   Symtab.finalizeSymtab();
312*e44482feSVedant Kumar   return success();
313a716cc5cSXinliang David Li }
314a716cc5cSXinliang David Li 
315a716cc5cSXinliang David Li template <class IntPtrT>
316a716cc5cSXinliang David Li std::error_code
317a716cc5cSXinliang David Li RawInstrProfReader<IntPtrT>::readHeader(const RawInstrProf::Header &Header) {
31833c76c0cSRong Xu   Version = swap(Header.Version);
31933c76c0cSRong Xu   if (GET_VERSION(Version) != RawInstrProf::Version)
32024b4b653SDuncan P. N. Exon Smith     return error(instrprof_error::unsupported_version);
32124b4b653SDuncan P. N. Exon Smith 
32224b4b653SDuncan P. N. Exon Smith   CountersDelta = swap(Header.CountersDelta);
32324b4b653SDuncan P. N. Exon Smith   NamesDelta = swap(Header.NamesDelta);
32424b4b653SDuncan P. N. Exon Smith   auto DataSize = swap(Header.DataSize);
32524b4b653SDuncan P. N. Exon Smith   auto CountersSize = swap(Header.CountersSize);
326a82d6c0aSXinliang David Li   NamesSize = swap(Header.NamesSize);
3276fac1741SBetul Buyukkurt   auto ValueDataSize = swap(Header.ValueDataSize);
3286fac1741SBetul Buyukkurt   ValueKindLast = swap(Header.ValueKindLast);
3296fac1741SBetul Buyukkurt 
3306fac1741SBetul Buyukkurt   auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
3316fac1741SBetul Buyukkurt   auto PaddingSize = getNumPaddingBytes(NamesSize);
33224b4b653SDuncan P. N. Exon Smith 
333dab183edSXinliang David Li   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header);
3346fac1741SBetul Buyukkurt   ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes;
33524b4b653SDuncan P. N. Exon Smith   ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
3366fac1741SBetul Buyukkurt   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
3376fac1741SBetul Buyukkurt   size_t ProfileSize = ValueDataOffset + ValueDataSize;
33824b4b653SDuncan P. N. Exon Smith 
339a119f323SJustin Bogner   auto *Start = reinterpret_cast<const char *>(&Header);
340a119f323SJustin Bogner   if (Start + ProfileSize > DataBuffer->getBufferEnd())
341531bb481SDuncan P. N. Exon Smith     return error(instrprof_error::bad_header);
34224b4b653SDuncan P. N. Exon Smith 
343dab183edSXinliang David Li   Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
344dab183edSXinliang David Li       Start + DataOffset);
34524b4b653SDuncan P. N. Exon Smith   DataEnd = Data + DataSize;
346d7d83477SDuncan P. N. Exon Smith   CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
347d7d83477SDuncan P. N. Exon Smith   NamesStart = Start + NamesOffset;
3486fac1741SBetul Buyukkurt   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
349a119f323SJustin Bogner   ProfileEnd = Start + ProfileSize;
35024b4b653SDuncan P. N. Exon Smith 
351a716cc5cSXinliang David Li   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
352*e44482feSVedant Kumar   if (auto EC = createSymtab(*NewSymtab.get()))
353*e44482feSVedant Kumar     return EC;
354*e44482feSVedant Kumar 
355a716cc5cSXinliang David Li   Symtab = std::move(NewSymtab);
35624b4b653SDuncan P. N. Exon Smith   return success();
35724b4b653SDuncan P. N. Exon Smith }
35824b4b653SDuncan P. N. Exon Smith 
3594680361dSDuncan P. N. Exon Smith template <class IntPtrT>
360cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) {
361a82d6c0aSXinliang David Li   Record.Name = getName(Data->NameRef);
362cf4a128cSXinliang David Li   return success();
363cf4a128cSXinliang David Li }
364cf4a128cSXinliang David Li 
365cf4a128cSXinliang David Li template <class IntPtrT>
366cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readFuncHash(
367cf4a128cSXinliang David Li     InstrProfRecord &Record) {
368cf4a128cSXinliang David Li   Record.Hash = swap(Data->FuncHash);
369cf4a128cSXinliang David Li   return success();
370cf4a128cSXinliang David Li }
371cf4a128cSXinliang David Li 
372cf4a128cSXinliang David Li template <class IntPtrT>
373cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readRawCounts(
374cf4a128cSXinliang David Li     InstrProfRecord &Record) {
375b59d7c73SJustin Bogner   uint32_t NumCounters = swap(Data->NumCounters);
376cf4a128cSXinliang David Li   IntPtrT CounterPtr = Data->CounterPtr;
377b59d7c73SJustin Bogner   if (NumCounters == 0)
378b59d7c73SJustin Bogner     return error(instrprof_error::malformed);
379cf4a128cSXinliang David Li 
380cf4a128cSXinliang David Li   auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters);
381cf4a128cSXinliang David Li   auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
38224b4b653SDuncan P. N. Exon Smith 
38324b4b653SDuncan P. N. Exon Smith   // Check bounds.
384cf4a128cSXinliang David Li   if (RawCounts.data() < CountersStart ||
385d7d83477SDuncan P. N. Exon Smith       RawCounts.data() + RawCounts.size() > NamesStartAsCounter)
38624b4b653SDuncan P. N. Exon Smith     return error(instrprof_error::malformed);
38724b4b653SDuncan P. N. Exon Smith 
38824b4b653SDuncan P. N. Exon Smith   if (ShouldSwapBytes) {
3893a7d44cbSJustin Bogner     Record.Counts.clear();
3903a7d44cbSJustin Bogner     Record.Counts.reserve(RawCounts.size());
39124b4b653SDuncan P. N. Exon Smith     for (uint64_t Count : RawCounts)
3923a7d44cbSJustin Bogner       Record.Counts.push_back(swap(Count));
39324b4b653SDuncan P. N. Exon Smith   } else
39424b4b653SDuncan P. N. Exon Smith     Record.Counts = RawCounts;
39524b4b653SDuncan P. N. Exon Smith 
396cf4a128cSXinliang David Li   return success();
397cf4a128cSXinliang David Li }
398cf4a128cSXinliang David Li 
399cf4a128cSXinliang David Li template <class IntPtrT>
40001cb9bd7SXinliang David Li std::error_code
40101cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readValueProfilingData(InstrProfRecord &Record) {
4026fac1741SBetul Buyukkurt 
4036fac1741SBetul Buyukkurt   Record.clearValueData();
404d922c26cSXinliang David Li   CurValueDataSize = 0;
405d922c26cSXinliang David Li   // Need to match the logic in value profile dumper code in compiler-rt:
406d922c26cSXinliang David Li   uint32_t NumValueKinds = 0;
407d922c26cSXinliang David Li   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
408d922c26cSXinliang David Li     NumValueKinds += (Data->NumValueSites[I] != 0);
409d922c26cSXinliang David Li 
410d922c26cSXinliang David Li   if (!NumValueKinds)
4116fac1741SBetul Buyukkurt     return success();
4126fac1741SBetul Buyukkurt 
41301cb9bd7SXinliang David Li   ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
414d922c26cSXinliang David Li       ValueProfData::getValueProfData(ValueDataStart,
41501cb9bd7SXinliang David Li                                       (const unsigned char *)ProfileEnd,
41601cb9bd7SXinliang David Li                                       getDataEndianness());
4176fac1741SBetul Buyukkurt 
41801cb9bd7SXinliang David Li   if (VDataPtrOrErr.getError())
41901cb9bd7SXinliang David Li     return VDataPtrOrErr.getError();
4206fac1741SBetul Buyukkurt 
4212f36f059SAdam Nemet   // Note that besides deserialization, this also performs the conversion for
4222f36f059SAdam Nemet   // indirect call targets.  The function pointers from the raw profile are
4232f36f059SAdam Nemet   // remapped into function name hashes.
424a716cc5cSXinliang David Li   VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap());
425d922c26cSXinliang David Li   CurValueDataSize = VDataPtrOrErr.get()->getSize();
4266fac1741SBetul Buyukkurt   return success();
4276fac1741SBetul Buyukkurt }
4286fac1741SBetul Buyukkurt 
4296fac1741SBetul Buyukkurt template <class IntPtrT>
43001cb9bd7SXinliang David Li std::error_code
43101cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
432cf4a128cSXinliang David Li   if (atEnd())
4334c3ab815SXinliang David Li     if (std::error_code EC = readNextHeader(ProfileEnd))
4344c3ab815SXinliang David Li       return EC;
435cf4a128cSXinliang David Li 
436cf4a128cSXinliang David Li   // Read name ad set it in Record.
4374c3ab815SXinliang David Li   if (std::error_code EC = readName(Record))
4384c3ab815SXinliang David Li     return EC;
439cf4a128cSXinliang David Li 
440cf4a128cSXinliang David Li   // Read FuncHash and set it in Record.
4414c3ab815SXinliang David Li   if (std::error_code EC = readFuncHash(Record))
4424c3ab815SXinliang David Li     return EC;
443cf4a128cSXinliang David Li 
444cf4a128cSXinliang David Li   // Read raw counts and set Record.
4454c3ab815SXinliang David Li   if (std::error_code EC = readRawCounts(Record))
4464c3ab815SXinliang David Li     return EC;
447cf4a128cSXinliang David Li 
4486fac1741SBetul Buyukkurt   // Read value data and set Record.
4492d4803e8SXinliang David Li   if (std::error_code EC = readValueProfilingData(Record))
4502d4803e8SXinliang David Li     return EC;
4516fac1741SBetul Buyukkurt 
45224b4b653SDuncan P. N. Exon Smith   // Iterate.
453cf4a128cSXinliang David Li   advanceData();
45424b4b653SDuncan P. N. Exon Smith   return success();
45524b4b653SDuncan P. N. Exon Smith }
4564680361dSDuncan P. N. Exon Smith 
4574680361dSDuncan P. N. Exon Smith namespace llvm {
4584680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint32_t>;
4594680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint64_t>;
4604680361dSDuncan P. N. Exon Smith }
461b7aa2630SJustin Bogner 
462b5d368e8SJustin Bogner InstrProfLookupTrait::hash_value_type
463b5d368e8SJustin Bogner InstrProfLookupTrait::ComputeHash(StringRef K) {
464b5d368e8SJustin Bogner   return IndexedInstrProf::ComputeHash(HashType, K);
465b5d368e8SJustin Bogner }
466b5d368e8SJustin Bogner 
4673a7d44cbSJustin Bogner typedef InstrProfLookupTrait::data_type data_type;
4683a7d44cbSJustin Bogner typedef InstrProfLookupTrait::offset_type offset_type;
4693a7d44cbSJustin Bogner 
470be969c29SXinliang David Li bool InstrProfLookupTrait::readValueProfilingData(
4719e9a057aSJustin Bogner     const unsigned char *&D, const unsigned char *const End) {
47299556877SXinliang David Li   ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
47399556877SXinliang David Li       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
4749e9a057aSJustin Bogner 
475ee415895SXinliang David Li   if (VDataPtrOrErr.getError())
4769e9a057aSJustin Bogner     return false;
4772004f003SXinliang David Li 
478a716cc5cSXinliang David Li   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
479ee415895SXinliang David Li   D += VDataPtrOrErr.get()->TotalSize;
4809e9a057aSJustin Bogner 
4819e9a057aSJustin Bogner   return true;
4829e9a057aSJustin Bogner }
4839e9a057aSJustin Bogner 
4843a7d44cbSJustin Bogner data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
4853a7d44cbSJustin Bogner                                          offset_type N) {
4863a7d44cbSJustin Bogner   // Check if the data is corrupt. If so, don't try to read it.
4873a7d44cbSJustin Bogner   if (N % sizeof(uint64_t))
4883a7d44cbSJustin Bogner     return data_type();
4893a7d44cbSJustin Bogner 
4903a7d44cbSJustin Bogner   DataBuffer.clear();
4913a7d44cbSJustin Bogner   std::vector<uint64_t> CounterBuffer;
4929e9a057aSJustin Bogner 
4933a7d44cbSJustin Bogner   using namespace support;
4949e9a057aSJustin Bogner   const unsigned char *End = D + N;
4959e9a057aSJustin Bogner   while (D < End) {
496c758387eSXinliang David Li     // Read hash.
4979e9a057aSJustin Bogner     if (D + sizeof(uint64_t) >= End)
4989e9a057aSJustin Bogner       return data_type();
4993a7d44cbSJustin Bogner     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
5003a7d44cbSJustin Bogner 
50133c76c0cSRong Xu     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
5029e9a057aSJustin Bogner     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
503c758387eSXinliang David Li     // If format version is different then read the number of counters.
50433c76c0cSRong Xu     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
5059e9a057aSJustin Bogner       if (D + sizeof(uint64_t) > End)
5063a7d44cbSJustin Bogner         return data_type();
5079e9a057aSJustin Bogner       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
5089e9a057aSJustin Bogner     }
509c758387eSXinliang David Li     // Read counter values.
5109e9a057aSJustin Bogner     if (D + CountsSize * sizeof(uint64_t) > End)
5113a7d44cbSJustin Bogner       return data_type();
5123a7d44cbSJustin Bogner 
5133a7d44cbSJustin Bogner     CounterBuffer.clear();
5149e9a057aSJustin Bogner     CounterBuffer.reserve(CountsSize);
5159e9a057aSJustin Bogner     for (uint64_t J = 0; J < CountsSize; ++J)
5163a7d44cbSJustin Bogner       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
5173a7d44cbSJustin Bogner 
5182004f003SXinliang David Li     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
5199e9a057aSJustin Bogner 
520c758387eSXinliang David Li     // Read value profiling data.
52133c76c0cSRong Xu     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
522a6b2c4f7SXinliang David Li         !readValueProfilingData(D, End)) {
5239e9a057aSJustin Bogner       DataBuffer.clear();
5249e9a057aSJustin Bogner       return data_type();
5259e9a057aSJustin Bogner     }
5263a7d44cbSJustin Bogner   }
5273a7d44cbSJustin Bogner   return DataBuffer;
5283a7d44cbSJustin Bogner }
5293a7d44cbSJustin Bogner 
530a28306dbSXinliang David Li template <typename HashTableImpl>
531a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords(
532a28306dbSXinliang David Li     StringRef FuncName, ArrayRef<InstrProfRecord> &Data) {
533a28306dbSXinliang David Li   auto Iter = HashTable->find(FuncName);
534a28306dbSXinliang David Li   if (Iter == HashTable->end())
5354c3ab815SXinliang David Li     return instrprof_error::unknown_function;
536140f4c4fSXinliang David Li 
537140f4c4fSXinliang David Li   Data = (*Iter);
5384c3ab815SXinliang David Li   if (Data.empty())
5394c3ab815SXinliang David Li     return instrprof_error::malformed;
540140f4c4fSXinliang David Li 
541140f4c4fSXinliang David Li   return instrprof_error::success;
542140f4c4fSXinliang David Li }
543140f4c4fSXinliang David Li 
544a28306dbSXinliang David Li template <typename HashTableImpl>
545a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords(
546140f4c4fSXinliang David Li     ArrayRef<InstrProfRecord> &Data) {
547a28306dbSXinliang David Li   if (atEnd())
548a28306dbSXinliang David Li     return instrprof_error::eof;
549140f4c4fSXinliang David Li 
550140f4c4fSXinliang David Li   Data = *RecordIterator;
551140f4c4fSXinliang David Li 
5522d4803e8SXinliang David Li   if (Data.empty())
5532d4803e8SXinliang David Li     return instrprof_error::malformed;
554140f4c4fSXinliang David Li 
555140f4c4fSXinliang David Li   return instrprof_error::success;
556140f4c4fSXinliang David Li }
557140f4c4fSXinliang David Li 
558a28306dbSXinliang David Li template <typename HashTableImpl>
559a28306dbSXinliang David Li InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
560a28306dbSXinliang David Li     const unsigned char *Buckets, const unsigned char *const Payload,
561a28306dbSXinliang David Li     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
562140f4c4fSXinliang David Li     uint64_t Version) {
563140f4c4fSXinliang David Li   FormatVersion = Version;
564a28306dbSXinliang David Li   HashTable.reset(HashTableImpl::Create(
565a28306dbSXinliang David Li       Buckets, Payload, Base,
566a28306dbSXinliang David Li       typename HashTableImpl::InfoType(HashType, Version)));
567a28306dbSXinliang David Li   RecordIterator = HashTable->data_begin();
568140f4c4fSXinliang David Li }
569140f4c4fSXinliang David Li 
570b7aa2630SJustin Bogner bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
5714c3ab815SXinliang David Li   if (DataBuffer.getBufferSize() < 8)
5724c3ab815SXinliang David Li     return false;
573b7aa2630SJustin Bogner   using namespace support;
574b7aa2630SJustin Bogner   uint64_t Magic =
575b7aa2630SJustin Bogner       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
576c758387eSXinliang David Li   // Verify that it's magical.
577b7aa2630SJustin Bogner   return Magic == IndexedInstrProf::Magic;
578b7aa2630SJustin Bogner }
579b7aa2630SJustin Bogner 
5806c93ee8dSXinliang David Li const unsigned char *
5816c93ee8dSXinliang David Li IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
5826c93ee8dSXinliang David Li                                     const unsigned char *Cur) {
5836c93ee8dSXinliang David Li   using namespace support;
5846c93ee8dSXinliang David Li   if (Version >= IndexedInstrProf::Version4) {
5856c93ee8dSXinliang David Li     const IndexedInstrProf::Summary *SummaryInLE =
5866c93ee8dSXinliang David Li         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
5876c93ee8dSXinliang David Li     uint64_t NFields =
5886c93ee8dSXinliang David Li         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
5896c93ee8dSXinliang David Li     uint64_t NEntries =
5906c93ee8dSXinliang David Li         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
5916c93ee8dSXinliang David Li     uint32_t SummarySize =
5926c93ee8dSXinliang David Li         IndexedInstrProf::Summary::getSize(NFields, NEntries);
5936c93ee8dSXinliang David Li     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
5946c93ee8dSXinliang David Li         IndexedInstrProf::allocSummary(SummarySize);
5956c93ee8dSXinliang David Li 
5966c93ee8dSXinliang David Li     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
5976c93ee8dSXinliang David Li     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
5986c93ee8dSXinliang David Li     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
5996c93ee8dSXinliang David Li       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
6006c93ee8dSXinliang David Li 
6014309570dSEaswaran Raman     // initialize InstrProfSummary using the SummaryData from disk.
6024309570dSEaswaran Raman     this->Summary = llvm::make_unique<InstrProfSummary>(*(SummaryData.get()));
6036c93ee8dSXinliang David Li     return Cur + SummarySize;
6046c93ee8dSXinliang David Li   } else {
6056c93ee8dSXinliang David Li     // For older version of profile data, we need to compute on the fly:
6066c93ee8dSXinliang David Li     using namespace IndexedInstrProf;
60740ee23dbSEaswaran Raman     this->Summary =
60840ee23dbSEaswaran Raman         llvm::make_unique<InstrProfSummary>(ProfileSummary::DefaultCutoffs);
6096c93ee8dSXinliang David Li     this->Summary->computeDetailedSummary();
6106c93ee8dSXinliang David Li     return Cur;
6116c93ee8dSXinliang David Li   }
6126c93ee8dSXinliang David Li }
6136c93ee8dSXinliang David Li 
614db4ed0bdSRafael Espindola std::error_code IndexedInstrProfReader::readHeader() {
615a7c9ed57SAaron Ballman   const unsigned char *Start =
616a7c9ed57SAaron Ballman       (const unsigned char *)DataBuffer->getBufferStart();
617b7aa2630SJustin Bogner   const unsigned char *Cur = Start;
618a7c9ed57SAaron Ballman   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
619b7aa2630SJustin Bogner     return error(instrprof_error::truncated);
620b7aa2630SJustin Bogner 
621b7aa2630SJustin Bogner   using namespace support;
622b7aa2630SJustin Bogner 
623dab183edSXinliang David Li   auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
624dab183edSXinliang David Li   Cur += sizeof(IndexedInstrProf::Header);
625dab183edSXinliang David Li 
626b7aa2630SJustin Bogner   // Check the magic number.
627dab183edSXinliang David Li   uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
628b7aa2630SJustin Bogner   if (Magic != IndexedInstrProf::Magic)
629b7aa2630SJustin Bogner     return error(instrprof_error::bad_magic);
630b7aa2630SJustin Bogner 
631b7aa2630SJustin Bogner   // Read the version.
632140f4c4fSXinliang David Li   uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
63333c76c0cSRong Xu   if (GET_VERSION(FormatVersion) >
63433c76c0cSRong Xu       IndexedInstrProf::ProfVersion::CurrentVersion)
635b7aa2630SJustin Bogner     return error(instrprof_error::unsupported_version);
636b7aa2630SJustin Bogner 
6376c93ee8dSXinliang David Li   Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
638b7aa2630SJustin Bogner 
639b7aa2630SJustin Bogner   // Read the hash type and start offset.
640b7aa2630SJustin Bogner   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
641dab183edSXinliang David Li       endian::byte_swap<uint64_t, little>(Header->HashType));
642b7aa2630SJustin Bogner   if (HashType > IndexedInstrProf::HashT::Last)
643b7aa2630SJustin Bogner     return error(instrprof_error::unsupported_hash_type);
644dab183edSXinliang David Li 
645dab183edSXinliang David Li   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
646b7aa2630SJustin Bogner 
647b7aa2630SJustin Bogner   // The rest of the file is an on disk hash table.
648a28306dbSXinliang David Li   InstrProfReaderIndexBase *IndexPtr = nullptr;
649a28306dbSXinliang David Li   IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>(
650a28306dbSXinliang David Li       Start + HashOffset, Cur, Start, HashType, FormatVersion);
651a28306dbSXinliang David Li   Index.reset(IndexPtr);
652b7aa2630SJustin Bogner   return success();
653b7aa2630SJustin Bogner }
654b7aa2630SJustin Bogner 
655a716cc5cSXinliang David Li InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
656a716cc5cSXinliang David Li   if (Symtab.get())
657a716cc5cSXinliang David Li     return *Symtab.get();
658a716cc5cSXinliang David Li 
659a716cc5cSXinliang David Li   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
660a716cc5cSXinliang David Li   Index->populateSymtab(*NewSymtab.get());
661a716cc5cSXinliang David Li 
662a716cc5cSXinliang David Li   Symtab = std::move(NewSymtab);
663a716cc5cSXinliang David Li   return *Symtab.get();
664a716cc5cSXinliang David Li }
665a716cc5cSXinliang David Li 
6666aa216c2SXinliang David Li ErrorOr<InstrProfRecord>
6676aa216c2SXinliang David Li IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
6686aa216c2SXinliang David Li                                            uint64_t FuncHash) {
669140f4c4fSXinliang David Li   ArrayRef<InstrProfRecord> Data;
670a28306dbSXinliang David Li   std::error_code EC = Index->getRecords(FuncName, Data);
6714c3ab815SXinliang David Li   if (EC != instrprof_error::success)
6724c3ab815SXinliang David Li     return EC;
673821d7471SJustin Bogner   // Found it. Look for counters with the right hash.
6743a7d44cbSJustin Bogner   for (unsigned I = 0, E = Data.size(); I < E; ++I) {
675821d7471SJustin Bogner     // Check for a match and fill the vector if there is one.
6763a7d44cbSJustin Bogner     if (Data[I].Hash == FuncHash) {
6772004f003SXinliang David Li       return std::move(Data[I]);
678b7aa2630SJustin Bogner     }
679821d7471SJustin Bogner   }
680821d7471SJustin Bogner   return error(instrprof_error::hash_mismatch);
681821d7471SJustin Bogner }
682b7aa2630SJustin Bogner 
6836aa216c2SXinliang David Li std::error_code
6846aa216c2SXinliang David Li IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
6856aa216c2SXinliang David Li                                           std::vector<uint64_t> &Counts) {
6862004f003SXinliang David Li   ErrorOr<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
6876aa216c2SXinliang David Li   if (std::error_code EC = Record.getError())
6886aa216c2SXinliang David Li     return EC;
6892004f003SXinliang David Li 
6902004f003SXinliang David Li   Counts = Record.get().Counts;
6912004f003SXinliang David Li   return success();
6922004f003SXinliang David Li }
6932004f003SXinliang David Li 
694140f4c4fSXinliang David Li std::error_code IndexedInstrProfReader::readNextRecord(
695140f4c4fSXinliang David Li     InstrProfRecord &Record) {
6963a7d44cbSJustin Bogner   static unsigned RecordIndex = 0;
697140f4c4fSXinliang David Li 
698140f4c4fSXinliang David Li   ArrayRef<InstrProfRecord> Data;
699140f4c4fSXinliang David Li 
700a28306dbSXinliang David Li   std::error_code EC = Index->getRecords(Data);
7014c3ab815SXinliang David Li   if (EC != instrprof_error::success)
7024c3ab815SXinliang David Li     return error(EC);
703140f4c4fSXinliang David Li 
7043a7d44cbSJustin Bogner   Record = Data[RecordIndex++];
7053a7d44cbSJustin Bogner   if (RecordIndex >= Data.size()) {
706a28306dbSXinliang David Li     Index->advanceToNextKey();
7073a7d44cbSJustin Bogner     RecordIndex = 0;
708821d7471SJustin Bogner   }
709b7aa2630SJustin Bogner   return success();
710b7aa2630SJustin Bogner }
711