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