1 //===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===//
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 instrumentation
10 // based PGO and coverage.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
15 #define LLVM_PROFILEDATA_INSTRPROFREADER_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/IR/ProfileSummary.h"
20 #include "llvm/ProfileData/InstrProf.h"
21 #include "llvm/ProfileData/InstrProfCorrelator.h"
22 #include "llvm/ProfileData/MemProf.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/LineIterator.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/OnDiskHashTable.h"
28 #include "llvm/Support/SwapByteOrder.h"
29 #include <algorithm>
30 #include <cassert>
31 #include <cstddef>
32 #include <cstdint>
33 #include <iterator>
34 #include <memory>
35 #include <utility>
36 #include <vector>
37 
38 namespace llvm {
39 
40 class InstrProfReader;
41 
42 /// A file format agnostic iterator over profiling data.
43 template <class record_type = NamedInstrProfRecord,
44           class reader_type = InstrProfReader>
45 class InstrProfIterator {
46 public:
47   using iterator_category = std::input_iterator_tag;
48   using value_type = record_type;
49   using difference_type = std::ptrdiff_t;
50   using pointer = value_type *;
51   using reference = value_type &;
52 
53 private:
54   reader_type *Reader = nullptr;
55   value_type Record;
56 
57   void increment() {
58     if (Error E = Reader->readNextRecord(Record)) {
59       // Handle errors in the reader.
60       InstrProfError::take(std::move(E));
61       *this = InstrProfIterator();
62     }
63   }
64 
65 public:
66   InstrProfIterator() = default;
67   InstrProfIterator(reader_type *Reader) : Reader(Reader) { increment(); }
68 
69   InstrProfIterator &operator++() {
70     increment();
71     return *this;
72   }
73   bool operator==(const InstrProfIterator &RHS) const {
74     return Reader == RHS.Reader;
75   }
76   bool operator!=(const InstrProfIterator &RHS) const {
77     return Reader != RHS.Reader;
78   }
79   value_type &operator*() { return Record; }
80   value_type *operator->() { return &Record; }
81 };
82 
83 /// Base class and interface for reading profiling data of any known instrprof
84 /// format. Provides an iterator over NamedInstrProfRecords.
85 class InstrProfReader {
86   instrprof_error LastError = instrprof_error::success;
87   std::string LastErrorMsg;
88 
89 public:
90   InstrProfReader() = default;
91   virtual ~InstrProfReader() = default;
92 
93   /// Read the header.  Required before reading first record.
94   virtual Error readHeader() = 0;
95 
96   /// Read a single record.
97   virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
98 
99   /// Print binary ids on stream OS.
100   virtual Error printBinaryIds(raw_ostream &OS) { return success(); };
101 
102   /// Iterator over profile data.
103   InstrProfIterator<> begin() { return InstrProfIterator<>(this); }
104   InstrProfIterator<> end() { return InstrProfIterator<>(); }
105 
106   virtual bool isIRLevelProfile() const = 0;
107 
108   virtual bool hasCSIRLevelProfile() const = 0;
109 
110   virtual bool instrEntryBBEnabled() const = 0;
111 
112   /// Return true if we must provide debug info to create PGO profiles.
113   virtual bool useDebugInfoCorrelate() const { return false; }
114 
115   /// Return true if the profile has single byte counters representing coverage.
116   virtual bool hasSingleByteCoverage() const = 0;
117 
118   /// Return true if the profile only instruments function entries.
119   virtual bool functionEntryOnly() const = 0;
120 
121   /// Returns a BitsetEnum describing the attributes of the profile. To check
122   /// individual attributes prefer using the helpers above.
123   virtual InstrProfKind getProfileKind() const = 0;
124 
125   /// Return the PGO symtab. There are three different readers:
126   /// Raw, Text, and Indexed profile readers. The first two types
127   /// of readers are used only by llvm-profdata tool, while the indexed
128   /// profile reader is also used by llvm-cov tool and the compiler (
129   /// backend or frontend). Since creating PGO symtab can create
130   /// significant runtime and memory overhead (as it touches data
131   /// for the whole program), InstrProfSymtab for the indexed profile
132   /// reader should be created on demand and it is recommended to be
133   /// only used for dumping purpose with llvm-proftool, not with the
134   /// compiler.
135   virtual InstrProfSymtab &getSymtab() = 0;
136 
137   /// Compute the sum of counts and return in Sum.
138   void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
139 
140 protected:
141   std::unique_ptr<InstrProfSymtab> Symtab;
142 
143   /// Set the current error and return same.
144   Error error(instrprof_error Err, const std::string &ErrMsg = "") {
145     LastError = Err;
146     LastErrorMsg = ErrMsg;
147     if (Err == instrprof_error::success)
148       return Error::success();
149     return make_error<InstrProfError>(Err, ErrMsg);
150   }
151 
152   Error error(Error &&E) {
153     handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
154       LastError = IPE.get();
155       LastErrorMsg = IPE.getMessage();
156     });
157     return make_error<InstrProfError>(LastError, LastErrorMsg);
158   }
159 
160   /// Clear the current error and return a successful one.
161   Error success() { return error(instrprof_error::success); }
162 
163 public:
164   /// Return true if the reader has finished reading the profile data.
165   bool isEOF() { return LastError == instrprof_error::eof; }
166 
167   /// Return true if the reader encountered an error reading profiling data.
168   bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
169 
170   /// Get the current error.
171   Error getError() {
172     if (hasError())
173       return make_error<InstrProfError>(LastError, LastErrorMsg);
174     return Error::success();
175   }
176 
177   /// Factory method to create an appropriately typed reader for the given
178   /// instrprof file.
179   static Expected<std::unique_ptr<InstrProfReader>>
180   create(const Twine &Path, const InstrProfCorrelator *Correlator = nullptr);
181 
182   static Expected<std::unique_ptr<InstrProfReader>>
183   create(std::unique_ptr<MemoryBuffer> Buffer,
184          const InstrProfCorrelator *Correlator = nullptr);
185 };
186 
187 /// Reader for the simple text based instrprof format.
188 ///
189 /// This format is a simple text format that's suitable for test data. Records
190 /// are separated by one or more blank lines, and record fields are separated by
191 /// new lines.
192 ///
193 /// Each record consists of a function name, a function hash, a number of
194 /// counters, and then each counter value, in that order.
195 class TextInstrProfReader : public InstrProfReader {
196 private:
197   /// The profile data file contents.
198   std::unique_ptr<MemoryBuffer> DataBuffer;
199   /// Iterator over the profile data.
200   line_iterator Line;
201   /// The attributes of the current profile.
202   InstrProfKind ProfileKind = InstrProfKind::Unknown;
203 
204   Error readValueProfileData(InstrProfRecord &Record);
205 
206 public:
207   TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
208       : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
209   TextInstrProfReader(const TextInstrProfReader &) = delete;
210   TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
211 
212   /// Return true if the given buffer is in text instrprof format.
213   static bool hasFormat(const MemoryBuffer &Buffer);
214 
215   bool isIRLevelProfile() const override {
216     return static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation);
217   }
218 
219   bool hasCSIRLevelProfile() const override {
220     return static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive);
221   }
222 
223   bool instrEntryBBEnabled() const override {
224     return static_cast<bool>(ProfileKind &
225                              InstrProfKind::FunctionEntryInstrumentation);
226   }
227 
228   bool hasSingleByteCoverage() const override {
229     return static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage);
230   }
231 
232   bool functionEntryOnly() const override {
233     return static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly);
234   }
235 
236   InstrProfKind getProfileKind() const override { return ProfileKind; }
237 
238   /// Read the header.
239   Error readHeader() override;
240 
241   /// Read a single record.
242   Error readNextRecord(NamedInstrProfRecord &Record) override;
243 
244   InstrProfSymtab &getSymtab() override {
245     assert(Symtab.get());
246     return *Symtab.get();
247   }
248 };
249 
250 /// Reader for the raw instrprof binary format from runtime.
251 ///
252 /// This format is a raw memory dump of the instrumentation-based profiling data
253 /// from the runtime.  It has no index.
254 ///
255 /// Templated on the unsigned type whose size matches pointers on the platform
256 /// that wrote the profile.
257 template <class IntPtrT>
258 class RawInstrProfReader : public InstrProfReader {
259 private:
260   /// The profile data file contents.
261   std::unique_ptr<MemoryBuffer> DataBuffer;
262   /// If available, this hold the ProfileData array used to correlate raw
263   /// instrumentation data to their functions.
264   const InstrProfCorrelatorImpl<IntPtrT> *Correlator;
265   bool ShouldSwapBytes;
266   // The value of the version field of the raw profile data header. The lower 56
267   // bits specifies the format version and the most significant 8 bits specify
268   // the variant types of the profile.
269   uint64_t Version;
270   uint64_t CountersDelta;
271   uint64_t NamesDelta;
272   const RawInstrProf::ProfileData<IntPtrT> *Data;
273   const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
274   const char *CountersStart;
275   const char *CountersEnd;
276   const char *NamesStart;
277   const char *NamesEnd;
278   // After value profile is all read, this pointer points to
279   // the header of next profile data (if exists)
280   const uint8_t *ValueDataStart;
281   uint32_t ValueKindLast;
282   uint32_t CurValueDataSize;
283 
284   uint64_t BinaryIdsSize;
285   const uint8_t *BinaryIdsStart;
286 
287 public:
288   RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer,
289                      const InstrProfCorrelator *Correlator)
290       : DataBuffer(std::move(DataBuffer)),
291         Correlator(dyn_cast_or_null<const InstrProfCorrelatorImpl<IntPtrT>>(
292             Correlator)) {}
293   RawInstrProfReader(const RawInstrProfReader &) = delete;
294   RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
295 
296   static bool hasFormat(const MemoryBuffer &DataBuffer);
297   Error readHeader() override;
298   Error readNextRecord(NamedInstrProfRecord &Record) override;
299   Error printBinaryIds(raw_ostream &OS) override;
300 
301   bool isIRLevelProfile() const override {
302     return (Version & VARIANT_MASK_IR_PROF) != 0;
303   }
304 
305   bool hasCSIRLevelProfile() const override {
306     return (Version & VARIANT_MASK_CSIR_PROF) != 0;
307   }
308 
309   bool instrEntryBBEnabled() const override {
310     return (Version & VARIANT_MASK_INSTR_ENTRY) != 0;
311   }
312 
313   bool useDebugInfoCorrelate() const override {
314     return (Version & VARIANT_MASK_DBG_CORRELATE) != 0;
315   }
316 
317   bool hasSingleByteCoverage() const override {
318     return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0;
319   }
320 
321   bool functionEntryOnly() const override {
322     return (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0;
323   }
324 
325   /// Returns a BitsetEnum describing the attributes of the raw instr profile.
326   InstrProfKind getProfileKind() const override;
327 
328   InstrProfSymtab &getSymtab() override {
329     assert(Symtab.get());
330     return *Symtab.get();
331   }
332 
333 private:
334   Error createSymtab(InstrProfSymtab &Symtab);
335   Error readNextHeader(const char *CurrentPos);
336   Error readHeader(const RawInstrProf::Header &Header);
337 
338   template <class IntT> IntT swap(IntT Int) const {
339     return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
340   }
341 
342   support::endianness getDataEndianness() const {
343     support::endianness HostEndian = getHostEndianness();
344     if (!ShouldSwapBytes)
345       return HostEndian;
346     if (HostEndian == support::little)
347       return support::big;
348     else
349       return support::little;
350   }
351 
352   inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
353     return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
354   }
355 
356   Error readName(NamedInstrProfRecord &Record);
357   Error readFuncHash(NamedInstrProfRecord &Record);
358   Error readRawCounts(InstrProfRecord &Record);
359   Error readValueProfilingData(InstrProfRecord &Record);
360   bool atEnd() const { return Data == DataEnd; }
361 
362   void advanceData() {
363     // `CountersDelta` is a constant zero when using debug info correlation.
364     if (!Correlator) {
365       // The initial CountersDelta is the in-memory address difference between
366       // the data and counts sections:
367       // start(__llvm_prf_cnts) - start(__llvm_prf_data)
368       // As we advance to the next record, we maintain the correct CountersDelta
369       // with respect to the next record.
370       CountersDelta -= sizeof(*Data);
371     }
372     Data++;
373     ValueDataStart += CurValueDataSize;
374   }
375 
376   const char *getNextHeaderPos() const {
377       assert(atEnd());
378       return (const char *)ValueDataStart;
379   }
380 
381   StringRef getName(uint64_t NameRef) const {
382     return Symtab->getFuncName(swap(NameRef));
383   }
384 
385   int getCounterTypeSize() const {
386     return hasSingleByteCoverage() ? sizeof(uint8_t) : sizeof(uint64_t);
387   }
388 };
389 
390 using RawInstrProfReader32 = RawInstrProfReader<uint32_t>;
391 using RawInstrProfReader64 = RawInstrProfReader<uint64_t>;
392 
393 namespace IndexedInstrProf {
394 
395 enum class HashT : uint32_t;
396 
397 } // end namespace IndexedInstrProf
398 
399 /// Trait for lookups into the on-disk hash table for the binary instrprof
400 /// format.
401 class InstrProfLookupTrait {
402   std::vector<NamedInstrProfRecord> DataBuffer;
403   IndexedInstrProf::HashT HashType;
404   unsigned FormatVersion;
405   // Endianness of the input value profile data.
406   // It should be LE by default, but can be changed
407   // for testing purpose.
408   support::endianness ValueProfDataEndianness = support::little;
409 
410 public:
411   InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
412       : HashType(HashType), FormatVersion(FormatVersion) {}
413 
414   using data_type = ArrayRef<NamedInstrProfRecord>;
415 
416   using internal_key_type = StringRef;
417   using external_key_type = StringRef;
418   using hash_value_type = uint64_t;
419   using offset_type = uint64_t;
420 
421   static bool EqualKey(StringRef A, StringRef B) { return A == B; }
422   static StringRef GetInternalKey(StringRef K) { return K; }
423   static StringRef GetExternalKey(StringRef K) { return K; }
424 
425   hash_value_type ComputeHash(StringRef K);
426 
427   static std::pair<offset_type, offset_type>
428   ReadKeyDataLength(const unsigned char *&D) {
429     using namespace support;
430 
431     offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
432     offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
433     return std::make_pair(KeyLen, DataLen);
434   }
435 
436   StringRef ReadKey(const unsigned char *D, offset_type N) {
437     return StringRef((const char *)D, N);
438   }
439 
440   bool readValueProfilingData(const unsigned char *&D,
441                               const unsigned char *const End);
442   data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
443 
444   // Used for testing purpose only.
445   void setValueProfDataEndianness(support::endianness Endianness) {
446     ValueProfDataEndianness = Endianness;
447   }
448 };
449 
450 struct InstrProfReaderIndexBase {
451   virtual ~InstrProfReaderIndexBase() = default;
452 
453   // Read all the profile records with the same key pointed to the current
454   // iterator.
455   virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
456 
457   // Read all the profile records with the key equal to FuncName
458   virtual Error getRecords(StringRef FuncName,
459                                      ArrayRef<NamedInstrProfRecord> &Data) = 0;
460   virtual void advanceToNextKey() = 0;
461   virtual bool atEnd() const = 0;
462   virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
463   virtual uint64_t getVersion() const = 0;
464   virtual bool isIRLevelProfile() const = 0;
465   virtual bool hasCSIRLevelProfile() const = 0;
466   virtual bool instrEntryBBEnabled() const = 0;
467   virtual bool hasSingleByteCoverage() const = 0;
468   virtual bool functionEntryOnly() const = 0;
469   virtual InstrProfKind getProfileKind() const = 0;
470   virtual Error populateSymtab(InstrProfSymtab &) = 0;
471 };
472 
473 using OnDiskHashTableImplV3 =
474     OnDiskIterableChainedHashTable<InstrProfLookupTrait>;
475 
476 using MemProfRecordHashTable =
477     OnDiskIterableChainedHashTable<memprof::RecordLookupTrait>;
478 using MemProfFrameHashTable =
479     OnDiskIterableChainedHashTable<memprof::FrameLookupTrait>;
480 
481 template <typename HashTableImpl>
482 class InstrProfReaderItaniumRemapper;
483 
484 template <typename HashTableImpl>
485 class InstrProfReaderIndex : public InstrProfReaderIndexBase {
486 private:
487   std::unique_ptr<HashTableImpl> HashTable;
488   typename HashTableImpl::data_iterator RecordIterator;
489   uint64_t FormatVersion;
490 
491   friend class InstrProfReaderItaniumRemapper<HashTableImpl>;
492 
493 public:
494   InstrProfReaderIndex(const unsigned char *Buckets,
495                        const unsigned char *const Payload,
496                        const unsigned char *const Base,
497                        IndexedInstrProf::HashT HashType, uint64_t Version);
498   ~InstrProfReaderIndex() override = default;
499 
500   Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
501   Error getRecords(StringRef FuncName,
502                    ArrayRef<NamedInstrProfRecord> &Data) override;
503   void advanceToNextKey() override { RecordIterator++; }
504 
505   bool atEnd() const override {
506     return RecordIterator == HashTable->data_end();
507   }
508 
509   void setValueProfDataEndianness(support::endianness Endianness) override {
510     HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
511   }
512 
513   uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
514 
515   bool isIRLevelProfile() const override {
516     return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
517   }
518 
519   bool hasCSIRLevelProfile() const override {
520     return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
521   }
522 
523   bool instrEntryBBEnabled() const override {
524     return (FormatVersion & VARIANT_MASK_INSTR_ENTRY) != 0;
525   }
526 
527   bool hasSingleByteCoverage() const override {
528     return (FormatVersion & VARIANT_MASK_BYTE_COVERAGE) != 0;
529   }
530 
531   bool functionEntryOnly() const override {
532     return (FormatVersion & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0;
533   }
534 
535   InstrProfKind getProfileKind() const override;
536 
537   Error populateSymtab(InstrProfSymtab &Symtab) override {
538     return Symtab.create(HashTable->keys());
539   }
540 };
541 
542 /// Name matcher supporting fuzzy matching of symbol names to names in profiles.
543 class InstrProfReaderRemapper {
544 public:
545   virtual ~InstrProfReaderRemapper() = default;
546   virtual Error populateRemappings() { return Error::success(); }
547   virtual Error getRecords(StringRef FuncName,
548                            ArrayRef<NamedInstrProfRecord> &Data) = 0;
549 };
550 
551 /// Reader for the indexed binary instrprof format.
552 class IndexedInstrProfReader : public InstrProfReader {
553 private:
554   /// The profile data file contents.
555   std::unique_ptr<MemoryBuffer> DataBuffer;
556   /// The profile remapping file contents.
557   std::unique_ptr<MemoryBuffer> RemappingBuffer;
558   /// The index into the profile data.
559   std::unique_ptr<InstrProfReaderIndexBase> Index;
560   /// The profile remapping file contents.
561   std::unique_ptr<InstrProfReaderRemapper> Remapper;
562   /// Profile summary data.
563   std::unique_ptr<ProfileSummary> Summary;
564   /// Context sensitive profile summary data.
565   std::unique_ptr<ProfileSummary> CS_Summary;
566   /// MemProf profile schema (if available).
567   memprof::MemProfSchema Schema;
568   /// MemProf record profile data on-disk indexed via llvm::md5(FunctionName).
569   std::unique_ptr<MemProfRecordHashTable> MemProfRecordTable;
570   /// MemProf frame profile data on-disk indexed via frame id.
571   std::unique_ptr<MemProfFrameHashTable> MemProfFrameTable;
572 
573   // Index to the current record in the record array.
574   unsigned RecordIndex;
575 
576   // Read the profile summary. Return a pointer pointing to one byte past the
577   // end of the summary data if it exists or the input \c Cur.
578   // \c UseCS indicates whether to use the context-sensitive profile summary.
579   const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
580                                    const unsigned char *Cur, bool UseCS);
581 
582 public:
583   IndexedInstrProfReader(
584       std::unique_ptr<MemoryBuffer> DataBuffer,
585       std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
586       : DataBuffer(std::move(DataBuffer)),
587         RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {}
588   IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
589   IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
590 
591   /// Return the profile version.
592   uint64_t getVersion() const { return Index->getVersion(); }
593   bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
594   bool hasCSIRLevelProfile() const override {
595     return Index->hasCSIRLevelProfile();
596   }
597 
598   bool instrEntryBBEnabled() const override {
599     return Index->instrEntryBBEnabled();
600   }
601 
602   bool hasSingleByteCoverage() const override {
603     return Index->hasSingleByteCoverage();
604   }
605 
606   bool functionEntryOnly() const override { return Index->functionEntryOnly(); }
607 
608   /// Returns a BitsetEnum describing the attributes of the indexed instr
609   /// profile.
610   InstrProfKind getProfileKind() const override {
611     return Index->getProfileKind();
612   }
613 
614   /// Return true if the given buffer is in an indexed instrprof format.
615   static bool hasFormat(const MemoryBuffer &DataBuffer);
616 
617   /// Read the file header.
618   Error readHeader() override;
619   /// Read a single record.
620   Error readNextRecord(NamedInstrProfRecord &Record) override;
621 
622   /// Return the NamedInstrProfRecord associated with FuncName and FuncHash
623   Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
624                                                uint64_t FuncHash);
625 
626   /// Return the memprof record for the function identified by
627   /// llvm::md5(Name).
628   Expected<memprof::MemProfRecord> getMemProfRecord(uint64_t FuncNameHash);
629 
630   /// Fill Counts with the profile data for the given function name.
631   Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
632                           std::vector<uint64_t> &Counts);
633 
634   /// Return the maximum of all known function counts.
635   /// \c UseCS indicates whether to use the context-sensitive count.
636   uint64_t getMaximumFunctionCount(bool UseCS) {
637     if (UseCS) {
638       assert(CS_Summary && "No context sensitive profile summary");
639       return CS_Summary->getMaxFunctionCount();
640     } else {
641       assert(Summary && "No profile summary");
642       return Summary->getMaxFunctionCount();
643     }
644   }
645 
646   /// Factory method to create an indexed reader.
647   static Expected<std::unique_ptr<IndexedInstrProfReader>>
648   create(const Twine &Path, const Twine &RemappingPath = "");
649 
650   static Expected<std::unique_ptr<IndexedInstrProfReader>>
651   create(std::unique_ptr<MemoryBuffer> Buffer,
652          std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
653 
654   // Used for testing purpose only.
655   void setValueProfDataEndianness(support::endianness Endianness) {
656     Index->setValueProfDataEndianness(Endianness);
657   }
658 
659   // See description in the base class. This interface is designed
660   // to be used by llvm-profdata (for dumping). Avoid using this when
661   // the client is the compiler.
662   InstrProfSymtab &getSymtab() override;
663 
664   /// Return the profile summary.
665   /// \c UseCS indicates whether to use the context-sensitive summary.
666   ProfileSummary &getSummary(bool UseCS) {
667     if (UseCS) {
668       assert(CS_Summary && "No context sensitive summary");
669       return *(CS_Summary.get());
670     } else {
671       assert(Summary && "No profile summary");
672       return *(Summary.get());
673     }
674   }
675 };
676 
677 } // end namespace llvm
678 
679 #endif // LLVM_PROFILEDATA_INSTRPROFREADER_H
680