xref: /llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp (revision 684e79f25415250afa51bfcd294d793720aa4bae)
1 //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for reading profiling data for clang's
10 // instrumentation based PGO and coverage.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ProfileData/InstrProfReader.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/IR/ProfileSummary.h"
20 #include "llvm/ProfileData/InstrProf.h"
21 #include "llvm/ProfileData/MemProf.h"
22 #include "llvm/ProfileData/ProfileCommon.h"
23 #include "llvm/ProfileData/SymbolRemappingReader.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/Error.h"
26 #include "llvm/Support/ErrorOr.h"
27 #include "llvm/Support/FormatVariadic.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include "llvm/Support/VirtualFileSystem.h"
30 #include <algorithm>
31 #include <cstddef>
32 #include <cstdint>
33 #include <limits>
34 #include <memory>
35 #include <optional>
36 #include <system_error>
37 #include <utility>
38 #include <vector>
39 
40 using namespace llvm;
41 
42 // Extracts the variant information from the top 32 bits in the version and
43 // returns an enum specifying the variants present.
44 static InstrProfKind getProfileKindFromVersion(uint64_t Version) {
45   InstrProfKind ProfileKind = InstrProfKind::Unknown;
46   if (Version & VARIANT_MASK_IR_PROF) {
47     ProfileKind |= InstrProfKind::IRInstrumentation;
48   }
49   if (Version & VARIANT_MASK_CSIR_PROF) {
50     ProfileKind |= InstrProfKind::ContextSensitive;
51   }
52   if (Version & VARIANT_MASK_INSTR_ENTRY) {
53     ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
54   }
55   if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) {
56     ProfileKind |= InstrProfKind::LoopEntriesInstrumentation;
57   }
58   if (Version & VARIANT_MASK_BYTE_COVERAGE) {
59     ProfileKind |= InstrProfKind::SingleByteCoverage;
60   }
61   if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
62     ProfileKind |= InstrProfKind::FunctionEntryOnly;
63   }
64   if (Version & VARIANT_MASK_MEMPROF) {
65     ProfileKind |= InstrProfKind::MemProf;
66   }
67   if (Version & VARIANT_MASK_TEMPORAL_PROF) {
68     ProfileKind |= InstrProfKind::TemporalProfile;
69   }
70   return ProfileKind;
71 }
72 
73 static Expected<std::unique_ptr<MemoryBuffer>>
74 setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) {
75   auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
76                                            : FS.getBufferForFile(Filename);
77   if (std::error_code EC = BufferOrErr.getError())
78     return errorCodeToError(EC);
79   return std::move(BufferOrErr.get());
80 }
81 
82 static Error initializeReader(InstrProfReader &Reader) {
83   return Reader.readHeader();
84 }
85 
86 /// Read a list of binary ids from a profile that consist of
87 /// a. uint64_t binary id length
88 /// b. uint8_t  binary id data
89 /// c. uint8_t  padding (if necessary)
90 /// This function is shared between raw and indexed profiles.
91 /// Raw profiles are in host-endian format, and indexed profiles are in
92 /// little-endian format. So, this function takes an argument indicating the
93 /// associated endian format to read the binary ids correctly.
94 static Error
95 readBinaryIdsInternal(const MemoryBuffer &DataBuffer,
96                       ArrayRef<uint8_t> BinaryIdsBuffer,
97                       std::vector<llvm::object::BuildID> &BinaryIds,
98                       const llvm::endianness Endian) {
99   using namespace support;
100 
101   const uint64_t BinaryIdsSize = BinaryIdsBuffer.size();
102   const uint8_t *BinaryIdsStart = BinaryIdsBuffer.data();
103 
104   if (BinaryIdsSize == 0)
105     return Error::success();
106 
107   const uint8_t *BI = BinaryIdsStart;
108   const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
109   const uint8_t *End =
110       reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
111 
112   while (BI < BIEnd) {
113     size_t Remaining = BIEnd - BI;
114     // There should be enough left to read the binary id length.
115     if (Remaining < sizeof(uint64_t))
116       return make_error<InstrProfError>(
117           instrprof_error::malformed,
118           "not enough data to read binary id length");
119 
120     uint64_t BILen = endian::readNext<uint64_t>(BI, Endian);
121     if (BILen == 0)
122       return make_error<InstrProfError>(instrprof_error::malformed,
123                                         "binary id length is 0");
124 
125     Remaining = BIEnd - BI;
126     // There should be enough left to read the binary id data.
127     if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
128       return make_error<InstrProfError>(
129           instrprof_error::malformed, "not enough data to read binary id data");
130 
131     // Add binary id to the binary ids list.
132     BinaryIds.push_back(object::BuildID(BI, BI + BILen));
133 
134     // Increment by binary id data length, which aligned to the size of uint64.
135     BI += alignToPowerOf2(BILen, sizeof(uint64_t));
136     if (BI > End)
137       return make_error<InstrProfError>(
138           instrprof_error::malformed,
139           "binary id section is greater than buffer size");
140   }
141 
142   return Error::success();
143 }
144 
145 static void printBinaryIdsInternal(raw_ostream &OS,
146                                    ArrayRef<llvm::object::BuildID> BinaryIds) {
147   OS << "Binary IDs: \n";
148   for (const auto &BI : BinaryIds) {
149     for (auto I : BI)
150       OS << format("%02x", I);
151     OS << "\n";
152   }
153 }
154 
155 Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
156     const Twine &Path, vfs::FileSystem &FS,
157     const InstrProfCorrelator *Correlator,
158     const object::BuildIDFetcher *BIDFetcher,
159     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
160     std::function<void(Error)> Warn) {
161   // Set up the buffer to read.
162   auto BufferOrError = setupMemoryBuffer(Path, FS);
163   if (Error E = BufferOrError.takeError())
164     return std::move(E);
165   return InstrProfReader::create(std::move(BufferOrError.get()), Correlator,
166                                  BIDFetcher, BIDFetcherCorrelatorKind, Warn);
167 }
168 
169 Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
170     std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator,
171     const object::BuildIDFetcher *BIDFetcher,
172     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
173     std::function<void(Error)> Warn) {
174   if (Buffer->getBufferSize() == 0)
175     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
176 
177   std::unique_ptr<InstrProfReader> Result;
178   // Create the reader.
179   if (IndexedInstrProfReader::hasFormat(*Buffer))
180     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
181   else if (RawInstrProfReader64::hasFormat(*Buffer))
182     Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator,
183                                           BIDFetcher, BIDFetcherCorrelatorKind,
184                                           Warn));
185   else if (RawInstrProfReader32::hasFormat(*Buffer))
186     Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator,
187                                           BIDFetcher, BIDFetcherCorrelatorKind,
188                                           Warn));
189   else if (TextInstrProfReader::hasFormat(*Buffer))
190     Result.reset(new TextInstrProfReader(std::move(Buffer)));
191   else
192     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
193 
194   // Initialize the reader and return the result.
195   if (Error E = initializeReader(*Result))
196     return std::move(E);
197 
198   return std::move(Result);
199 }
200 
201 Expected<std::unique_ptr<IndexedInstrProfReader>>
202 IndexedInstrProfReader::create(const Twine &Path, vfs::FileSystem &FS,
203                                const Twine &RemappingPath) {
204   // Set up the buffer to read.
205   auto BufferOrError = setupMemoryBuffer(Path, FS);
206   if (Error E = BufferOrError.takeError())
207     return std::move(E);
208 
209   // Set up the remapping buffer if requested.
210   std::unique_ptr<MemoryBuffer> RemappingBuffer;
211   std::string RemappingPathStr = RemappingPath.str();
212   if (!RemappingPathStr.empty()) {
213     auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS);
214     if (Error E = RemappingBufferOrError.takeError())
215       return std::move(E);
216     RemappingBuffer = std::move(RemappingBufferOrError.get());
217   }
218 
219   return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
220                                         std::move(RemappingBuffer));
221 }
222 
223 Expected<std::unique_ptr<IndexedInstrProfReader>>
224 IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
225                                std::unique_ptr<MemoryBuffer> RemappingBuffer) {
226   // Create the reader.
227   if (!IndexedInstrProfReader::hasFormat(*Buffer))
228     return make_error<InstrProfError>(instrprof_error::bad_magic);
229   auto Result = std::make_unique<IndexedInstrProfReader>(
230       std::move(Buffer), std::move(RemappingBuffer));
231 
232   // Initialize the reader and return the result.
233   if (Error E = initializeReader(*Result))
234     return std::move(E);
235 
236   return std::move(Result);
237 }
238 
239 bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
240   // Verify that this really looks like plain ASCII text by checking a
241   // 'reasonable' number of characters (up to profile magic size).
242   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
243   StringRef buffer = Buffer.getBufferStart();
244   return count == 0 ||
245          std::all_of(buffer.begin(), buffer.begin() + count,
246                      [](char c) { return isPrint(c) || isSpace(c); });
247 }
248 
249 // Read the profile variant flag from the header: ":FE" means this is a FE
250 // generated profile. ":IR" means this is an IR level profile. Other strings
251 // with a leading ':' will be reported an error format.
252 Error TextInstrProfReader::readHeader() {
253   Symtab.reset(new InstrProfSymtab());
254 
255   while (Line->starts_with(":")) {
256     StringRef Str = Line->substr(1);
257     if (Str.equals_insensitive("ir"))
258       ProfileKind |= InstrProfKind::IRInstrumentation;
259     else if (Str.equals_insensitive("fe"))
260       ProfileKind |= InstrProfKind::FrontendInstrumentation;
261     else if (Str.equals_insensitive("csir")) {
262       ProfileKind |= InstrProfKind::IRInstrumentation;
263       ProfileKind |= InstrProfKind::ContextSensitive;
264     } else if (Str.equals_insensitive("entry_first"))
265       ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
266     else if (Str.equals_insensitive("not_entry_first"))
267       ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation;
268     else if (Str.equals_insensitive("instrument_loop_entries"))
269       ProfileKind |= InstrProfKind::LoopEntriesInstrumentation;
270     else if (Str.equals_insensitive("single_byte_coverage"))
271       ProfileKind |= InstrProfKind::SingleByteCoverage;
272     else if (Str.equals_insensitive("temporal_prof_traces")) {
273       ProfileKind |= InstrProfKind::TemporalProfile;
274       if (auto Err = readTemporalProfTraceData())
275         return error(std::move(Err));
276     } else
277       return error(instrprof_error::bad_header);
278     ++Line;
279   }
280   return success();
281 }
282 
283 /// Temporal profile trace data is stored in the header immediately after
284 /// ":temporal_prof_traces". The first integer is the number of traces, the
285 /// second integer is the stream size, then the following lines are the actual
286 /// traces which consist of a weight and a comma separated list of function
287 /// names.
288 Error TextInstrProfReader::readTemporalProfTraceData() {
289   if ((++Line).is_at_end())
290     return error(instrprof_error::eof);
291 
292   uint32_t NumTraces;
293   if (Line->getAsInteger(0, NumTraces))
294     return error(instrprof_error::malformed);
295 
296   if ((++Line).is_at_end())
297     return error(instrprof_error::eof);
298 
299   if (Line->getAsInteger(0, TemporalProfTraceStreamSize))
300     return error(instrprof_error::malformed);
301 
302   for (uint32_t i = 0; i < NumTraces; i++) {
303     if ((++Line).is_at_end())
304       return error(instrprof_error::eof);
305 
306     TemporalProfTraceTy Trace;
307     if (Line->getAsInteger(0, Trace.Weight))
308       return error(instrprof_error::malformed);
309 
310     if ((++Line).is_at_end())
311       return error(instrprof_error::eof);
312 
313     SmallVector<StringRef> FuncNames;
314     Line->split(FuncNames, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
315     for (auto &FuncName : FuncNames)
316       Trace.FunctionNameRefs.push_back(
317           IndexedInstrProf::ComputeHash(FuncName.trim()));
318     TemporalProfTraces.push_back(std::move(Trace));
319   }
320   return success();
321 }
322 
323 Error
324 TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
325 
326 #define CHECK_LINE_END(Line)                                                   \
327   if (Line.is_at_end())                                                        \
328     return error(instrprof_error::truncated);
329 #define READ_NUM(Str, Dst)                                                     \
330   if ((Str).getAsInteger(10, (Dst)))                                           \
331     return error(instrprof_error::malformed);
332 #define VP_READ_ADVANCE(Val)                                                   \
333   CHECK_LINE_END(Line);                                                        \
334   uint32_t Val;                                                                \
335   READ_NUM((*Line), (Val));                                                    \
336   Line++;
337 
338   if (Line.is_at_end())
339     return success();
340 
341   uint32_t NumValueKinds;
342   if (Line->getAsInteger(10, NumValueKinds)) {
343     // No value profile data
344     return success();
345   }
346   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
347     return error(instrprof_error::malformed,
348                  "number of value kinds is invalid");
349   Line++;
350 
351   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
352     VP_READ_ADVANCE(ValueKind);
353     if (ValueKind > IPVK_Last)
354       return error(instrprof_error::malformed, "value kind is invalid");
355     ;
356     VP_READ_ADVANCE(NumValueSites);
357     if (!NumValueSites)
358       continue;
359 
360     Record.reserveSites(VK, NumValueSites);
361     for (uint32_t S = 0; S < NumValueSites; S++) {
362       VP_READ_ADVANCE(NumValueData);
363 
364       std::vector<InstrProfValueData> CurrentValues;
365       for (uint32_t V = 0; V < NumValueData; V++) {
366         CHECK_LINE_END(Line);
367         std::pair<StringRef, StringRef> VD = Line->rsplit(':');
368         uint64_t TakenCount, Value;
369         if (ValueKind == IPVK_IndirectCallTarget) {
370           if (InstrProfSymtab::isExternalSymbol(VD.first)) {
371             Value = 0;
372           } else {
373             if (Error E = Symtab->addFuncName(VD.first))
374               return E;
375             Value = IndexedInstrProf::ComputeHash(VD.first);
376           }
377         } else if (ValueKind == IPVK_VTableTarget) {
378           if (InstrProfSymtab::isExternalSymbol(VD.first))
379             Value = 0;
380           else {
381             if (Error E = Symtab->addVTableName(VD.first))
382               return E;
383             Value = IndexedInstrProf::ComputeHash(VD.first);
384           }
385         } else {
386           READ_NUM(VD.first, Value);
387         }
388         READ_NUM(VD.second, TakenCount);
389         CurrentValues.push_back({Value, TakenCount});
390         Line++;
391       }
392       assert(CurrentValues.size() == NumValueData);
393       Record.addValueData(ValueKind, S, CurrentValues, nullptr);
394     }
395   }
396   return success();
397 
398 #undef CHECK_LINE_END
399 #undef READ_NUM
400 #undef VP_READ_ADVANCE
401 }
402 
403 Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
404   // Skip empty lines and comments.
405   while (!Line.is_at_end() && (Line->empty() || Line->starts_with("#")))
406     ++Line;
407   // If we hit EOF while looking for a name, we're done.
408   if (Line.is_at_end()) {
409     return error(instrprof_error::eof);
410   }
411 
412   // Read the function name.
413   Record.Name = *Line++;
414   if (Error E = Symtab->addFuncName(Record.Name))
415     return error(std::move(E));
416 
417   // Read the function hash.
418   if (Line.is_at_end())
419     return error(instrprof_error::truncated);
420   if ((Line++)->getAsInteger(0, Record.Hash))
421     return error(instrprof_error::malformed,
422                  "function hash is not a valid integer");
423 
424   // Read the number of counters.
425   uint64_t NumCounters;
426   if (Line.is_at_end())
427     return error(instrprof_error::truncated);
428   if ((Line++)->getAsInteger(10, NumCounters))
429     return error(instrprof_error::malformed,
430                  "number of counters is not a valid integer");
431   if (NumCounters == 0)
432     return error(instrprof_error::malformed, "number of counters is zero");
433 
434   // Read each counter and fill our internal storage with the values.
435   Record.Clear();
436   Record.Counts.reserve(NumCounters);
437   for (uint64_t I = 0; I < NumCounters; ++I) {
438     if (Line.is_at_end())
439       return error(instrprof_error::truncated);
440     uint64_t Count;
441     if ((Line++)->getAsInteger(10, Count))
442       return error(instrprof_error::malformed, "count is invalid");
443     Record.Counts.push_back(Count);
444   }
445 
446   // Bitmap byte information is indicated with special character.
447   if (Line->starts_with("$")) {
448     Record.BitmapBytes.clear();
449     // Read the number of bitmap bytes.
450     uint64_t NumBitmapBytes;
451     if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
452       return error(instrprof_error::malformed,
453                    "number of bitmap bytes is not a valid integer");
454     if (NumBitmapBytes != 0) {
455       // Read each bitmap and fill our internal storage with the values.
456       Record.BitmapBytes.reserve(NumBitmapBytes);
457       for (uint8_t I = 0; I < NumBitmapBytes; ++I) {
458         if (Line.is_at_end())
459           return error(instrprof_error::truncated);
460         uint8_t BitmapByte;
461         if ((Line++)->getAsInteger(0, BitmapByte))
462           return error(instrprof_error::malformed,
463                        "bitmap byte is not a valid integer");
464         Record.BitmapBytes.push_back(BitmapByte);
465       }
466     }
467   }
468 
469   // Check if value profile data exists and read it if so.
470   if (Error E = readValueProfileData(Record))
471     return error(std::move(E));
472 
473   return success();
474 }
475 
476 template <class IntPtrT>
477 InstrProfKind RawInstrProfReader<IntPtrT>::getProfileKind() const {
478   return getProfileKindFromVersion(Version);
479 }
480 
481 template <class IntPtrT>
482 SmallVector<TemporalProfTraceTy> &
483 RawInstrProfReader<IntPtrT>::getTemporalProfTraces(
484     std::optional<uint64_t> Weight) {
485   if (TemporalProfTimestamps.empty()) {
486     assert(TemporalProfTraces.empty());
487     return TemporalProfTraces;
488   }
489   // Sort functions by their timestamps to build the trace.
490   std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
491   TemporalProfTraceTy Trace;
492   if (Weight)
493     Trace.Weight = *Weight;
494   for (auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
495     Trace.FunctionNameRefs.push_back(NameRef);
496   TemporalProfTraces = {std::move(Trace)};
497   return TemporalProfTraces;
498 }
499 
500 template <class IntPtrT>
501 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
502   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
503     return false;
504   uint64_t Magic =
505     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
506   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
507          llvm::byteswap(RawInstrProf::getMagic<IntPtrT>()) == Magic;
508 }
509 
510 template <class IntPtrT>
511 Error RawInstrProfReader<IntPtrT>::readHeader() {
512   if (!hasFormat(*DataBuffer))
513     return error(instrprof_error::bad_magic);
514   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
515     return error(instrprof_error::bad_header);
516   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
517       DataBuffer->getBufferStart());
518   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
519   return readHeader(*Header);
520 }
521 
522 template <class IntPtrT>
523 Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
524   const char *End = DataBuffer->getBufferEnd();
525   // Skip zero padding between profiles.
526   while (CurrentPos != End && *CurrentPos == 0)
527     ++CurrentPos;
528   // If there's nothing left, we're done.
529   if (CurrentPos == End)
530     return make_error<InstrProfError>(instrprof_error::eof);
531   // If there isn't enough space for another header, this is probably just
532   // garbage at the end of the file.
533   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
534     return make_error<InstrProfError>(instrprof_error::malformed,
535                                       "not enough space for another header");
536   // The writer ensures each profile is padded to start at an aligned address.
537   if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
538     return make_error<InstrProfError>(instrprof_error::malformed,
539                                       "insufficient padding");
540   // The magic should have the same byte order as in the previous header.
541   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
542   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
543     return make_error<InstrProfError>(instrprof_error::bad_magic);
544 
545   // There's another profile to read, so we need to process the header.
546   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
547   return readHeader(*Header);
548 }
549 
550 template <class IntPtrT>
551 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
552   if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
553                               StringRef(VNamesStart, VNamesEnd - VNamesStart)))
554     return error(std::move(E));
555   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
556     const IntPtrT FPtr = swap(I->FunctionPointer);
557     if (!FPtr)
558       continue;
559     Symtab.mapAddress(FPtr, swap(I->NameRef));
560   }
561 
562   if (VTableBegin != nullptr && VTableEnd != nullptr) {
563     for (const RawInstrProf::VTableProfileData<IntPtrT> *I = VTableBegin;
564          I != VTableEnd; ++I) {
565       const IntPtrT VPtr = swap(I->VTablePointer);
566       if (!VPtr)
567         continue;
568       // Map both begin and end address to the name hash, since the instrumented
569       // address could be somewhere in the middle.
570       // VPtr is of type uint32_t or uint64_t so 'VPtr + I->VTableSize' marks
571       // the end of vtable address.
572       Symtab.mapVTableAddress(VPtr, VPtr + swap(I->VTableSize),
573                               swap(I->VTableNameHash));
574     }
575   }
576   return success();
577 }
578 
579 template <class IntPtrT>
580 Error RawInstrProfReader<IntPtrT>::readHeader(
581     const RawInstrProf::Header &Header) {
582   Version = swap(Header.Version);
583   if (GET_VERSION(Version) != RawInstrProf::Version)
584     return error(instrprof_error::raw_profile_version_mismatch,
585                  ("Profile uses raw profile format version = " +
586                   Twine(GET_VERSION(Version)) +
587                   "; expected version = " + Twine(RawInstrProf::Version) +
588                   "\nPLEASE update this tool to version in the raw profile, or "
589                   "regenerate raw profile with expected version.")
590                      .str());
591 
592   uint64_t BinaryIdSize = swap(Header.BinaryIdsSize);
593   // Binary id start just after the header if exists.
594   const uint8_t *BinaryIdStart =
595       reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
596   const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
597   const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
598   if (BinaryIdSize % sizeof(uint64_t) || BinaryIdEnd > BufferEnd)
599     return error(instrprof_error::bad_header);
600   ArrayRef<uint8_t> BinaryIdsBuffer(BinaryIdStart, BinaryIdSize);
601   if (!BinaryIdsBuffer.empty()) {
602     if (Error Err = readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer,
603                                           BinaryIds, getDataEndianness()))
604       return Err;
605   }
606 
607   CountersDelta = swap(Header.CountersDelta);
608   BitmapDelta = swap(Header.BitmapDelta);
609   NamesDelta = swap(Header.NamesDelta);
610   auto NumData = swap(Header.NumData);
611   auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
612   auto CountersSize = swap(Header.NumCounters) * getCounterTypeSize();
613   auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
614   auto NumBitmapBytes = swap(Header.NumBitmapBytes);
615   auto PaddingBytesAfterBitmapBytes = swap(Header.PaddingBytesAfterBitmapBytes);
616   auto NamesSize = swap(Header.NamesSize);
617   auto VTableNameSize = swap(Header.VNamesSize);
618   auto NumVTables = swap(Header.NumVTables);
619   ValueKindLast = swap(Header.ValueKindLast);
620 
621   auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>);
622   auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize);
623   auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize);
624 
625   auto VTableSectionSize =
626       NumVTables * sizeof(RawInstrProf::VTableProfileData<IntPtrT>);
627   auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize);
628 
629   // Profile data starts after profile header and binary ids if exist.
630   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdSize;
631   ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
632   ptrdiff_t BitmapOffset =
633       CountersOffset + CountersSize + PaddingBytesAfterCounters;
634   ptrdiff_t NamesOffset =
635       BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
636   ptrdiff_t VTableProfDataOffset =
637       NamesOffset + NamesSize + PaddingBytesAfterNames;
638   ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize +
639                                PaddingBytesAfterVTableProfData;
640   ptrdiff_t ValueDataOffset =
641       VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames;
642 
643   auto *Start = reinterpret_cast<const char *>(&Header);
644   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
645     return error(instrprof_error::bad_header);
646 
647   if (BIDFetcher) {
648     std::vector<object::BuildID> BinaryIDs;
649     if (Error E = readBinaryIds(BinaryIDs))
650       return E;
651     if (auto E = InstrProfCorrelator::get("", BIDFetcherCorrelatorKind,
652                                           BIDFetcher, BinaryIDs)
653                      .moveInto(BIDFetcherCorrelator)) {
654       return E;
655     }
656     if (auto Err = BIDFetcherCorrelator->correlateProfileData(0))
657       return Err;
658   }
659 
660   if (Correlator) {
661     // These sizes in the raw file are zero because we constructed them in the
662     // Correlator.
663     if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
664           NamesDelta == 0))
665       return error(instrprof_error::unexpected_correlation_info);
666     Data = Correlator->getDataPointer();
667     DataEnd = Data + Correlator->getDataSize();
668     NamesStart = Correlator->getNamesPointer();
669     NamesEnd = NamesStart + Correlator->getNamesSize();
670   } else if (BIDFetcherCorrelator) {
671     InstrProfCorrelatorImpl<IntPtrT> *BIDFetcherCorrelatorImpl =
672         dyn_cast_or_null<InstrProfCorrelatorImpl<IntPtrT>>(
673             BIDFetcherCorrelator.get());
674     Data = BIDFetcherCorrelatorImpl->getDataPointer();
675     DataEnd = Data + BIDFetcherCorrelatorImpl->getDataSize();
676     NamesStart = BIDFetcherCorrelatorImpl->getNamesPointer();
677     NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->getNamesSize();
678   } else {
679     Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
680         Start + DataOffset);
681     DataEnd = Data + NumData;
682     VTableBegin =
683         reinterpret_cast<const RawInstrProf::VTableProfileData<IntPtrT> *>(
684             Start + VTableProfDataOffset);
685     VTableEnd = VTableBegin + NumVTables;
686     NamesStart = Start + NamesOffset;
687     NamesEnd = NamesStart + NamesSize;
688     VNamesStart = Start + VTableNameOffset;
689     VNamesEnd = VNamesStart + VTableNameSize;
690   }
691 
692   CountersStart = Start + CountersOffset;
693   CountersEnd = CountersStart + CountersSize;
694   BitmapStart = Start + BitmapOffset;
695   BitmapEnd = BitmapStart + NumBitmapBytes;
696   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
697 
698   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
699   if (Error E = createSymtab(*NewSymtab))
700     return E;
701 
702   Symtab = std::move(NewSymtab);
703   return success();
704 }
705 
706 template <class IntPtrT>
707 Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
708   Record.Name = getName(Data->NameRef);
709   return success();
710 }
711 
712 template <class IntPtrT>
713 Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
714   Record.Hash = swap(Data->FuncHash);
715   return success();
716 }
717 
718 template <class IntPtrT>
719 Error RawInstrProfReader<IntPtrT>::readRawCounts(
720     InstrProfRecord &Record) {
721   uint32_t NumCounters = swap(Data->NumCounters);
722   if (NumCounters == 0)
723     return error(instrprof_error::malformed, "number of counters is zero");
724 
725   ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta;
726   if (CounterBaseOffset < 0)
727     return error(
728         instrprof_error::malformed,
729         ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
730 
731   if (CounterBaseOffset >= CountersEnd - CountersStart)
732     return error(instrprof_error::malformed,
733                  ("counter offset " + Twine(CounterBaseOffset) +
734                   " is greater than the maximum counter offset " +
735                   Twine(CountersEnd - CountersStart - 1))
736                      .str());
737 
738   uint64_t MaxNumCounters =
739       (CountersEnd - (CountersStart + CounterBaseOffset)) /
740       getCounterTypeSize();
741   if (NumCounters > MaxNumCounters)
742     return error(instrprof_error::malformed,
743                  ("number of counters " + Twine(NumCounters) +
744                   " is greater than the maximum number of counters " +
745                   Twine(MaxNumCounters))
746                      .str());
747 
748   Record.Counts.clear();
749   Record.Counts.reserve(NumCounters);
750   for (uint32_t I = 0; I < NumCounters; I++) {
751     const char *Ptr =
752         CountersStart + CounterBaseOffset + I * getCounterTypeSize();
753     if (I == 0 && hasTemporalProfile()) {
754       uint64_t TimestampValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
755       if (TimestampValue != 0 &&
756           TimestampValue != std::numeric_limits<uint64_t>::max()) {
757         TemporalProfTimestamps.emplace_back(TimestampValue,
758                                             swap(Data->NameRef));
759         TemporalProfTraceStreamSize = 1;
760       }
761       if (hasSingleByteCoverage()) {
762         // In coverage mode, getCounterTypeSize() returns 1 byte but our
763         // timestamp field has size uint64_t. Increment I so that the next
764         // iteration of this for loop points to the byte after the timestamp
765         // field, i.e., I += 8.
766         I += 7;
767       }
768       continue;
769     }
770     if (hasSingleByteCoverage()) {
771       // A value of zero signifies the block is covered.
772       Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
773     } else {
774       uint64_t CounterValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
775       if (CounterValue > MaxCounterValue && Warn)
776         Warn(make_error<InstrProfError>(
777             instrprof_error::counter_value_too_large, Twine(CounterValue)));
778 
779       Record.Counts.push_back(CounterValue);
780     }
781   }
782 
783   return success();
784 }
785 
786 template <class IntPtrT>
787 Error RawInstrProfReader<IntPtrT>::readRawBitmapBytes(InstrProfRecord &Record) {
788   uint32_t NumBitmapBytes = swap(Data->NumBitmapBytes);
789 
790   Record.BitmapBytes.clear();
791   Record.BitmapBytes.reserve(NumBitmapBytes);
792 
793   // It's possible MCDC is either not enabled or only used for some functions
794   // and not others. So if we record 0 bytes, just move on.
795   if (NumBitmapBytes == 0)
796     return success();
797 
798   // BitmapDelta decreases as we advance to the next data record.
799   ptrdiff_t BitmapOffset = swap(Data->BitmapPtr) - BitmapDelta;
800   if (BitmapOffset < 0)
801     return error(
802         instrprof_error::malformed,
803         ("bitmap offset " + Twine(BitmapOffset) + " is negative").str());
804 
805   if (BitmapOffset >= BitmapEnd - BitmapStart)
806     return error(instrprof_error::malformed,
807                  ("bitmap offset " + Twine(BitmapOffset) +
808                   " is greater than the maximum bitmap offset " +
809                   Twine(BitmapEnd - BitmapStart - 1))
810                      .str());
811 
812   uint64_t MaxNumBitmapBytes =
813       (BitmapEnd - (BitmapStart + BitmapOffset)) / sizeof(uint8_t);
814   if (NumBitmapBytes > MaxNumBitmapBytes)
815     return error(instrprof_error::malformed,
816                  ("number of bitmap bytes " + Twine(NumBitmapBytes) +
817                   " is greater than the maximum number of bitmap bytes " +
818                   Twine(MaxNumBitmapBytes))
819                      .str());
820 
821   for (uint32_t I = 0; I < NumBitmapBytes; I++) {
822     const char *Ptr = BitmapStart + BitmapOffset + I;
823     Record.BitmapBytes.push_back(swap(*Ptr));
824   }
825 
826   return success();
827 }
828 
829 template <class IntPtrT>
830 Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
831     InstrProfRecord &Record) {
832   Record.clearValueData();
833   CurValueDataSize = 0;
834   // Need to match the logic in value profile dumper code in compiler-rt:
835   uint32_t NumValueKinds = 0;
836   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
837     NumValueKinds += (Data->NumValueSites[I] != 0);
838 
839   if (!NumValueKinds)
840     return success();
841 
842   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
843       ValueProfData::getValueProfData(
844           ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
845           getDataEndianness());
846 
847   if (Error E = VDataPtrOrErr.takeError())
848     return E;
849 
850   // Note that besides deserialization, this also performs the conversion for
851   // indirect call targets.  The function pointers from the raw profile are
852   // remapped into function name hashes.
853   VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
854   CurValueDataSize = VDataPtrOrErr.get()->getSize();
855   return success();
856 }
857 
858 template <class IntPtrT>
859 Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
860   // Keep reading profiles that consist of only headers and no profile data and
861   // counters.
862   while (atEnd())
863     // At this point, ValueDataStart field points to the next header.
864     if (Error E = readNextHeader(getNextHeaderPos()))
865       return error(std::move(E));
866 
867   // Read name and set it in Record.
868   if (Error E = readName(Record))
869     return error(std::move(E));
870 
871   // Read FuncHash and set it in Record.
872   if (Error E = readFuncHash(Record))
873     return error(std::move(E));
874 
875   // Read raw counts and set Record.
876   if (Error E = readRawCounts(Record))
877     return error(std::move(E));
878 
879   // Read raw bitmap bytes and set Record.
880   if (Error E = readRawBitmapBytes(Record))
881     return error(std::move(E));
882 
883   // Read value data and set Record.
884   if (Error E = readValueProfilingData(Record))
885     return error(std::move(E));
886 
887   // Iterate.
888   advanceData();
889   return success();
890 }
891 
892 template <class IntPtrT>
893 Error RawInstrProfReader<IntPtrT>::readBinaryIds(
894     std::vector<llvm::object::BuildID> &BinaryIds) {
895   BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
896                    this->BinaryIds.end());
897   return Error::success();
898 }
899 
900 template <class IntPtrT>
901 Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) {
902   if (!BinaryIds.empty())
903     printBinaryIdsInternal(OS, BinaryIds);
904   return Error::success();
905 }
906 
907 namespace llvm {
908 
909 template class RawInstrProfReader<uint32_t>;
910 template class RawInstrProfReader<uint64_t>;
911 
912 } // end namespace llvm
913 
914 InstrProfLookupTrait::hash_value_type
915 InstrProfLookupTrait::ComputeHash(StringRef K) {
916   return IndexedInstrProf::ComputeHash(HashType, K);
917 }
918 
919 using data_type = InstrProfLookupTrait::data_type;
920 using offset_type = InstrProfLookupTrait::offset_type;
921 
922 bool InstrProfLookupTrait::readValueProfilingData(
923     const unsigned char *&D, const unsigned char *const End) {
924   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
925       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
926 
927   if (VDataPtrOrErr.takeError())
928     return false;
929 
930   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
931   D += VDataPtrOrErr.get()->TotalSize;
932 
933   return true;
934 }
935 
936 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
937                                          offset_type N) {
938   using namespace support;
939 
940   // Check if the data is corrupt. If so, don't try to read it.
941   if (N % sizeof(uint64_t))
942     return data_type();
943 
944   DataBuffer.clear();
945   std::vector<uint64_t> CounterBuffer;
946   std::vector<uint8_t> BitmapByteBuffer;
947 
948   const unsigned char *End = D + N;
949   while (D < End) {
950     // Read hash.
951     if (D + sizeof(uint64_t) >= End)
952       return data_type();
953     uint64_t Hash = endian::readNext<uint64_t, llvm::endianness::little>(D);
954 
955     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
956     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
957     // If format version is different then read the number of counters.
958     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
959       if (D + sizeof(uint64_t) > End)
960         return data_type();
961       CountsSize = endian::readNext<uint64_t, llvm::endianness::little>(D);
962     }
963     // Read counter values.
964     if (D + CountsSize * sizeof(uint64_t) > End)
965       return data_type();
966 
967     CounterBuffer.clear();
968     CounterBuffer.reserve(CountsSize);
969     for (uint64_t J = 0; J < CountsSize; ++J)
970       CounterBuffer.push_back(
971           endian::readNext<uint64_t, llvm::endianness::little>(D));
972 
973     // Read bitmap bytes for GET_VERSION(FormatVersion) > 10.
974     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version10) {
975       uint64_t BitmapBytes = 0;
976       if (D + sizeof(uint64_t) > End)
977         return data_type();
978       BitmapBytes = endian::readNext<uint64_t, llvm::endianness::little>(D);
979       // Read bitmap byte values.
980       if (D + BitmapBytes * sizeof(uint8_t) > End)
981         return data_type();
982       BitmapByteBuffer.clear();
983       BitmapByteBuffer.reserve(BitmapBytes);
984       for (uint64_t J = 0; J < BitmapBytes; ++J)
985         BitmapByteBuffer.push_back(static_cast<uint8_t>(
986             endian::readNext<uint64_t, llvm::endianness::little>(D)));
987     }
988 
989     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
990                             std::move(BitmapByteBuffer));
991 
992     // Read value profiling data.
993     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
994         !readValueProfilingData(D, End)) {
995       DataBuffer.clear();
996       return data_type();
997     }
998   }
999   return DataBuffer;
1000 }
1001 
1002 template <typename HashTableImpl>
1003 Error InstrProfReaderIndex<HashTableImpl>::getRecords(
1004     StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
1005   auto Iter = HashTable->find(FuncName);
1006   if (Iter == HashTable->end())
1007     return make_error<InstrProfError>(instrprof_error::unknown_function);
1008 
1009   Data = (*Iter);
1010   if (Data.empty())
1011     return make_error<InstrProfError>(instrprof_error::malformed,
1012                                       "profile data is empty");
1013 
1014   return Error::success();
1015 }
1016 
1017 template <typename HashTableImpl>
1018 Error InstrProfReaderIndex<HashTableImpl>::getRecords(
1019     ArrayRef<NamedInstrProfRecord> &Data) {
1020   if (atEnd())
1021     return make_error<InstrProfError>(instrprof_error::eof);
1022 
1023   Data = *RecordIterator;
1024 
1025   if (Data.empty())
1026     return make_error<InstrProfError>(instrprof_error::malformed,
1027                                       "profile data is empty");
1028 
1029   return Error::success();
1030 }
1031 
1032 template <typename HashTableImpl>
1033 InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
1034     const unsigned char *Buckets, const unsigned char *const Payload,
1035     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
1036     uint64_t Version) {
1037   FormatVersion = Version;
1038   HashTable.reset(HashTableImpl::Create(
1039       Buckets, Payload, Base,
1040       typename HashTableImpl::InfoType(HashType, Version)));
1041   RecordIterator = HashTable->data_begin();
1042 }
1043 
1044 template <typename HashTableImpl>
1045 InstrProfKind InstrProfReaderIndex<HashTableImpl>::getProfileKind() const {
1046   return getProfileKindFromVersion(FormatVersion);
1047 }
1048 
1049 namespace {
1050 /// A remapper that does not apply any remappings.
1051 class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
1052   InstrProfReaderIndexBase &Underlying;
1053 
1054 public:
1055   InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
1056       : Underlying(Underlying) {}
1057 
1058   Error getRecords(StringRef FuncName,
1059                    ArrayRef<NamedInstrProfRecord> &Data) override {
1060     return Underlying.getRecords(FuncName, Data);
1061   }
1062 };
1063 } // namespace
1064 
1065 /// A remapper that applies remappings based on a symbol remapping file.
1066 template <typename HashTableImpl>
1067 class llvm::InstrProfReaderItaniumRemapper
1068     : public InstrProfReaderRemapper {
1069 public:
1070   InstrProfReaderItaniumRemapper(
1071       std::unique_ptr<MemoryBuffer> RemapBuffer,
1072       InstrProfReaderIndex<HashTableImpl> &Underlying)
1073       : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
1074   }
1075 
1076   /// Extract the original function name from a PGO function name.
1077   static StringRef extractName(StringRef Name) {
1078     // We can have multiple pieces separated by kGlobalIdentifierDelimiter (
1079     // semicolon now and colon in older profiles); there can be pieces both
1080     // before and after the mangled name. Find the first part that starts with
1081     // '_Z'; we'll assume that's the mangled name we want.
1082     std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
1083     while (true) {
1084       Parts = Parts.second.split(GlobalIdentifierDelimiter);
1085       if (Parts.first.starts_with("_Z"))
1086         return Parts.first;
1087       if (Parts.second.empty())
1088         return Name;
1089     }
1090   }
1091 
1092   /// Given a mangled name extracted from a PGO function name, and a new
1093   /// form for that mangled name, reconstitute the name.
1094   static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
1095                                StringRef Replacement,
1096                                SmallVectorImpl<char> &Out) {
1097     Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
1098     Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
1099     Out.insert(Out.end(), Replacement.begin(), Replacement.end());
1100     Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
1101   }
1102 
1103   Error populateRemappings() override {
1104     if (Error E = Remappings.read(*RemapBuffer))
1105       return E;
1106     for (StringRef Name : Underlying.HashTable->keys()) {
1107       StringRef RealName = extractName(Name);
1108       if (auto Key = Remappings.insert(RealName)) {
1109         // FIXME: We could theoretically map the same equivalence class to
1110         // multiple names in the profile data. If that happens, we should
1111         // return NamedInstrProfRecords from all of them.
1112         MappedNames.insert({Key, RealName});
1113       }
1114     }
1115     return Error::success();
1116   }
1117 
1118   Error getRecords(StringRef FuncName,
1119                    ArrayRef<NamedInstrProfRecord> &Data) override {
1120     StringRef RealName = extractName(FuncName);
1121     if (auto Key = Remappings.lookup(RealName)) {
1122       StringRef Remapped = MappedNames.lookup(Key);
1123       if (!Remapped.empty()) {
1124         if (RealName.begin() == FuncName.begin() &&
1125             RealName.end() == FuncName.end())
1126           FuncName = Remapped;
1127         else {
1128           // Try rebuilding the name from the given remapping.
1129           SmallString<256> Reconstituted;
1130           reconstituteName(FuncName, RealName, Remapped, Reconstituted);
1131           Error E = Underlying.getRecords(Reconstituted, Data);
1132           if (!E)
1133             return E;
1134 
1135           // If we failed because the name doesn't exist, fall back to asking
1136           // about the original name.
1137           if (Error Unhandled = handleErrors(
1138                   std::move(E), [](std::unique_ptr<InstrProfError> Err) {
1139                     return Err->get() == instrprof_error::unknown_function
1140                                ? Error::success()
1141                                : Error(std::move(Err));
1142                   }))
1143             return Unhandled;
1144         }
1145       }
1146     }
1147     return Underlying.getRecords(FuncName, Data);
1148   }
1149 
1150 private:
1151   /// The memory buffer containing the remapping configuration. Remappings
1152   /// holds pointers into this buffer.
1153   std::unique_ptr<MemoryBuffer> RemapBuffer;
1154 
1155   /// The mangling remapper.
1156   SymbolRemappingReader Remappings;
1157 
1158   /// Mapping from mangled name keys to the name used for the key in the
1159   /// profile data.
1160   /// FIXME: Can we store a location within the on-disk hash table instead of
1161   /// redoing lookup?
1162   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
1163 
1164   /// The real profile data reader.
1165   InstrProfReaderIndex<HashTableImpl> &Underlying;
1166 };
1167 
1168 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
1169   using namespace support;
1170 
1171   if (DataBuffer.getBufferSize() < 8)
1172     return false;
1173   uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>(
1174       DataBuffer.getBufferStart());
1175   // Verify that it's magical.
1176   return Magic == IndexedInstrProf::Magic;
1177 }
1178 
1179 const unsigned char *
1180 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
1181                                     const unsigned char *Cur, bool UseCS) {
1182   using namespace IndexedInstrProf;
1183   using namespace support;
1184 
1185   if (Version >= IndexedInstrProf::Version4) {
1186     const IndexedInstrProf::Summary *SummaryInLE =
1187         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
1188     uint64_t NFields = endian::byte_swap<uint64_t, llvm::endianness::little>(
1189         SummaryInLE->NumSummaryFields);
1190     uint64_t NEntries = endian::byte_swap<uint64_t, llvm::endianness::little>(
1191         SummaryInLE->NumCutoffEntries);
1192     uint32_t SummarySize =
1193         IndexedInstrProf::Summary::getSize(NFields, NEntries);
1194     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
1195         IndexedInstrProf::allocSummary(SummarySize);
1196 
1197     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
1198     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
1199     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
1200       Dst[I] = endian::byte_swap<uint64_t, llvm::endianness::little>(Src[I]);
1201 
1202     SummaryEntryVector DetailedSummary;
1203     for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
1204       const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
1205       DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
1206                                    Ent.NumBlocks);
1207     }
1208     std::unique_ptr<llvm::ProfileSummary> &Summary =
1209         UseCS ? this->CS_Summary : this->Summary;
1210 
1211     // initialize InstrProfSummary using the SummaryData from disk.
1212     Summary = std::make_unique<ProfileSummary>(
1213         UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
1214         DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1215         SummaryData->get(Summary::MaxBlockCount),
1216         SummaryData->get(Summary::MaxInternalBlockCount),
1217         SummaryData->get(Summary::MaxFunctionCount),
1218         SummaryData->get(Summary::TotalNumBlocks),
1219         SummaryData->get(Summary::TotalNumFunctions));
1220     return Cur + SummarySize;
1221   } else {
1222     // The older versions do not support a profile summary. This just computes
1223     // an empty summary, which will not result in accurate hot/cold detection.
1224     // We would need to call addRecord for all NamedInstrProfRecords to get the
1225     // correct summary. However, this version is old (prior to early 2016) and
1226     // has not been supporting an accurate summary for several years.
1227     InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
1228     Summary = Builder.getSummary();
1229     return Cur;
1230   }
1231 }
1232 
1233 Error IndexedMemProfReader::deserializeV2(const unsigned char *Start,
1234                                           const unsigned char *Ptr) {
1235   // The value returned from RecordTableGenerator.Emit.
1236   const uint64_t RecordTableOffset =
1237       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1238   // The offset in the stream right before invoking
1239   // FrameTableGenerator.Emit.
1240   const uint64_t FramePayloadOffset =
1241       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1242   // The value returned from FrameTableGenerator.Emit.
1243   const uint64_t FrameTableOffset =
1244       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1245 
1246   // The offset in the stream right before invoking
1247   // CallStackTableGenerator.Emit.
1248   uint64_t CallStackPayloadOffset = 0;
1249   // The value returned from CallStackTableGenerator.Emit.
1250   uint64_t CallStackTableOffset = 0;
1251   if (Version >= memprof::Version2) {
1252     CallStackPayloadOffset =
1253         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1254     CallStackTableOffset =
1255         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1256   }
1257 
1258   // Read the schema.
1259   auto SchemaOr = memprof::readMemProfSchema(Ptr);
1260   if (!SchemaOr)
1261     return SchemaOr.takeError();
1262   Schema = SchemaOr.get();
1263 
1264   // Now initialize the table reader with a pointer into data buffer.
1265   MemProfRecordTable.reset(MemProfRecordHashTable::Create(
1266       /*Buckets=*/Start + RecordTableOffset,
1267       /*Payload=*/Ptr,
1268       /*Base=*/Start, memprof::RecordLookupTrait(Version, Schema)));
1269 
1270   // Initialize the frame table reader with the payload and bucket offsets.
1271   MemProfFrameTable.reset(MemProfFrameHashTable::Create(
1272       /*Buckets=*/Start + FrameTableOffset,
1273       /*Payload=*/Start + FramePayloadOffset,
1274       /*Base=*/Start));
1275 
1276   if (Version >= memprof::Version2)
1277     MemProfCallStackTable.reset(MemProfCallStackHashTable::Create(
1278         /*Buckets=*/Start + CallStackTableOffset,
1279         /*Payload=*/Start + CallStackPayloadOffset,
1280         /*Base=*/Start));
1281 
1282   return Error::success();
1283 }
1284 
1285 Error IndexedMemProfReader::deserializeV3(const unsigned char *Start,
1286                                           const unsigned char *Ptr) {
1287   // The offset in the stream right before invoking
1288   // CallStackTableGenerator.Emit.
1289   const uint64_t CallStackPayloadOffset =
1290       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1291   // The offset in the stream right before invoking RecordTableGenerator.Emit.
1292   const uint64_t RecordPayloadOffset =
1293       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1294   // The value returned from RecordTableGenerator.Emit.
1295   const uint64_t RecordTableOffset =
1296       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1297 
1298   // Read the schema.
1299   auto SchemaOr = memprof::readMemProfSchema(Ptr);
1300   if (!SchemaOr)
1301     return SchemaOr.takeError();
1302   Schema = SchemaOr.get();
1303 
1304   FrameBase = Ptr;
1305   CallStackBase = Start + CallStackPayloadOffset;
1306 
1307   // Compute the number of elements in the radix tree array.  Since we use this
1308   // to reserve enough bits in a BitVector, it's totally OK if we overestimate
1309   // this number a little bit because of padding just before the next section.
1310   RadixTreeSize = (RecordPayloadOffset - CallStackPayloadOffset) /
1311                   sizeof(memprof::LinearFrameId);
1312 
1313   // Now initialize the table reader with a pointer into data buffer.
1314   MemProfRecordTable.reset(MemProfRecordHashTable::Create(
1315       /*Buckets=*/Start + RecordTableOffset,
1316       /*Payload=*/Start + RecordPayloadOffset,
1317       /*Base=*/Start, memprof::RecordLookupTrait(memprof::Version3, Schema)));
1318 
1319   return Error::success();
1320 }
1321 
1322 Error IndexedMemProfReader::deserialize(const unsigned char *Start,
1323                                         uint64_t MemProfOffset) {
1324   const unsigned char *Ptr = Start + MemProfOffset;
1325 
1326   // Read the MemProf version number.
1327   const uint64_t FirstWord =
1328       support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1329 
1330   if (FirstWord == memprof::Version2 || FirstWord == memprof::Version3) {
1331     // Everything is good.  We can proceed to deserialize the rest.
1332     Version = static_cast<memprof::IndexedVersion>(FirstWord);
1333   } else {
1334     return make_error<InstrProfError>(
1335         instrprof_error::unsupported_version,
1336         formatv("MemProf version {} not supported; "
1337                 "requires version between {} and {}, inclusive",
1338                 FirstWord, memprof::MinimumSupportedVersion,
1339                 memprof::MaximumSupportedVersion));
1340   }
1341 
1342   switch (Version) {
1343   case memprof::Version2:
1344     if (Error E = deserializeV2(Start, Ptr))
1345       return E;
1346     break;
1347   case memprof::Version3:
1348     if (Error E = deserializeV3(Start, Ptr))
1349       return E;
1350     break;
1351   }
1352 
1353   return Error::success();
1354 }
1355 
1356 Error IndexedInstrProfReader::readHeader() {
1357   using namespace support;
1358 
1359   const unsigned char *Start =
1360       (const unsigned char *)DataBuffer->getBufferStart();
1361   const unsigned char *Cur = Start;
1362   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1363     return error(instrprof_error::truncated);
1364 
1365   auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
1366   if (!HeaderOr)
1367     return HeaderOr.takeError();
1368 
1369   const IndexedInstrProf::Header *Header = &HeaderOr.get();
1370   Cur += Header->size();
1371 
1372   Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur,
1373                     /* UseCS */ false);
1374   if (Header->Version & VARIANT_MASK_CSIR_PROF)
1375     Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur,
1376                       /* UseCS */ true);
1377   // Read the hash type and start offset.
1378   IndexedInstrProf::HashT HashType =
1379       static_cast<IndexedInstrProf::HashT>(Header->HashType);
1380   if (HashType > IndexedInstrProf::HashT::Last)
1381     return error(instrprof_error::unsupported_hash_type);
1382 
1383   // The hash table with profile counts comes next.
1384   auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1385       Start + Header->HashOffset, Cur, Start, HashType, Header->Version);
1386 
1387   // The MemProfOffset field in the header is only valid when the format
1388   // version is higher than 8 (when it was introduced).
1389   if (Header->getIndexedProfileVersion() >= 8 &&
1390       Header->Version & VARIANT_MASK_MEMPROF) {
1391     if (Error E = MemProfReader.deserialize(Start, Header->MemProfOffset))
1392       return E;
1393   }
1394 
1395   // BinaryIdOffset field in the header is only valid when the format version
1396   // is higher than 9 (when it was introduced).
1397   if (Header->getIndexedProfileVersion() >= 9) {
1398     const unsigned char *Ptr = Start + Header->BinaryIdOffset;
1399     // Read binary ids size.
1400     uint64_t BinaryIdsSize =
1401         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1402     if (BinaryIdsSize % sizeof(uint64_t))
1403       return error(instrprof_error::bad_header);
1404     // Set the binary ids start.
1405     BinaryIdsBuffer = ArrayRef<uint8_t>(Ptr, BinaryIdsSize);
1406     if (Ptr > (const unsigned char *)DataBuffer->getBufferEnd())
1407       return make_error<InstrProfError>(instrprof_error::malformed,
1408                                         "corrupted binary ids");
1409   }
1410 
1411   if (Header->getIndexedProfileVersion() >= 12) {
1412     const unsigned char *Ptr = Start + Header->VTableNamesOffset;
1413 
1414     uint64_t CompressedVTableNamesLen =
1415         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1416 
1417     // Writer first writes the length of compressed string, and then the actual
1418     // content.
1419     const char *VTableNamePtr = (const char *)Ptr;
1420     if (VTableNamePtr > (const char *)DataBuffer->getBufferEnd())
1421       return make_error<InstrProfError>(instrprof_error::truncated);
1422 
1423     VTableName = StringRef(VTableNamePtr, CompressedVTableNamesLen);
1424   }
1425 
1426   if (Header->getIndexedProfileVersion() >= 10 &&
1427       Header->Version & VARIANT_MASK_TEMPORAL_PROF) {
1428     const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset;
1429     const auto *PtrEnd = (const unsigned char *)DataBuffer->getBufferEnd();
1430     // Expect at least two 64 bit fields: NumTraces, and TraceStreamSize
1431     if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1432       return error(instrprof_error::truncated);
1433     const uint64_t NumTraces =
1434         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1435     TemporalProfTraceStreamSize =
1436         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1437     for (unsigned i = 0; i < NumTraces; i++) {
1438       // Expect at least two 64 bit fields: Weight and NumFunctions
1439       if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1440         return error(instrprof_error::truncated);
1441       TemporalProfTraceTy Trace;
1442       Trace.Weight =
1443           support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1444       const uint64_t NumFunctions =
1445           support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1446       // Expect at least NumFunctions 64 bit fields
1447       if (Ptr + NumFunctions * sizeof(uint64_t) > PtrEnd)
1448         return error(instrprof_error::truncated);
1449       for (unsigned j = 0; j < NumFunctions; j++) {
1450         const uint64_t NameRef =
1451             support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1452         Trace.FunctionNameRefs.push_back(NameRef);
1453       }
1454       TemporalProfTraces.push_back(std::move(Trace));
1455     }
1456   }
1457 
1458   // Load the remapping table now if requested.
1459   if (RemappingBuffer) {
1460     Remapper =
1461         std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1462             std::move(RemappingBuffer), *IndexPtr);
1463     if (Error E = Remapper->populateRemappings())
1464       return E;
1465   } else {
1466     Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1467   }
1468   Index = std::move(IndexPtr);
1469 
1470   return success();
1471 }
1472 
1473 InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
1474   if (Symtab)
1475     return *Symtab;
1476 
1477   auto NewSymtab = std::make_unique<InstrProfSymtab>();
1478 
1479   if (Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) {
1480     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
1481     consumeError(error(ErrCode, Msg));
1482   }
1483 
1484   // finalizeSymtab is called inside populateSymtab.
1485   if (Error E = Index->populateSymtab(*NewSymtab)) {
1486     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
1487     consumeError(error(ErrCode, Msg));
1488   }
1489 
1490   Symtab = std::move(NewSymtab);
1491   return *Symtab;
1492 }
1493 
1494 Expected<InstrProfRecord> IndexedInstrProfReader::getInstrProfRecord(
1495     StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName,
1496     uint64_t *MismatchedFuncSum) {
1497   ArrayRef<NamedInstrProfRecord> Data;
1498   uint64_t FuncSum = 0;
1499   auto Err = Remapper->getRecords(FuncName, Data);
1500   if (Err) {
1501     // If we don't find FuncName, try DeprecatedFuncName to handle profiles
1502     // built by older compilers.
1503     auto Err2 =
1504         handleErrors(std::move(Err), [&](const InstrProfError &IE) -> Error {
1505           if (IE.get() != instrprof_error::unknown_function)
1506             return make_error<InstrProfError>(IE);
1507           if (auto Err = Remapper->getRecords(DeprecatedFuncName, Data))
1508             return Err;
1509           return Error::success();
1510         });
1511     if (Err2)
1512       return std::move(Err2);
1513   }
1514   // Found it. Look for counters with the right hash.
1515 
1516   // A flag to indicate if the records are from the same type
1517   // of profile (i.e cs vs nocs).
1518   bool CSBitMatch = false;
1519   auto getFuncSum = [](ArrayRef<uint64_t> Counts) {
1520     uint64_t ValueSum = 0;
1521     for (uint64_t CountValue : Counts) {
1522       if (CountValue == (uint64_t)-1)
1523         continue;
1524       // Handle overflow -- if that happens, return max.
1525       if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1526         return std::numeric_limits<uint64_t>::max();
1527       ValueSum += CountValue;
1528     }
1529     return ValueSum;
1530   };
1531 
1532   for (const NamedInstrProfRecord &I : Data) {
1533     // Check for a match and fill the vector if there is one.
1534     if (I.Hash == FuncHash)
1535       return std::move(I);
1536     if (NamedInstrProfRecord::hasCSFlagInHash(I.Hash) ==
1537         NamedInstrProfRecord::hasCSFlagInHash(FuncHash)) {
1538       CSBitMatch = true;
1539       if (MismatchedFuncSum == nullptr)
1540         continue;
1541       FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
1542     }
1543   }
1544   if (CSBitMatch) {
1545     if (MismatchedFuncSum != nullptr)
1546       *MismatchedFuncSum = FuncSum;
1547     return error(instrprof_error::hash_mismatch);
1548   }
1549   return error(instrprof_error::unknown_function);
1550 }
1551 
1552 static Expected<memprof::MemProfRecord>
1553 getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord,
1554                    MemProfFrameHashTable &MemProfFrameTable,
1555                    MemProfCallStackHashTable &MemProfCallStackTable) {
1556   memprof::FrameIdConverter<MemProfFrameHashTable> FrameIdConv(
1557       MemProfFrameTable);
1558 
1559   memprof::CallStackIdConverter<MemProfCallStackHashTable> CSIdConv(
1560       MemProfCallStackTable, FrameIdConv);
1561 
1562   memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv);
1563 
1564   // Check that all call stack ids were successfully converted to call stacks.
1565   if (CSIdConv.LastUnmappedId) {
1566     return make_error<InstrProfError>(
1567         instrprof_error::hash_mismatch,
1568         "memprof call stack not found for call stack id " +
1569             Twine(*CSIdConv.LastUnmappedId));
1570   }
1571 
1572   // Check that all frame ids were successfully converted to frames.
1573   if (FrameIdConv.LastUnmappedId) {
1574     return make_error<InstrProfError>(instrprof_error::hash_mismatch,
1575                                       "memprof frame not found for frame id " +
1576                                           Twine(*FrameIdConv.LastUnmappedId));
1577   }
1578 
1579   return Record;
1580 }
1581 
1582 static Expected<memprof::MemProfRecord>
1583 getMemProfRecordV3(const memprof::IndexedMemProfRecord &IndexedRecord,
1584                    const unsigned char *FrameBase,
1585                    const unsigned char *CallStackBase) {
1586   memprof::LinearFrameIdConverter FrameIdConv(FrameBase);
1587   memprof::LinearCallStackIdConverter CSIdConv(CallStackBase, FrameIdConv);
1588   memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv);
1589   return Record;
1590 }
1591 
1592 Expected<memprof::MemProfRecord>
1593 IndexedMemProfReader::getMemProfRecord(const uint64_t FuncNameHash) const {
1594   // TODO: Add memprof specific errors.
1595   if (MemProfRecordTable == nullptr)
1596     return make_error<InstrProfError>(instrprof_error::invalid_prof,
1597                                       "no memprof data available in profile");
1598   auto Iter = MemProfRecordTable->find(FuncNameHash);
1599   if (Iter == MemProfRecordTable->end())
1600     return make_error<InstrProfError>(
1601         instrprof_error::unknown_function,
1602         "memprof record not found for function hash " + Twine(FuncNameHash));
1603 
1604   const memprof::IndexedMemProfRecord &IndexedRecord = *Iter;
1605   switch (Version) {
1606   case memprof::Version2:
1607     assert(MemProfFrameTable && "MemProfFrameTable must be available");
1608     assert(MemProfCallStackTable && "MemProfCallStackTable must be available");
1609     return getMemProfRecordV2(IndexedRecord, *MemProfFrameTable,
1610                               *MemProfCallStackTable);
1611   case memprof::Version3:
1612     assert(!MemProfFrameTable && "MemProfFrameTable must not be available");
1613     assert(!MemProfCallStackTable &&
1614            "MemProfCallStackTable must not be available");
1615     assert(FrameBase && "FrameBase must be available");
1616     assert(CallStackBase && "CallStackBase must be available");
1617     return getMemProfRecordV3(IndexedRecord, FrameBase, CallStackBase);
1618   }
1619 
1620   return make_error<InstrProfError>(
1621       instrprof_error::unsupported_version,
1622       formatv("MemProf version {} not supported; "
1623               "requires version between {} and {}, inclusive",
1624               Version, memprof::MinimumSupportedVersion,
1625               memprof::MaximumSupportedVersion));
1626 }
1627 
1628 DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>>
1629 IndexedMemProfReader::getMemProfCallerCalleePairs() const {
1630   assert(MemProfRecordTable);
1631   assert(Version == memprof::Version3);
1632 
1633   memprof::LinearFrameIdConverter FrameIdConv(FrameBase);
1634   memprof::CallerCalleePairExtractor Extractor(CallStackBase, FrameIdConv,
1635                                                RadixTreeSize);
1636 
1637   // The set of linear call stack IDs that we need to traverse from.  We expect
1638   // the set to be dense, so we use a BitVector.
1639   BitVector Worklist(RadixTreeSize);
1640 
1641   // Collect the set of linear call stack IDs.  Since we expect a lot of
1642   // duplicates, we first collect them in the form of a bit vector before
1643   // processing them.
1644   for (const memprof::IndexedMemProfRecord &IndexedRecord :
1645        MemProfRecordTable->data()) {
1646     for (const memprof::IndexedAllocationInfo &IndexedAI :
1647          IndexedRecord.AllocSites)
1648       Worklist.set(IndexedAI.CSId);
1649   }
1650 
1651   // Collect caller-callee pairs for each linear call stack ID in Worklist.
1652   for (unsigned CS : Worklist.set_bits())
1653     Extractor(CS);
1654 
1655   DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>> Pairs =
1656       std::move(Extractor.CallerCalleePairs);
1657 
1658   // Sort each call list by the source location.
1659   for (auto &[CallerGUID, CallList] : Pairs) {
1660     llvm::sort(CallList);
1661     CallList.erase(llvm::unique(CallList), CallList.end());
1662   }
1663 
1664   return Pairs;
1665 }
1666 
1667 memprof::AllMemProfData IndexedMemProfReader::getAllMemProfData() const {
1668   memprof::AllMemProfData AllMemProfData;
1669   AllMemProfData.HeapProfileRecords.reserve(
1670       MemProfRecordTable->getNumEntries());
1671   for (uint64_t Key : MemProfRecordTable->keys()) {
1672     auto Record = getMemProfRecord(Key);
1673     if (Record.takeError())
1674       continue;
1675     memprof::GUIDMemProfRecordPair Pair;
1676     Pair.GUID = Key;
1677     Pair.Record = std::move(*Record);
1678     AllMemProfData.HeapProfileRecords.push_back(std::move(Pair));
1679   }
1680   return AllMemProfData;
1681 }
1682 
1683 Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
1684                                                 uint64_t FuncHash,
1685                                                 std::vector<uint64_t> &Counts) {
1686   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
1687   if (Error E = Record.takeError())
1688     return error(std::move(E));
1689 
1690   Counts = Record.get().Counts;
1691   return success();
1692 }
1693 
1694 Error IndexedInstrProfReader::getFunctionBitmap(StringRef FuncName,
1695                                                 uint64_t FuncHash,
1696                                                 BitVector &Bitmap) {
1697   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
1698   if (Error E = Record.takeError())
1699     return error(std::move(E));
1700 
1701   const auto &BitmapBytes = Record.get().BitmapBytes;
1702   size_t I = 0, E = BitmapBytes.size();
1703   Bitmap.resize(E * CHAR_BIT);
1704   BitVector::apply(
1705       [&](auto X) {
1706         using XTy = decltype(X);
1707         alignas(XTy) uint8_t W[sizeof(X)];
1708         size_t N = std::min(E - I, sizeof(W));
1709         std::memset(W, 0, sizeof(W));
1710         std::memcpy(W, &BitmapBytes[I], N);
1711         I += N;
1712         return support::endian::read<XTy, llvm::endianness::little,
1713                                      support::aligned>(W);
1714       },
1715       Bitmap, Bitmap);
1716   assert(I == E);
1717 
1718   return success();
1719 }
1720 
1721 Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
1722   ArrayRef<NamedInstrProfRecord> Data;
1723 
1724   Error E = Index->getRecords(Data);
1725   if (E)
1726     return error(std::move(E));
1727 
1728   Record = Data[RecordIndex++];
1729   if (RecordIndex >= Data.size()) {
1730     Index->advanceToNextKey();
1731     RecordIndex = 0;
1732   }
1733   return success();
1734 }
1735 
1736 Error IndexedInstrProfReader::readBinaryIds(
1737     std::vector<llvm::object::BuildID> &BinaryIds) {
1738   return readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer, BinaryIds,
1739                                llvm::endianness::little);
1740 }
1741 
1742 Error IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) {
1743   std::vector<llvm::object::BuildID> BinaryIds;
1744   if (Error E = readBinaryIds(BinaryIds))
1745     return E;
1746   printBinaryIdsInternal(OS, BinaryIds);
1747   return Error::success();
1748 }
1749 
1750 void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) {
1751   uint64_t NumFuncs = 0;
1752   for (const auto &Func : *this) {
1753     if (isIRLevelProfile()) {
1754       bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
1755       if (FuncIsCS != IsCS)
1756         continue;
1757     }
1758     Func.accumulateCounts(Sum);
1759     ++NumFuncs;
1760   }
1761   Sum.NumEntries = NumFuncs;
1762 }
1763