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