1e78d131aSEugene Zelenko //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
2f8d79198SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f8d79198SJustin Bogner //
7f8d79198SJustin Bogner //===----------------------------------------------------------------------===//
8f8d79198SJustin Bogner //
9f8d79198SJustin Bogner // This file contains support for reading profiling data for clang's
10f8d79198SJustin Bogner // instrumentation based PGO and coverage.
11f8d79198SJustin Bogner //
12f8d79198SJustin Bogner //===----------------------------------------------------------------------===//
13f8d79198SJustin Bogner 
146bda14b3SChandler Carruth #include "llvm/ProfileData/InstrProfReader.h"
15e78d131aSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
16ceed4eb1SRichard Smith #include "llvm/ADT/DenseMap.h"
170a446fd5SBenjamin Kramer #include "llvm/ADT/STLExtras.h"
18d10c995bSSam McCall #include "llvm/ADT/StringExtras.h"
19e78d131aSEugene Zelenko #include "llvm/ADT/StringRef.h"
20e78d131aSEugene Zelenko #include "llvm/IR/ProfileSummary.h"
21e78d131aSEugene Zelenko #include "llvm/ProfileData/InstrProf.h"
22e78d131aSEugene Zelenko #include "llvm/ProfileData/ProfileCommon.h"
23e78d131aSEugene Zelenko #include "llvm/Support/Endian.h"
24e78d131aSEugene Zelenko #include "llvm/Support/Error.h"
25e78d131aSEugene Zelenko #include "llvm/Support/ErrorOr.h"
26e78d131aSEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
27fd895bc8SGulfem Savrun Yeniceri #include "llvm/Support/SwapByteOrder.h"
28e50a3884SGulfem Savrun Yeniceri #include "llvm/Support/SymbolRemappingReader.h"
29e78d131aSEugene Zelenko #include <algorithm>
30e78d131aSEugene Zelenko #include <cctype>
31e78d131aSEugene Zelenko #include <cstddef>
32e78d131aSEugene Zelenko #include <cstdint>
33e78d131aSEugene Zelenko #include <limits>
34e78d131aSEugene Zelenko #include <memory>
35e78d131aSEugene Zelenko #include <system_error>
36e78d131aSEugene Zelenko #include <utility>
37e78d131aSEugene Zelenko #include <vector>
38f8d79198SJustin Bogner 
39f8d79198SJustin Bogner using namespace llvm;
40f8d79198SJustin Bogner 
419152fd17SVedant Kumar static Expected<std::unique_ptr<MemoryBuffer>>
420da23a27SBenjamin Kramer setupMemoryBuffer(const Twine &Path) {
43adf21f2aSRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
44e71994a2SJonathan Crowther       MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
45adf21f2aSRafael Espindola   if (std::error_code EC = BufferOrErr.getError())
469152fd17SVedant Kumar     return errorCodeToError(EC);
472b6c537bSJustin Bogner   return std::move(BufferOrErr.get());
48b7aa2630SJustin Bogner }
49b7aa2630SJustin Bogner 
509152fd17SVedant Kumar static Error initializeReader(InstrProfReader &Reader) {
51b7aa2630SJustin Bogner   return Reader.readHeader();
52b7aa2630SJustin Bogner }
53b7aa2630SJustin Bogner 
549152fd17SVedant Kumar Expected<std::unique_ptr<InstrProfReader>>
550da23a27SBenjamin Kramer InstrProfReader::create(const Twine &Path) {
56b7aa2630SJustin Bogner   // Set up the buffer to read.
57fcd55607SDiego Novillo   auto BufferOrError = setupMemoryBuffer(Path);
589152fd17SVedant Kumar   if (Error E = BufferOrError.takeError())
59c55cf4afSBill Wendling     return std::move(E);
602b6c537bSJustin Bogner   return InstrProfReader::create(std::move(BufferOrError.get()));
612b6c537bSJustin Bogner }
62f8d79198SJustin Bogner 
639152fd17SVedant Kumar Expected<std::unique_ptr<InstrProfReader>>
642b6c537bSJustin Bogner InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
65d6c15b66SVedant Kumar   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
669152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::too_large);
672b6c537bSJustin Bogner 
682c684cfdSRong Xu   if (Buffer->getBufferSize() == 0)
692c684cfdSRong Xu     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
702c684cfdSRong Xu 
71fcd55607SDiego Novillo   std::unique_ptr<InstrProfReader> Result;
7209a67f45SDuncan P. N. Exon Smith   // Create the reader.
73b7aa2630SJustin Bogner   if (IndexedInstrProfReader::hasFormat(*Buffer))
74b7aa2630SJustin Bogner     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
75b7aa2630SJustin Bogner   else if (RawInstrProfReader64::hasFormat(*Buffer))
764680361dSDuncan P. N. Exon Smith     Result.reset(new RawInstrProfReader64(std::move(Buffer)));
774680361dSDuncan P. N. Exon Smith   else if (RawInstrProfReader32::hasFormat(*Buffer))
784680361dSDuncan P. N. Exon Smith     Result.reset(new RawInstrProfReader32(std::move(Buffer)));
794f823667SNathan Slingerland   else if (TextInstrProfReader::hasFormat(*Buffer))
80911ced6bSNathan Slingerland     Result.reset(new TextInstrProfReader(std::move(Buffer)));
814f823667SNathan Slingerland   else
829152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
8309a67f45SDuncan P. N. Exon Smith 
84b7aa2630SJustin Bogner   // Initialize the reader and return the result.
859152fd17SVedant Kumar   if (Error E = initializeReader(*Result))
86c55cf4afSBill Wendling     return std::move(E);
87fcd55607SDiego Novillo 
88c55cf4afSBill Wendling   return std::move(Result);
89b7aa2630SJustin Bogner }
90b7aa2630SJustin Bogner 
919152fd17SVedant Kumar Expected<std::unique_ptr<IndexedInstrProfReader>>
92ceed4eb1SRichard Smith IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) {
93b7aa2630SJustin Bogner   // Set up the buffer to read.
94fcd55607SDiego Novillo   auto BufferOrError = setupMemoryBuffer(Path);
959152fd17SVedant Kumar   if (Error E = BufferOrError.takeError())
96c55cf4afSBill Wendling     return std::move(E);
97ceed4eb1SRichard Smith 
98ceed4eb1SRichard Smith   // Set up the remapping buffer if requested.
99ceed4eb1SRichard Smith   std::unique_ptr<MemoryBuffer> RemappingBuffer;
100ceed4eb1SRichard Smith   std::string RemappingPathStr = RemappingPath.str();
101ceed4eb1SRichard Smith   if (!RemappingPathStr.empty()) {
102ceed4eb1SRichard Smith     auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr);
103ceed4eb1SRichard Smith     if (Error E = RemappingBufferOrError.takeError())
104c55cf4afSBill Wendling       return std::move(E);
105ceed4eb1SRichard Smith     RemappingBuffer = std::move(RemappingBufferOrError.get());
106ceed4eb1SRichard Smith   }
107ceed4eb1SRichard Smith 
108ceed4eb1SRichard Smith   return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
109ceed4eb1SRichard Smith                                         std::move(RemappingBuffer));
1102b6c537bSJustin Bogner }
111b7aa2630SJustin Bogner 
1129152fd17SVedant Kumar Expected<std::unique_ptr<IndexedInstrProfReader>>
113ceed4eb1SRichard Smith IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
114ceed4eb1SRichard Smith                                std::unique_ptr<MemoryBuffer> RemappingBuffer) {
115d6c15b66SVedant Kumar   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
1169152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::too_large);
117ab89ed7dSJustin Bogner 
118b7aa2630SJustin Bogner   // Create the reader.
119b7aa2630SJustin Bogner   if (!IndexedInstrProfReader::hasFormat(*Buffer))
1209152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::bad_magic);
1210eaee545SJonas Devlieghere   auto Result = std::make_unique<IndexedInstrProfReader>(
122ceed4eb1SRichard Smith       std::move(Buffer), std::move(RemappingBuffer));
123b7aa2630SJustin Bogner 
124b7aa2630SJustin Bogner   // Initialize the reader and return the result.
1259152fd17SVedant Kumar   if (Error E = initializeReader(*Result))
126c55cf4afSBill Wendling     return std::move(E);
127ab89ed7dSJustin Bogner 
128c55cf4afSBill Wendling   return std::move(Result);
129f8d79198SJustin Bogner }
130f8d79198SJustin Bogner 
131f8d79198SJustin Bogner void InstrProfIterator::Increment() {
1329152fd17SVedant Kumar   if (auto E = Reader->readNextRecord(Record)) {
1339152fd17SVedant Kumar     // Handle errors in the reader.
1349152fd17SVedant Kumar     InstrProfError::take(std::move(E));
135f8d79198SJustin Bogner     *this = InstrProfIterator();
136f8d79198SJustin Bogner   }
1379152fd17SVedant Kumar }
138f8d79198SJustin Bogner 
1394f823667SNathan Slingerland bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
1404f823667SNathan Slingerland   // Verify that this really looks like plain ASCII text by checking a
1414f823667SNathan Slingerland   // 'reasonable' number of characters (up to profile magic size).
1424f823667SNathan Slingerland   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
1434f823667SNathan Slingerland   StringRef buffer = Buffer.getBufferStart();
1442491dd11SVedant Kumar   return count == 0 ||
1452491dd11SVedant Kumar          std::all_of(buffer.begin(), buffer.begin() + count,
146d10c995bSSam McCall                      [](char c) { return isPrint(c) || isSpace(c); });
1474f823667SNathan Slingerland }
1484f823667SNathan Slingerland 
14933c76c0cSRong Xu // Read the profile variant flag from the header: ":FE" means this is a FE
15033c76c0cSRong Xu // generated profile. ":IR" means this is an IR level profile. Other strings
15133c76c0cSRong Xu // with a leading ':' will be reported an error format.
1529152fd17SVedant Kumar Error TextInstrProfReader::readHeader() {
153a716cc5cSXinliang David Li   Symtab.reset(new InstrProfSymtab());
15433c76c0cSRong Xu   bool IsIRInstr = false;
15550da55a5SRong Xu   bool IsEntryFirst = false;
15650da55a5SRong Xu   bool IsCS = false;
15750da55a5SRong Xu 
15850da55a5SRong Xu   while (Line->startswith(":")) {
15950da55a5SRong Xu     StringRef Str = Line->substr(1);
16042f74e82SMartin Storsjö     if (Str.equals_insensitive("ir"))
16133c76c0cSRong Xu       IsIRInstr = true;
16242f74e82SMartin Storsjö     else if (Str.equals_insensitive("fe"))
16333c76c0cSRong Xu       IsIRInstr = false;
16442f74e82SMartin Storsjö     else if (Str.equals_insensitive("csir")) {
165a6ff69f6SRong Xu       IsIRInstr = true;
16650da55a5SRong Xu       IsCS = true;
16742f74e82SMartin Storsjö     } else if (Str.equals_insensitive("entry_first"))
16850da55a5SRong Xu       IsEntryFirst = true;
16942f74e82SMartin Storsjö     else if (Str.equals_insensitive("not_entry_first"))
17050da55a5SRong Xu       IsEntryFirst = false;
17150da55a5SRong Xu     else
1729152fd17SVedant Kumar       return error(instrprof_error::bad_header);
17333c76c0cSRong Xu     ++Line;
17450da55a5SRong Xu   }
17533c76c0cSRong Xu   IsIRLevelProfile = IsIRInstr;
17650da55a5SRong Xu   InstrEntryBBEnabled = IsEntryFirst;
17750da55a5SRong Xu   HasCSIRLevelProfile = IsCS;
178a716cc5cSXinliang David Li   return success();
179a716cc5cSXinliang David Li }
180a716cc5cSXinliang David Li 
1819152fd17SVedant Kumar Error
182e3bf4fd3SXinliang David Li TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
183e3bf4fd3SXinliang David Li 
184e3bf4fd3SXinliang David Li #define CHECK_LINE_END(Line)                                                   \
185e3bf4fd3SXinliang David Li   if (Line.is_at_end())                                                        \
186e3bf4fd3SXinliang David Li     return error(instrprof_error::truncated);
187e3bf4fd3SXinliang David Li #define READ_NUM(Str, Dst)                                                     \
188e3bf4fd3SXinliang David Li   if ((Str).getAsInteger(10, (Dst)))                                           \
189e3bf4fd3SXinliang David Li     return error(instrprof_error::malformed);
190e3bf4fd3SXinliang David Li #define VP_READ_ADVANCE(Val)                                                   \
191e3bf4fd3SXinliang David Li   CHECK_LINE_END(Line);                                                        \
192e3bf4fd3SXinliang David Li   uint32_t Val;                                                                \
193e3bf4fd3SXinliang David Li   READ_NUM((*Line), (Val));                                                    \
194e3bf4fd3SXinliang David Li   Line++;
195e3bf4fd3SXinliang David Li 
196e3bf4fd3SXinliang David Li   if (Line.is_at_end())
197e3bf4fd3SXinliang David Li     return success();
198a716cc5cSXinliang David Li 
199e3bf4fd3SXinliang David Li   uint32_t NumValueKinds;
200e3bf4fd3SXinliang David Li   if (Line->getAsInteger(10, NumValueKinds)) {
201e3bf4fd3SXinliang David Li     // No value profile data
202e3bf4fd3SXinliang David Li     return success();
203e3bf4fd3SXinliang David Li   }
204e3bf4fd3SXinliang David Li   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
205ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed,
206ee88b8d6SGulfem Savrun Yeniceri                  "number of value kinds is invalid");
207e3bf4fd3SXinliang David Li   Line++;
208e3bf4fd3SXinliang David Li 
209e3bf4fd3SXinliang David Li   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
210e3bf4fd3SXinliang David Li     VP_READ_ADVANCE(ValueKind);
211e3bf4fd3SXinliang David Li     if (ValueKind > IPVK_Last)
212ee88b8d6SGulfem Savrun Yeniceri       return error(instrprof_error::malformed, "value kind is invalid");
213ee88b8d6SGulfem Savrun Yeniceri     ;
214e3bf4fd3SXinliang David Li     VP_READ_ADVANCE(NumValueSites);
215e3bf4fd3SXinliang David Li     if (!NumValueSites)
216e3bf4fd3SXinliang David Li       continue;
217e3bf4fd3SXinliang David Li 
218e3bf4fd3SXinliang David Li     Record.reserveSites(VK, NumValueSites);
219e3bf4fd3SXinliang David Li     for (uint32_t S = 0; S < NumValueSites; S++) {
220e3bf4fd3SXinliang David Li       VP_READ_ADVANCE(NumValueData);
221e3bf4fd3SXinliang David Li 
222e3bf4fd3SXinliang David Li       std::vector<InstrProfValueData> CurrentValues;
223e3bf4fd3SXinliang David Li       for (uint32_t V = 0; V < NumValueData; V++) {
224e3bf4fd3SXinliang David Li         CHECK_LINE_END(Line);
22535723644SRong Xu         std::pair<StringRef, StringRef> VD = Line->rsplit(':');
226e3bf4fd3SXinliang David Li         uint64_t TakenCount, Value;
227cbb11407SRong Xu         if (ValueKind == IPVK_IndirectCallTarget) {
22829a21babSMircea Trofin           if (InstrProfSymtab::isExternalSymbol(VD.first)) {
22929a21babSMircea Trofin             Value = 0;
23029a21babSMircea Trofin           } else {
231b5794ca9SVedant Kumar             if (Error E = Symtab->addFuncName(VD.first))
232b5794ca9SVedant Kumar               return E;
233a716cc5cSXinliang David Li             Value = IndexedInstrProf::ComputeHash(VD.first);
23429a21babSMircea Trofin           }
235a716cc5cSXinliang David Li         } else {
236e3bf4fd3SXinliang David Li           READ_NUM(VD.first, Value);
237e3bf4fd3SXinliang David Li         }
238a716cc5cSXinliang David Li         READ_NUM(VD.second, TakenCount);
239e3bf4fd3SXinliang David Li         CurrentValues.push_back({Value, TakenCount});
240e3bf4fd3SXinliang David Li         Line++;
241e3bf4fd3SXinliang David Li       }
242cbb11407SRong Xu       Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
243cbb11407SRong Xu                           nullptr);
244e3bf4fd3SXinliang David Li     }
245e3bf4fd3SXinliang David Li   }
246e3bf4fd3SXinliang David Li   return success();
247e3bf4fd3SXinliang David Li 
248e3bf4fd3SXinliang David Li #undef CHECK_LINE_END
249e3bf4fd3SXinliang David Li #undef READ_NUM
250e3bf4fd3SXinliang David Li #undef VP_READ_ADVANCE
251e3bf4fd3SXinliang David Li }
252e3bf4fd3SXinliang David Li 
253cf9d52c6SDavid Blaikie Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
254cf36a366SJustin Bogner   // Skip empty lines and comments.
255cf36a366SJustin Bogner   while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
256f8d79198SJustin Bogner     ++Line;
257f8d79198SJustin Bogner   // If we hit EOF while looking for a name, we're done.
258a716cc5cSXinliang David Li   if (Line.is_at_end()) {
259f8d79198SJustin Bogner     return error(instrprof_error::eof);
260a716cc5cSXinliang David Li   }
261f8d79198SJustin Bogner 
262f8d79198SJustin Bogner   // Read the function name.
263f8d79198SJustin Bogner   Record.Name = *Line++;
264b5794ca9SVedant Kumar   if (Error E = Symtab->addFuncName(Record.Name))
26529a21babSMircea Trofin     return error(std::move(E));
266f8d79198SJustin Bogner 
267f8d79198SJustin Bogner   // Read the function hash.
268f8d79198SJustin Bogner   if (Line.is_at_end())
269f8d79198SJustin Bogner     return error(instrprof_error::truncated);
270f95ca075SJustin Bogner   if ((Line++)->getAsInteger(0, Record.Hash))
271ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed,
272ee88b8d6SGulfem Savrun Yeniceri                  "function hash is not a valid integer");
273f8d79198SJustin Bogner 
274f8d79198SJustin Bogner   // Read the number of counters.
275f8d79198SJustin Bogner   uint64_t NumCounters;
276f8d79198SJustin Bogner   if (Line.is_at_end())
277f8d79198SJustin Bogner     return error(instrprof_error::truncated);
278f8d79198SJustin Bogner   if ((Line++)->getAsInteger(10, NumCounters))
279ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed,
280ee88b8d6SGulfem Savrun Yeniceri                  "number of counters is not a valid integer");
281b59d7c73SJustin Bogner   if (NumCounters == 0)
282ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed, "number of counters is zero");
283f8d79198SJustin Bogner 
284f8d79198SJustin Bogner   // Read each counter and fill our internal storage with the values.
2856241c2a6SRong Xu   Record.Clear();
2863a7d44cbSJustin Bogner   Record.Counts.reserve(NumCounters);
287f8d79198SJustin Bogner   for (uint64_t I = 0; I < NumCounters; ++I) {
288f8d79198SJustin Bogner     if (Line.is_at_end())
289f8d79198SJustin Bogner       return error(instrprof_error::truncated);
290f8d79198SJustin Bogner     uint64_t Count;
291f8d79198SJustin Bogner     if ((Line++)->getAsInteger(10, Count))
292ee88b8d6SGulfem Savrun Yeniceri       return error(instrprof_error::malformed, "count is invalid");
2933a7d44cbSJustin Bogner     Record.Counts.push_back(Count);
294f8d79198SJustin Bogner   }
295f8d79198SJustin Bogner 
296e3bf4fd3SXinliang David Li   // Check if value profile data exists and read it if so.
2979152fd17SVedant Kumar   if (Error E = readValueProfileData(Record))
29829a21babSMircea Trofin     return error(std::move(E));
299e3bf4fd3SXinliang David Li 
300f8d79198SJustin Bogner   return success();
301f8d79198SJustin Bogner }
30224b4b653SDuncan P. N. Exon Smith 
3034680361dSDuncan P. N. Exon Smith template <class IntPtrT>
3044680361dSDuncan P. N. Exon Smith bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
305d7d83477SDuncan P. N. Exon Smith   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
3064680361dSDuncan P. N. Exon Smith     return false;
307d7d83477SDuncan P. N. Exon Smith   uint64_t Magic =
308d7d83477SDuncan P. N. Exon Smith     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
309dab183edSXinliang David Li   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
310dab183edSXinliang David Li          sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
3114680361dSDuncan P. N. Exon Smith }
3124680361dSDuncan P. N. Exon Smith 
3134680361dSDuncan P. N. Exon Smith template <class IntPtrT>
3149152fd17SVedant Kumar Error RawInstrProfReader<IntPtrT>::readHeader() {
31509a67f45SDuncan P. N. Exon Smith   if (!hasFormat(*DataBuffer))
31609a67f45SDuncan P. N. Exon Smith     return error(instrprof_error::bad_magic);
317dab183edSXinliang David Li   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
318531bb481SDuncan P. N. Exon Smith     return error(instrprof_error::bad_header);
319dab183edSXinliang David Li   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
320dab183edSXinliang David Li       DataBuffer->getBufferStart());
321dab183edSXinliang David Li   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
32224b4b653SDuncan P. N. Exon Smith   return readHeader(*Header);
32324b4b653SDuncan P. N. Exon Smith }
32424b4b653SDuncan P. N. Exon Smith 
325a119f323SJustin Bogner template <class IntPtrT>
3269152fd17SVedant Kumar Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
327a119f323SJustin Bogner   const char *End = DataBuffer->getBufferEnd();
328a119f323SJustin Bogner   // Skip zero padding between profiles.
329a119f323SJustin Bogner   while (CurrentPos != End && *CurrentPos == 0)
330a119f323SJustin Bogner     ++CurrentPos;
331a119f323SJustin Bogner   // If there's nothing left, we're done.
332a119f323SJustin Bogner   if (CurrentPos == End)
3339152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::eof);
334a119f323SJustin Bogner   // If there isn't enough space for another header, this is probably just
335a119f323SJustin Bogner   // garbage at the end of the file.
336dab183edSXinliang David Li   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
337ee88b8d6SGulfem Savrun Yeniceri     return make_error<InstrProfError>(instrprof_error::malformed,
338ee88b8d6SGulfem Savrun Yeniceri                                       "not enough space for another header");
33954b11282SJustin Bogner   // The writer ensures each profile is padded to start at an aligned address.
340b2505005SBenjamin Kramer   if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
341ee88b8d6SGulfem Savrun Yeniceri     return make_error<InstrProfError>(instrprof_error::malformed,
342ee88b8d6SGulfem Savrun Yeniceri                                       "insufficient padding");
343a119f323SJustin Bogner   // The magic should have the same byte order as in the previous header.
344a119f323SJustin Bogner   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
345dab183edSXinliang David Li   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
3469152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::bad_magic);
347a119f323SJustin Bogner 
348a119f323SJustin Bogner   // There's another profile to read, so we need to process the header.
349dab183edSXinliang David Li   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
350a119f323SJustin Bogner   return readHeader(*Header);
351a119f323SJustin Bogner }
352a119f323SJustin Bogner 
3534680361dSDuncan P. N. Exon Smith template <class IntPtrT>
3549152fd17SVedant Kumar Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
3559152fd17SVedant Kumar   if (Error E = Symtab.create(StringRef(NamesStart, NamesSize)))
3569152fd17SVedant Kumar     return error(std::move(E));
357a716cc5cSXinliang David Li   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
358a716cc5cSXinliang David Li     const IntPtrT FPtr = swap(I->FunctionPointer);
359a716cc5cSXinliang David Li     if (!FPtr)
360a716cc5cSXinliang David Li       continue;
361a82d6c0aSXinliang David Li     Symtab.mapAddress(FPtr, I->NameRef);
362a716cc5cSXinliang David Li   }
363e44482feSVedant Kumar   return success();
364a716cc5cSXinliang David Li }
365a716cc5cSXinliang David Li 
366a716cc5cSXinliang David Li template <class IntPtrT>
3679152fd17SVedant Kumar Error RawInstrProfReader<IntPtrT>::readHeader(
3689152fd17SVedant Kumar     const RawInstrProf::Header &Header) {
36933c76c0cSRong Xu   Version = swap(Header.Version);
37033c76c0cSRong Xu   if (GET_VERSION(Version) != RawInstrProf::Version)
37124b4b653SDuncan P. N. Exon Smith     return error(instrprof_error::unsupported_version);
37224b4b653SDuncan P. N. Exon Smith 
37383302c84SPetr Hosek   BinaryIdsSize = swap(Header.BinaryIdsSize);
374b9f547e8SLeonard Chan   if (BinaryIdsSize % sizeof(uint64_t))
375b9f547e8SLeonard Chan     return error(instrprof_error::bad_header);
376b9f547e8SLeonard Chan 
37724b4b653SDuncan P. N. Exon Smith   CountersDelta = swap(Header.CountersDelta);
37824b4b653SDuncan P. N. Exon Smith   NamesDelta = swap(Header.NamesDelta);
37924b4b653SDuncan P. N. Exon Smith   auto DataSize = swap(Header.DataSize);
380d889d1efSVedant Kumar   auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
38124b4b653SDuncan P. N. Exon Smith   auto CountersSize = swap(Header.CountersSize);
382d889d1efSVedant Kumar   auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
383a82d6c0aSXinliang David Li   NamesSize = swap(Header.NamesSize);
3846fac1741SBetul Buyukkurt   ValueKindLast = swap(Header.ValueKindLast);
3856fac1741SBetul Buyukkurt 
3866fac1741SBetul Buyukkurt   auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
3876fac1741SBetul Buyukkurt   auto PaddingSize = getNumPaddingBytes(NamesSize);
38824b4b653SDuncan P. N. Exon Smith 
389e50a3884SGulfem Savrun Yeniceri   // Profile data starts after profile header and binary ids if exist.
390e50a3884SGulfem Savrun Yeniceri   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize;
391d889d1efSVedant Kumar   ptrdiff_t CountersOffset =
392d889d1efSVedant Kumar       DataOffset + DataSizeInBytes + PaddingBytesBeforeCounters;
393d889d1efSVedant Kumar   ptrdiff_t NamesOffset = CountersOffset + (sizeof(uint64_t) * CountersSize) +
394d889d1efSVedant Kumar                           PaddingBytesAfterCounters;
3956fac1741SBetul Buyukkurt   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
39624b4b653SDuncan P. N. Exon Smith 
397a119f323SJustin Bogner   auto *Start = reinterpret_cast<const char *>(&Header);
398188a7c5fSXinliang David Li   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
399531bb481SDuncan P. N. Exon Smith     return error(instrprof_error::bad_header);
40024b4b653SDuncan P. N. Exon Smith 
401dab183edSXinliang David Li   Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
402dab183edSXinliang David Li       Start + DataOffset);
40324b4b653SDuncan P. N. Exon Smith   DataEnd = Data + DataSize;
404e50a3884SGulfem Savrun Yeniceri 
405e50a3884SGulfem Savrun Yeniceri   // Binary ids start just after the header.
406e50a3884SGulfem Savrun Yeniceri   BinaryIdsStart =
407e50a3884SGulfem Savrun Yeniceri       reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
408d7d83477SDuncan P. N. Exon Smith   CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
409d7d83477SDuncan P. N. Exon Smith   NamesStart = Start + NamesOffset;
4106fac1741SBetul Buyukkurt   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
41124b4b653SDuncan P. N. Exon Smith 
412b9f547e8SLeonard Chan   const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
413b9f547e8SLeonard Chan   if (BinaryIdsStart + BinaryIdsSize > BufferEnd)
414b9f547e8SLeonard Chan     return error(instrprof_error::bad_header);
415b9f547e8SLeonard Chan 
4160eaee545SJonas Devlieghere   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
4179152fd17SVedant Kumar   if (Error E = createSymtab(*NewSymtab.get()))
4189152fd17SVedant Kumar     return E;
419e44482feSVedant Kumar 
420a716cc5cSXinliang David Li   Symtab = std::move(NewSymtab);
42124b4b653SDuncan P. N. Exon Smith   return success();
42224b4b653SDuncan P. N. Exon Smith }
42324b4b653SDuncan P. N. Exon Smith 
4244680361dSDuncan P. N. Exon Smith template <class IntPtrT>
425cf9d52c6SDavid Blaikie Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
426a82d6c0aSXinliang David Li   Record.Name = getName(Data->NameRef);
427cf4a128cSXinliang David Li   return success();
428cf4a128cSXinliang David Li }
429cf4a128cSXinliang David Li 
430cf4a128cSXinliang David Li template <class IntPtrT>
431cf9d52c6SDavid Blaikie Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
432cf4a128cSXinliang David Li   Record.Hash = swap(Data->FuncHash);
433cf4a128cSXinliang David Li   return success();
434cf4a128cSXinliang David Li }
435cf4a128cSXinliang David Li 
436cf4a128cSXinliang David Li template <class IntPtrT>
4379152fd17SVedant Kumar Error RawInstrProfReader<IntPtrT>::readRawCounts(
438cf4a128cSXinliang David Li     InstrProfRecord &Record) {
439b59d7c73SJustin Bogner   uint32_t NumCounters = swap(Data->NumCounters);
440b59d7c73SJustin Bogner   if (NumCounters == 0)
441ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed, "number of counters is zero");
442cf4a128cSXinliang David Li 
443ee88b8d6SGulfem Savrun Yeniceri   IntPtrT CounterPtr = Data->CounterPtr;
444cf4a128cSXinliang David Li   auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
44595fb23abSVedant Kumar   ptrdiff_t MaxNumCounters = NamesStartAsCounter - CountersStart;
44624b4b653SDuncan P. N. Exon Smith 
44795fb23abSVedant Kumar   // Check bounds. Note that the counter pointer embedded in the data record
44895fb23abSVedant Kumar   // may itself be corrupt.
449db817d15SAlexandre Ganea   if (MaxNumCounters < 0 || NumCounters > (uint32_t)MaxNumCounters)
450ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed,
451ee88b8d6SGulfem Savrun Yeniceri                  "counter pointer is out of bounds");
452a1532ed2SFangrui Song 
453a1532ed2SFangrui Song   // We need to compute the in-buffer counter offset from the in-memory address
454a1532ed2SFangrui Song   // distance. The initial CountersDelta is the in-memory address difference
455a1532ed2SFangrui Song   // start(__llvm_prf_cnts)-start(__llvm_prf_data), so SrcData->CounterPtr -
456a1532ed2SFangrui Song   // CountersDelta computes the offset into the in-buffer counter section.
457a1532ed2SFangrui Song   //
458a1532ed2SFangrui Song   // CountersDelta decreases as we advance to the next data record.
45995fb23abSVedant Kumar   ptrdiff_t CounterOffset = getCounterOffset(CounterPtr);
460a1532ed2SFangrui Song   CountersDelta -= sizeof(*Data);
461ee88b8d6SGulfem Savrun Yeniceri   if (CounterOffset < 0)
462ee88b8d6SGulfem Savrun Yeniceri     return error(
463ee88b8d6SGulfem Savrun Yeniceri         instrprof_error::malformed,
464126e7611SGulfem Savrun Yeniceri         ("counter offset " + Twine(CounterOffset) + " is negative").str());
465ee88b8d6SGulfem Savrun Yeniceri 
466ee88b8d6SGulfem Savrun Yeniceri   if (CounterOffset > MaxNumCounters)
467ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed,
468126e7611SGulfem Savrun Yeniceri                  ("counter offset " + Twine(CounterOffset) +
469126e7611SGulfem Savrun Yeniceri                   " is greater than the maximum number of counters " +
470126e7611SGulfem Savrun Yeniceri                   Twine((uint32_t)MaxNumCounters))
471ee88b8d6SGulfem Savrun Yeniceri                      .str());
472ee88b8d6SGulfem Savrun Yeniceri 
473ee88b8d6SGulfem Savrun Yeniceri   if (((uint32_t)CounterOffset + NumCounters) > (uint32_t)MaxNumCounters)
474ee88b8d6SGulfem Savrun Yeniceri     return error(instrprof_error::malformed,
475126e7611SGulfem Savrun Yeniceri                  ("number of counters " +
476126e7611SGulfem Savrun Yeniceri                   Twine(((uint32_t)CounterOffset + NumCounters)) +
477126e7611SGulfem Savrun Yeniceri                   " is greater than the maximum number of counters " +
478126e7611SGulfem Savrun Yeniceri                   Twine((uint32_t)MaxNumCounters))
479ee88b8d6SGulfem Savrun Yeniceri                      .str());
48095fb23abSVedant Kumar 
48195fb23abSVedant Kumar   auto RawCounts = makeArrayRef(getCounter(CounterOffset), NumCounters);
48224b4b653SDuncan P. N. Exon Smith 
48324b4b653SDuncan P. N. Exon Smith   if (ShouldSwapBytes) {
4843a7d44cbSJustin Bogner     Record.Counts.clear();
4853a7d44cbSJustin Bogner     Record.Counts.reserve(RawCounts.size());
48624b4b653SDuncan P. N. Exon Smith     for (uint64_t Count : RawCounts)
4873a7d44cbSJustin Bogner       Record.Counts.push_back(swap(Count));
48824b4b653SDuncan P. N. Exon Smith   } else
48924b4b653SDuncan P. N. Exon Smith     Record.Counts = RawCounts;
49024b4b653SDuncan P. N. Exon Smith 
491cf4a128cSXinliang David Li   return success();
492cf4a128cSXinliang David Li }
493cf4a128cSXinliang David Li 
494cf4a128cSXinliang David Li template <class IntPtrT>
4959152fd17SVedant Kumar Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
4969152fd17SVedant Kumar     InstrProfRecord &Record) {
4976fac1741SBetul Buyukkurt   Record.clearValueData();
498d922c26cSXinliang David Li   CurValueDataSize = 0;
499d922c26cSXinliang David Li   // Need to match the logic in value profile dumper code in compiler-rt:
500d922c26cSXinliang David Li   uint32_t NumValueKinds = 0;
501d922c26cSXinliang David Li   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
502d922c26cSXinliang David Li     NumValueKinds += (Data->NumValueSites[I] != 0);
503d922c26cSXinliang David Li 
504d922c26cSXinliang David Li   if (!NumValueKinds)
5056fac1741SBetul Buyukkurt     return success();
5066fac1741SBetul Buyukkurt 
5079152fd17SVedant Kumar   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
508188a7c5fSXinliang David Li       ValueProfData::getValueProfData(
509188a7c5fSXinliang David Li           ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
51001cb9bd7SXinliang David Li           getDataEndianness());
5116fac1741SBetul Buyukkurt 
5129152fd17SVedant Kumar   if (Error E = VDataPtrOrErr.takeError())
5139152fd17SVedant Kumar     return E;
5146fac1741SBetul Buyukkurt 
5152f36f059SAdam Nemet   // Note that besides deserialization, this also performs the conversion for
5162f36f059SAdam Nemet   // indirect call targets.  The function pointers from the raw profile are
5172f36f059SAdam Nemet   // remapped into function name hashes.
518556f8f6aSMircea Trofin   VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
519d922c26cSXinliang David Li   CurValueDataSize = VDataPtrOrErr.get()->getSize();
5206fac1741SBetul Buyukkurt   return success();
5216fac1741SBetul Buyukkurt }
5226fac1741SBetul Buyukkurt 
5236fac1741SBetul Buyukkurt template <class IntPtrT>
524cf9d52c6SDavid Blaikie Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
525cf4a128cSXinliang David Li   if (atEnd())
526188a7c5fSXinliang David Li     // At this point, ValueDataStart field points to the next header.
5279152fd17SVedant Kumar     if (Error E = readNextHeader(getNextHeaderPos()))
5285b63803dSMircea Trofin       return error(std::move(E));
529cf4a128cSXinliang David Li 
530cf4a128cSXinliang David Li   // Read name ad set it in Record.
5319152fd17SVedant Kumar   if (Error E = readName(Record))
5325b63803dSMircea Trofin     return error(std::move(E));
533cf4a128cSXinliang David Li 
534cf4a128cSXinliang David Li   // Read FuncHash and set it in Record.
5359152fd17SVedant Kumar   if (Error E = readFuncHash(Record))
5365b63803dSMircea Trofin     return error(std::move(E));
537cf4a128cSXinliang David Li 
538cf4a128cSXinliang David Li   // Read raw counts and set Record.
5399152fd17SVedant Kumar   if (Error E = readRawCounts(Record))
5405b63803dSMircea Trofin     return error(std::move(E));
541cf4a128cSXinliang David Li 
5426fac1741SBetul Buyukkurt   // Read value data and set Record.
5439152fd17SVedant Kumar   if (Error E = readValueProfilingData(Record))
5445b63803dSMircea Trofin     return error(std::move(E));
5456fac1741SBetul Buyukkurt 
54624b4b653SDuncan P. N. Exon Smith   // Iterate.
547cf4a128cSXinliang David Li   advanceData();
54824b4b653SDuncan P. N. Exon Smith   return success();
54924b4b653SDuncan P. N. Exon Smith }
5504680361dSDuncan P. N. Exon Smith 
551b9f547e8SLeonard Chan static size_t RoundUp(size_t size, size_t align) {
552b9f547e8SLeonard Chan   return (size + align - 1) & ~(align - 1);
553b9f547e8SLeonard Chan }
554b9f547e8SLeonard Chan 
555e50a3884SGulfem Savrun Yeniceri template <class IntPtrT>
556e50a3884SGulfem Savrun Yeniceri Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) {
557e50a3884SGulfem Savrun Yeniceri   if (BinaryIdsSize == 0)
558e50a3884SGulfem Savrun Yeniceri     return success();
559e50a3884SGulfem Savrun Yeniceri 
560e50a3884SGulfem Savrun Yeniceri   OS << "Binary IDs: \n";
561e50a3884SGulfem Savrun Yeniceri   const uint8_t *BI = BinaryIdsStart;
562b9f547e8SLeonard Chan   const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
563b9f547e8SLeonard Chan   while (BI < BIEnd) {
564b9f547e8SLeonard Chan     size_t Remaining = BIEnd - BI;
565b9f547e8SLeonard Chan 
566b9f547e8SLeonard Chan     // There should be enough left to read the binary ID size field.
567b9f547e8SLeonard Chan     if (Remaining < sizeof(uint64_t))
568ee88b8d6SGulfem Savrun Yeniceri       return make_error<InstrProfError>(
569ee88b8d6SGulfem Savrun Yeniceri           instrprof_error::malformed,
570ee88b8d6SGulfem Savrun Yeniceri           "not enough data to read binary id length");
571b9f547e8SLeonard Chan 
572e50a3884SGulfem Savrun Yeniceri     uint64_t BinaryIdLen = swap(*reinterpret_cast<const uint64_t *>(BI));
573b9f547e8SLeonard Chan 
574b9f547e8SLeonard Chan     // There should be enough left to read the binary ID size field, and the
575b9f547e8SLeonard Chan     // binary ID.
576b9f547e8SLeonard Chan     if (Remaining < sizeof(BinaryIdLen) + BinaryIdLen)
577ee88b8d6SGulfem Savrun Yeniceri       return make_error<InstrProfError>(
578ee88b8d6SGulfem Savrun Yeniceri           instrprof_error::malformed, "not enough data to read binary id data");
579b9f547e8SLeonard Chan 
580e50a3884SGulfem Savrun Yeniceri     // Increment by binary id length data type size.
581e50a3884SGulfem Savrun Yeniceri     BI += sizeof(BinaryIdLen);
582e50a3884SGulfem Savrun Yeniceri     if (BI > (const uint8_t *)DataBuffer->getBufferEnd())
583ee88b8d6SGulfem Savrun Yeniceri       return make_error<InstrProfError>(
584ee88b8d6SGulfem Savrun Yeniceri           instrprof_error::malformed,
585ee88b8d6SGulfem Savrun Yeniceri           "binary id that is read is bigger than buffer size");
586e50a3884SGulfem Savrun Yeniceri 
587e50a3884SGulfem Savrun Yeniceri     for (uint64_t I = 0; I < BinaryIdLen; I++)
588e50a3884SGulfem Savrun Yeniceri       OS << format("%02x", BI[I]);
589e50a3884SGulfem Savrun Yeniceri     OS << "\n";
590e50a3884SGulfem Savrun Yeniceri 
591b9f547e8SLeonard Chan     // Increment by binary id data length, rounded to the next 8 bytes. This
592b9f547e8SLeonard Chan     // accounts for the zero-padding after each build ID.
593b9f547e8SLeonard Chan     BI += RoundUp(BinaryIdLen, sizeof(uint64_t));
594e50a3884SGulfem Savrun Yeniceri     if (BI > (const uint8_t *)DataBuffer->getBufferEnd())
595e50a3884SGulfem Savrun Yeniceri       return make_error<InstrProfError>(instrprof_error::malformed);
596e50a3884SGulfem Savrun Yeniceri   }
597e50a3884SGulfem Savrun Yeniceri 
598e50a3884SGulfem Savrun Yeniceri   return success();
599e50a3884SGulfem Savrun Yeniceri }
600e50a3884SGulfem Savrun Yeniceri 
6014680361dSDuncan P. N. Exon Smith namespace llvm {
602e78d131aSEugene Zelenko 
6034680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint32_t>;
6044680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint64_t>;
605e78d131aSEugene Zelenko 
606e78d131aSEugene Zelenko } // end namespace llvm
607b7aa2630SJustin Bogner 
608b5d368e8SJustin Bogner InstrProfLookupTrait::hash_value_type
609b5d368e8SJustin Bogner InstrProfLookupTrait::ComputeHash(StringRef K) {
610b5d368e8SJustin Bogner   return IndexedInstrProf::ComputeHash(HashType, K);
611b5d368e8SJustin Bogner }
612b5d368e8SJustin Bogner 
61372208a82SEugene Zelenko using data_type = InstrProfLookupTrait::data_type;
61472208a82SEugene Zelenko using offset_type = InstrProfLookupTrait::offset_type;
6153a7d44cbSJustin Bogner 
616be969c29SXinliang David Li bool InstrProfLookupTrait::readValueProfilingData(
6179e9a057aSJustin Bogner     const unsigned char *&D, const unsigned char *const End) {
6189152fd17SVedant Kumar   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
61999556877SXinliang David Li       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
6209e9a057aSJustin Bogner 
6219152fd17SVedant Kumar   if (VDataPtrOrErr.takeError())
6229e9a057aSJustin Bogner     return false;
6232004f003SXinliang David Li 
624a716cc5cSXinliang David Li   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
625ee415895SXinliang David Li   D += VDataPtrOrErr.get()->TotalSize;
6269e9a057aSJustin Bogner 
6279e9a057aSJustin Bogner   return true;
6289e9a057aSJustin Bogner }
6299e9a057aSJustin Bogner 
6303a7d44cbSJustin Bogner data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
6313a7d44cbSJustin Bogner                                          offset_type N) {
632e78d131aSEugene Zelenko   using namespace support;
633e78d131aSEugene Zelenko 
6343a7d44cbSJustin Bogner   // Check if the data is corrupt. If so, don't try to read it.
6353a7d44cbSJustin Bogner   if (N % sizeof(uint64_t))
6363a7d44cbSJustin Bogner     return data_type();
6373a7d44cbSJustin Bogner 
6383a7d44cbSJustin Bogner   DataBuffer.clear();
6393a7d44cbSJustin Bogner   std::vector<uint64_t> CounterBuffer;
6409e9a057aSJustin Bogner 
6419e9a057aSJustin Bogner   const unsigned char *End = D + N;
6429e9a057aSJustin Bogner   while (D < End) {
643c758387eSXinliang David Li     // Read hash.
6449e9a057aSJustin Bogner     if (D + sizeof(uint64_t) >= End)
6459e9a057aSJustin Bogner       return data_type();
6463a7d44cbSJustin Bogner     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
6473a7d44cbSJustin Bogner 
64833c76c0cSRong Xu     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
6499e9a057aSJustin Bogner     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
650c758387eSXinliang David Li     // If format version is different then read the number of counters.
65133c76c0cSRong Xu     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
6529e9a057aSJustin Bogner       if (D + sizeof(uint64_t) > End)
6533a7d44cbSJustin Bogner         return data_type();
6549e9a057aSJustin Bogner       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
6559e9a057aSJustin Bogner     }
656c758387eSXinliang David Li     // Read counter values.
6579e9a057aSJustin Bogner     if (D + CountsSize * sizeof(uint64_t) > End)
6583a7d44cbSJustin Bogner       return data_type();
6593a7d44cbSJustin Bogner 
6603a7d44cbSJustin Bogner     CounterBuffer.clear();
6619e9a057aSJustin Bogner     CounterBuffer.reserve(CountsSize);
6629e9a057aSJustin Bogner     for (uint64_t J = 0; J < CountsSize; ++J)
6633a7d44cbSJustin Bogner       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
6643a7d44cbSJustin Bogner 
6652004f003SXinliang David Li     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
6669e9a057aSJustin Bogner 
667c758387eSXinliang David Li     // Read value profiling data.
66833c76c0cSRong Xu     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
669a6b2c4f7SXinliang David Li         !readValueProfilingData(D, End)) {
6709e9a057aSJustin Bogner       DataBuffer.clear();
6719e9a057aSJustin Bogner       return data_type();
6729e9a057aSJustin Bogner     }
6733a7d44cbSJustin Bogner   }
6743a7d44cbSJustin Bogner   return DataBuffer;
6753a7d44cbSJustin Bogner }
6763a7d44cbSJustin Bogner 
677a28306dbSXinliang David Li template <typename HashTableImpl>
6789152fd17SVedant Kumar Error InstrProfReaderIndex<HashTableImpl>::getRecords(
679cf9d52c6SDavid Blaikie     StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
680a28306dbSXinliang David Li   auto Iter = HashTable->find(FuncName);
681a28306dbSXinliang David Li   if (Iter == HashTable->end())
6829152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::unknown_function);
683140f4c4fSXinliang David Li 
684140f4c4fSXinliang David Li   Data = (*Iter);
6854c3ab815SXinliang David Li   if (Data.empty())
686ee88b8d6SGulfem Savrun Yeniceri     return make_error<InstrProfError>(instrprof_error::malformed,
687ee88b8d6SGulfem Savrun Yeniceri                                       "profile data is empty");
688140f4c4fSXinliang David Li 
6899152fd17SVedant Kumar   return Error::success();
690140f4c4fSXinliang David Li }
691140f4c4fSXinliang David Li 
692a28306dbSXinliang David Li template <typename HashTableImpl>
6939152fd17SVedant Kumar Error InstrProfReaderIndex<HashTableImpl>::getRecords(
694cf9d52c6SDavid Blaikie     ArrayRef<NamedInstrProfRecord> &Data) {
695a28306dbSXinliang David Li   if (atEnd())
6969152fd17SVedant Kumar     return make_error<InstrProfError>(instrprof_error::eof);
697140f4c4fSXinliang David Li 
698140f4c4fSXinliang David Li   Data = *RecordIterator;
699140f4c4fSXinliang David Li 
7002d4803e8SXinliang David Li   if (Data.empty())
701ee88b8d6SGulfem Savrun Yeniceri     return make_error<InstrProfError>(instrprof_error::malformed,
702ee88b8d6SGulfem Savrun Yeniceri                                       "profile data is empty");
703140f4c4fSXinliang David Li 
7049152fd17SVedant Kumar   return Error::success();
705140f4c4fSXinliang David Li }
706140f4c4fSXinliang David Li 
707a28306dbSXinliang David Li template <typename HashTableImpl>
708a28306dbSXinliang David Li InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
709a28306dbSXinliang David Li     const unsigned char *Buckets, const unsigned char *const Payload,
710a28306dbSXinliang David Li     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
711140f4c4fSXinliang David Li     uint64_t Version) {
712140f4c4fSXinliang David Li   FormatVersion = Version;
713a28306dbSXinliang David Li   HashTable.reset(HashTableImpl::Create(
714a28306dbSXinliang David Li       Buckets, Payload, Base,
715a28306dbSXinliang David Li       typename HashTableImpl::InfoType(HashType, Version)));
716a28306dbSXinliang David Li   RecordIterator = HashTable->data_begin();
717140f4c4fSXinliang David Li }
718140f4c4fSXinliang David Li 
719ceed4eb1SRichard Smith namespace {
720ceed4eb1SRichard Smith /// A remapper that does not apply any remappings.
721ceed4eb1SRichard Smith class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
722ceed4eb1SRichard Smith   InstrProfReaderIndexBase &Underlying;
723ceed4eb1SRichard Smith 
724ceed4eb1SRichard Smith public:
725ceed4eb1SRichard Smith   InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
726ceed4eb1SRichard Smith       : Underlying(Underlying) {}
727ceed4eb1SRichard Smith 
728ceed4eb1SRichard Smith   Error getRecords(StringRef FuncName,
729ceed4eb1SRichard Smith                    ArrayRef<NamedInstrProfRecord> &Data) override {
730ceed4eb1SRichard Smith     return Underlying.getRecords(FuncName, Data);
731ceed4eb1SRichard Smith   }
732ceed4eb1SRichard Smith };
733ee88b8d6SGulfem Savrun Yeniceri } // namespace
734ceed4eb1SRichard Smith 
735ceed4eb1SRichard Smith /// A remapper that applies remappings based on a symbol remapping file.
736ceed4eb1SRichard Smith template <typename HashTableImpl>
737ceed4eb1SRichard Smith class llvm::InstrProfReaderItaniumRemapper
738ceed4eb1SRichard Smith     : public InstrProfReaderRemapper {
739ceed4eb1SRichard Smith public:
740ceed4eb1SRichard Smith   InstrProfReaderItaniumRemapper(
741ceed4eb1SRichard Smith       std::unique_ptr<MemoryBuffer> RemapBuffer,
742ceed4eb1SRichard Smith       InstrProfReaderIndex<HashTableImpl> &Underlying)
743ceed4eb1SRichard Smith       : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
744ceed4eb1SRichard Smith   }
745ceed4eb1SRichard Smith 
746ceed4eb1SRichard Smith   /// Extract the original function name from a PGO function name.
747ceed4eb1SRichard Smith   static StringRef extractName(StringRef Name) {
748ceed4eb1SRichard Smith     // We can have multiple :-separated pieces; there can be pieces both
749ceed4eb1SRichard Smith     // before and after the mangled name. Find the first part that starts
750ceed4eb1SRichard Smith     // with '_Z'; we'll assume that's the mangled name we want.
751ceed4eb1SRichard Smith     std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
752ceed4eb1SRichard Smith     while (true) {
753ceed4eb1SRichard Smith       Parts = Parts.second.split(':');
754ceed4eb1SRichard Smith       if (Parts.first.startswith("_Z"))
755ceed4eb1SRichard Smith         return Parts.first;
756ceed4eb1SRichard Smith       if (Parts.second.empty())
757ceed4eb1SRichard Smith         return Name;
758ceed4eb1SRichard Smith     }
759ceed4eb1SRichard Smith   }
760ceed4eb1SRichard Smith 
761ceed4eb1SRichard Smith   /// Given a mangled name extracted from a PGO function name, and a new
762ceed4eb1SRichard Smith   /// form for that mangled name, reconstitute the name.
763ceed4eb1SRichard Smith   static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
764ceed4eb1SRichard Smith                                StringRef Replacement,
765ceed4eb1SRichard Smith                                SmallVectorImpl<char> &Out) {
766ceed4eb1SRichard Smith     Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
767ceed4eb1SRichard Smith     Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
768ceed4eb1SRichard Smith     Out.insert(Out.end(), Replacement.begin(), Replacement.end());
769ceed4eb1SRichard Smith     Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
770ceed4eb1SRichard Smith   }
771ceed4eb1SRichard Smith 
772ceed4eb1SRichard Smith   Error populateRemappings() override {
773ceed4eb1SRichard Smith     if (Error E = Remappings.read(*RemapBuffer))
774ceed4eb1SRichard Smith       return E;
775ceed4eb1SRichard Smith     for (StringRef Name : Underlying.HashTable->keys()) {
776ceed4eb1SRichard Smith       StringRef RealName = extractName(Name);
777ceed4eb1SRichard Smith       if (auto Key = Remappings.insert(RealName)) {
778ceed4eb1SRichard Smith         // FIXME: We could theoretically map the same equivalence class to
779ceed4eb1SRichard Smith         // multiple names in the profile data. If that happens, we should
780ceed4eb1SRichard Smith         // return NamedInstrProfRecords from all of them.
781ceed4eb1SRichard Smith         MappedNames.insert({Key, RealName});
782ceed4eb1SRichard Smith       }
783ceed4eb1SRichard Smith     }
784ceed4eb1SRichard Smith     return Error::success();
785ceed4eb1SRichard Smith   }
786ceed4eb1SRichard Smith 
787ceed4eb1SRichard Smith   Error getRecords(StringRef FuncName,
788ceed4eb1SRichard Smith                    ArrayRef<NamedInstrProfRecord> &Data) override {
789ceed4eb1SRichard Smith     StringRef RealName = extractName(FuncName);
790ceed4eb1SRichard Smith     if (auto Key = Remappings.lookup(RealName)) {
791ceed4eb1SRichard Smith       StringRef Remapped = MappedNames.lookup(Key);
792ceed4eb1SRichard Smith       if (!Remapped.empty()) {
793ceed4eb1SRichard Smith         if (RealName.begin() == FuncName.begin() &&
794ceed4eb1SRichard Smith             RealName.end() == FuncName.end())
795ceed4eb1SRichard Smith           FuncName = Remapped;
796ceed4eb1SRichard Smith         else {
797ceed4eb1SRichard Smith           // Try rebuilding the name from the given remapping.
798ceed4eb1SRichard Smith           SmallString<256> Reconstituted;
799ceed4eb1SRichard Smith           reconstituteName(FuncName, RealName, Remapped, Reconstituted);
800ceed4eb1SRichard Smith           Error E = Underlying.getRecords(Reconstituted, Data);
801ceed4eb1SRichard Smith           if (!E)
802ceed4eb1SRichard Smith             return E;
803ceed4eb1SRichard Smith 
804ceed4eb1SRichard Smith           // If we failed because the name doesn't exist, fall back to asking
805ceed4eb1SRichard Smith           // about the original name.
806ceed4eb1SRichard Smith           if (Error Unhandled = handleErrors(
807ceed4eb1SRichard Smith                   std::move(E), [](std::unique_ptr<InstrProfError> Err) {
808ceed4eb1SRichard Smith                     return Err->get() == instrprof_error::unknown_function
809ceed4eb1SRichard Smith                                ? Error::success()
810ceed4eb1SRichard Smith                                : Error(std::move(Err));
811ceed4eb1SRichard Smith                   }))
812ceed4eb1SRichard Smith             return Unhandled;
813ceed4eb1SRichard Smith         }
814ceed4eb1SRichard Smith       }
815ceed4eb1SRichard Smith     }
816ceed4eb1SRichard Smith     return Underlying.getRecords(FuncName, Data);
817ceed4eb1SRichard Smith   }
818ceed4eb1SRichard Smith 
819ceed4eb1SRichard Smith private:
820ceed4eb1SRichard Smith   /// The memory buffer containing the remapping configuration. Remappings
821ceed4eb1SRichard Smith   /// holds pointers into this buffer.
822ceed4eb1SRichard Smith   std::unique_ptr<MemoryBuffer> RemapBuffer;
823ceed4eb1SRichard Smith 
824ceed4eb1SRichard Smith   /// The mangling remapper.
825ceed4eb1SRichard Smith   SymbolRemappingReader Remappings;
826ceed4eb1SRichard Smith 
827ceed4eb1SRichard Smith   /// Mapping from mangled name keys to the name used for the key in the
828ceed4eb1SRichard Smith   /// profile data.
829ceed4eb1SRichard Smith   /// FIXME: Can we store a location within the on-disk hash table instead of
830ceed4eb1SRichard Smith   /// redoing lookup?
831ceed4eb1SRichard Smith   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
832ceed4eb1SRichard Smith 
833ceed4eb1SRichard Smith   /// The real profile data reader.
834ceed4eb1SRichard Smith   InstrProfReaderIndex<HashTableImpl> &Underlying;
835ceed4eb1SRichard Smith };
836ceed4eb1SRichard Smith 
837b7aa2630SJustin Bogner bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
838e78d131aSEugene Zelenko   using namespace support;
839e78d131aSEugene Zelenko 
8404c3ab815SXinliang David Li   if (DataBuffer.getBufferSize() < 8)
8414c3ab815SXinliang David Li     return false;
842b7aa2630SJustin Bogner   uint64_t Magic =
843b7aa2630SJustin Bogner       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
844c758387eSXinliang David Li   // Verify that it's magical.
845b7aa2630SJustin Bogner   return Magic == IndexedInstrProf::Magic;
846b7aa2630SJustin Bogner }
847b7aa2630SJustin Bogner 
8486c93ee8dSXinliang David Li const unsigned char *
8496c93ee8dSXinliang David Li IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
850a6ff69f6SRong Xu                                     const unsigned char *Cur, bool UseCS) {
851e5a17e3fSEaswaran Raman   using namespace IndexedInstrProf;
8526c93ee8dSXinliang David Li   using namespace support;
853e78d131aSEugene Zelenko 
8546c93ee8dSXinliang David Li   if (Version >= IndexedInstrProf::Version4) {
8556c93ee8dSXinliang David Li     const IndexedInstrProf::Summary *SummaryInLE =
8566c93ee8dSXinliang David Li         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
8576c93ee8dSXinliang David Li     uint64_t NFields =
8586c93ee8dSXinliang David Li         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
8596c93ee8dSXinliang David Li     uint64_t NEntries =
8606c93ee8dSXinliang David Li         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
8616c93ee8dSXinliang David Li     uint32_t SummarySize =
8626c93ee8dSXinliang David Li         IndexedInstrProf::Summary::getSize(NFields, NEntries);
8636c93ee8dSXinliang David Li     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
8646c93ee8dSXinliang David Li         IndexedInstrProf::allocSummary(SummarySize);
8656c93ee8dSXinliang David Li 
8666c93ee8dSXinliang David Li     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
8676c93ee8dSXinliang David Li     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
8686c93ee8dSXinliang David Li     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
8696c93ee8dSXinliang David Li       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
8706c93ee8dSXinliang David Li 
87172208a82SEugene Zelenko     SummaryEntryVector DetailedSummary;
872e5a17e3fSEaswaran Raman     for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
873e5a17e3fSEaswaran Raman       const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
874e5a17e3fSEaswaran Raman       DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
875e5a17e3fSEaswaran Raman                                    Ent.NumBlocks);
876e5a17e3fSEaswaran Raman     }
877a6ff69f6SRong Xu     std::unique_ptr<llvm::ProfileSummary> &Summary =
878a6ff69f6SRong Xu         UseCS ? this->CS_Summary : this->Summary;
879a6ff69f6SRong Xu 
8804309570dSEaswaran Raman     // initialize InstrProfSummary using the SummaryData from disk.
8810eaee545SJonas Devlieghere     Summary = std::make_unique<ProfileSummary>(
882a6ff69f6SRong Xu         UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
883a6ff69f6SRong Xu         DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
884e5a17e3fSEaswaran Raman         SummaryData->get(Summary::MaxBlockCount),
885e5a17e3fSEaswaran Raman         SummaryData->get(Summary::MaxInternalBlockCount),
886e5a17e3fSEaswaran Raman         SummaryData->get(Summary::MaxFunctionCount),
887e5a17e3fSEaswaran Raman         SummaryData->get(Summary::TotalNumBlocks),
8887cefdb81SEaswaran Raman         SummaryData->get(Summary::TotalNumFunctions));
8896c93ee8dSXinliang David Li     return Cur + SummarySize;
8906c93ee8dSXinliang David Li   } else {
891fd2044f2STeresa Johnson     // The older versions do not support a profile summary. This just computes
892fd2044f2STeresa Johnson     // an empty summary, which will not result in accurate hot/cold detection.
893fd2044f2STeresa Johnson     // We would need to call addRecord for all NamedInstrProfRecords to get the
894fd2044f2STeresa Johnson     // correct summary. However, this version is old (prior to early 2016) and
895fd2044f2STeresa Johnson     // has not been supporting an accurate summary for several years.
896e5a17e3fSEaswaran Raman     InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
897fd2044f2STeresa Johnson     Summary = Builder.getSummary();
8986c93ee8dSXinliang David Li     return Cur;
8996c93ee8dSXinliang David Li   }
9006c93ee8dSXinliang David Li }
9016c93ee8dSXinliang David Li 
9029152fd17SVedant Kumar Error IndexedInstrProfReader::readHeader() {
903e78d131aSEugene Zelenko   using namespace support;
904e78d131aSEugene Zelenko 
905a7c9ed57SAaron Ballman   const unsigned char *Start =
906a7c9ed57SAaron Ballman       (const unsigned char *)DataBuffer->getBufferStart();
907b7aa2630SJustin Bogner   const unsigned char *Cur = Start;
908a7c9ed57SAaron Ballman   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
909b7aa2630SJustin Bogner     return error(instrprof_error::truncated);
910b7aa2630SJustin Bogner 
911dab183edSXinliang David Li   auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
912dab183edSXinliang David Li   Cur += sizeof(IndexedInstrProf::Header);
913dab183edSXinliang David Li 
914b7aa2630SJustin Bogner   // Check the magic number.
915dab183edSXinliang David Li   uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
916b7aa2630SJustin Bogner   if (Magic != IndexedInstrProf::Magic)
917b7aa2630SJustin Bogner     return error(instrprof_error::bad_magic);
918b7aa2630SJustin Bogner 
919b7aa2630SJustin Bogner   // Read the version.
920140f4c4fSXinliang David Li   uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
92133c76c0cSRong Xu   if (GET_VERSION(FormatVersion) >
92233c76c0cSRong Xu       IndexedInstrProf::ProfVersion::CurrentVersion)
923b7aa2630SJustin Bogner     return error(instrprof_error::unsupported_version);
924b7aa2630SJustin Bogner 
925a6ff69f6SRong Xu   Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
926a6ff69f6SRong Xu                     /* UseCS */ false);
92705c0afe8SRong Xu   if (FormatVersion & VARIANT_MASK_CSIR_PROF)
928a6ff69f6SRong Xu     Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
929a6ff69f6SRong Xu                       /* UseCS */ true);
930b7aa2630SJustin Bogner 
931b7aa2630SJustin Bogner   // Read the hash type and start offset.
932b7aa2630SJustin Bogner   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
933dab183edSXinliang David Li       endian::byte_swap<uint64_t, little>(Header->HashType));
934b7aa2630SJustin Bogner   if (HashType > IndexedInstrProf::HashT::Last)
935b7aa2630SJustin Bogner     return error(instrprof_error::unsupported_hash_type);
936dab183edSXinliang David Li 
937dab183edSXinliang David Li   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
938b7aa2630SJustin Bogner 
939b7aa2630SJustin Bogner   // The rest of the file is an on disk hash table.
940ceed4eb1SRichard Smith   auto IndexPtr =
9410eaee545SJonas Devlieghere       std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
942a28306dbSXinliang David Li           Start + HashOffset, Cur, Start, HashType, FormatVersion);
943ceed4eb1SRichard Smith 
944ceed4eb1SRichard Smith   // Load the remapping table now if requested.
945ceed4eb1SRichard Smith   if (RemappingBuffer) {
9460eaee545SJonas Devlieghere     Remapper = std::make_unique<
947ceed4eb1SRichard Smith         InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
948ceed4eb1SRichard Smith         std::move(RemappingBuffer), *IndexPtr);
949ceed4eb1SRichard Smith     if (Error E = Remapper->populateRemappings())
950ceed4eb1SRichard Smith       return E;
951ceed4eb1SRichard Smith   } else {
9520eaee545SJonas Devlieghere     Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
953ceed4eb1SRichard Smith   }
954ceed4eb1SRichard Smith   Index = std::move(IndexPtr);
955ceed4eb1SRichard Smith 
956b7aa2630SJustin Bogner   return success();
957b7aa2630SJustin Bogner }
958b7aa2630SJustin Bogner 
959a716cc5cSXinliang David Li InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
960a716cc5cSXinliang David Li   if (Symtab.get())
961a716cc5cSXinliang David Li     return *Symtab.get();
962a716cc5cSXinliang David Li 
9630eaee545SJonas Devlieghere   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
964b5794ca9SVedant Kumar   if (Error E = Index->populateSymtab(*NewSymtab.get())) {
965b5794ca9SVedant Kumar     consumeError(error(InstrProfError::take(std::move(E))));
966b5794ca9SVedant Kumar   }
967a716cc5cSXinliang David Li 
968a716cc5cSXinliang David Li   Symtab = std::move(NewSymtab);
969a716cc5cSXinliang David Li   return *Symtab.get();
970a716cc5cSXinliang David Li }
971a716cc5cSXinliang David Li 
9729152fd17SVedant Kumar Expected<InstrProfRecord>
9736aa216c2SXinliang David Li IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
9746aa216c2SXinliang David Li                                            uint64_t FuncHash) {
975cf9d52c6SDavid Blaikie   ArrayRef<NamedInstrProfRecord> Data;
976ceed4eb1SRichard Smith   Error Err = Remapper->getRecords(FuncName, Data);
9779152fd17SVedant Kumar   if (Err)
978c55cf4afSBill Wendling     return std::move(Err);
979821d7471SJustin Bogner   // Found it. Look for counters with the right hash.
980*ccdd5bb2SKazu Hirata   for (const NamedInstrProfRecord &I : Data) {
981821d7471SJustin Bogner     // Check for a match and fill the vector if there is one.
982*ccdd5bb2SKazu Hirata     if (I.Hash == FuncHash)
983*ccdd5bb2SKazu Hirata       return std::move(I);
984821d7471SJustin Bogner   }
985821d7471SJustin Bogner   return error(instrprof_error::hash_mismatch);
986821d7471SJustin Bogner }
987b7aa2630SJustin Bogner 
9889152fd17SVedant Kumar Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
9899152fd17SVedant Kumar                                                 uint64_t FuncHash,
9906aa216c2SXinliang David Li                                                 std::vector<uint64_t> &Counts) {
9919152fd17SVedant Kumar   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
9929152fd17SVedant Kumar   if (Error E = Record.takeError())
9939152fd17SVedant Kumar     return error(std::move(E));
9942004f003SXinliang David Li 
9952004f003SXinliang David Li   Counts = Record.get().Counts;
9962004f003SXinliang David Li   return success();
9972004f003SXinliang David Li }
9982004f003SXinliang David Li 
999cf9d52c6SDavid Blaikie Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
1000cf9d52c6SDavid Blaikie   ArrayRef<NamedInstrProfRecord> Data;
1001140f4c4fSXinliang David Li 
10029152fd17SVedant Kumar   Error E = Index->getRecords(Data);
10039152fd17SVedant Kumar   if (E)
10049152fd17SVedant Kumar     return error(std::move(E));
1005140f4c4fSXinliang David Li 
10063a7d44cbSJustin Bogner   Record = Data[RecordIndex++];
10073a7d44cbSJustin Bogner   if (RecordIndex >= Data.size()) {
1008a28306dbSXinliang David Li     Index->advanceToNextKey();
10093a7d44cbSJustin Bogner     RecordIndex = 0;
1010821d7471SJustin Bogner   }
1011b7aa2630SJustin Bogner   return success();
1012b7aa2630SJustin Bogner }
1013998b97f6SRong Xu 
1014e0fa2689SRong Xu void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) {
1015998b97f6SRong Xu   uint64_t NumFuncs = 0;
1016998b97f6SRong Xu   for (const auto &Func : *this) {
1017998b97f6SRong Xu     if (isIRLevelProfile()) {
1018998b97f6SRong Xu       bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
1019998b97f6SRong Xu       if (FuncIsCS != IsCS)
1020998b97f6SRong Xu         continue;
1021998b97f6SRong Xu     }
1022e0fa2689SRong Xu     Func.accumulateCounts(Sum);
1023998b97f6SRong Xu     ++NumFuncs;
1024998b97f6SRong Xu   }
1025998b97f6SRong Xu   Sum.NumEntries = NumFuncs;
1026998b97f6SRong Xu }
1027