Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:24

0001 //===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains support for reading profiling data for instrumentation
0010 // based PGO and coverage.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
0015 #define LLVM_PROFILEDATA_INSTRPROFREADER_H
0016 
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/IR/ProfileSummary.h"
0020 #include "llvm/Object/BuildID.h"
0021 #include "llvm/ProfileData/InstrProf.h"
0022 #include "llvm/ProfileData/InstrProfCorrelator.h"
0023 #include "llvm/ProfileData/MemProf.h"
0024 #include "llvm/ProfileData/MemProfYAML.h"
0025 #include "llvm/Support/Endian.h"
0026 #include "llvm/Support/Error.h"
0027 #include "llvm/Support/LineIterator.h"
0028 #include "llvm/Support/MathExtras.h"
0029 #include "llvm/Support/MemoryBuffer.h"
0030 #include "llvm/Support/OnDiskHashTable.h"
0031 #include "llvm/Support/SwapByteOrder.h"
0032 #include <algorithm>
0033 #include <cassert>
0034 #include <cstddef>
0035 #include <cstdint>
0036 #include <iterator>
0037 #include <memory>
0038 #include <utility>
0039 #include <vector>
0040 
0041 namespace llvm {
0042 
0043 class InstrProfReader;
0044 
0045 namespace vfs {
0046 class FileSystem;
0047 } // namespace vfs
0048 
0049 /// A file format agnostic iterator over profiling data.
0050 template <class record_type = NamedInstrProfRecord,
0051           class reader_type = InstrProfReader>
0052 class InstrProfIterator {
0053 public:
0054   using iterator_category = std::input_iterator_tag;
0055   using value_type = record_type;
0056   using difference_type = std::ptrdiff_t;
0057   using pointer = value_type *;
0058   using reference = value_type &;
0059 
0060 private:
0061   reader_type *Reader = nullptr;
0062   value_type Record;
0063 
0064   void increment() {
0065     if (Error E = Reader->readNextRecord(Record)) {
0066       // Handle errors in the reader.
0067       InstrProfError::take(std::move(E));
0068       *this = InstrProfIterator();
0069     }
0070   }
0071 
0072 public:
0073   InstrProfIterator() = default;
0074   InstrProfIterator(reader_type *Reader) : Reader(Reader) { increment(); }
0075 
0076   InstrProfIterator &operator++() {
0077     increment();
0078     return *this;
0079   }
0080   bool operator==(const InstrProfIterator &RHS) const {
0081     return Reader == RHS.Reader;
0082   }
0083   bool operator!=(const InstrProfIterator &RHS) const {
0084     return Reader != RHS.Reader;
0085   }
0086   value_type &operator*() { return Record; }
0087   value_type *operator->() { return &Record; }
0088 };
0089 
0090 /// Base class and interface for reading profiling data of any known instrprof
0091 /// format. Provides an iterator over NamedInstrProfRecords.
0092 class InstrProfReader {
0093   instrprof_error LastError = instrprof_error::success;
0094   std::string LastErrorMsg;
0095 
0096 public:
0097   InstrProfReader() = default;
0098   virtual ~InstrProfReader() = default;
0099 
0100   /// Read the header.  Required before reading first record.
0101   virtual Error readHeader() = 0;
0102 
0103   /// Read a single record.
0104   virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
0105 
0106   /// Read a list of binary ids.
0107   virtual Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) {
0108     return success();
0109   }
0110 
0111   /// Print binary ids.
0112   virtual Error printBinaryIds(raw_ostream &OS) { return success(); };
0113 
0114   /// Iterator over profile data.
0115   InstrProfIterator<> begin() { return InstrProfIterator<>(this); }
0116   InstrProfIterator<> end() { return InstrProfIterator<>(); }
0117 
0118   /// Return the profile version.
0119   virtual uint64_t getVersion() const = 0;
0120 
0121   virtual bool isIRLevelProfile() const = 0;
0122 
0123   virtual bool hasCSIRLevelProfile() const = 0;
0124 
0125   virtual bool instrEntryBBEnabled() const = 0;
0126 
0127   /// Return true if the profile instruments all loop entries.
0128   virtual bool instrLoopEntriesEnabled() const = 0;
0129 
0130   /// Return true if the profile has single byte counters representing coverage.
0131   virtual bool hasSingleByteCoverage() const = 0;
0132 
0133   /// Return true if the profile only instruments function entries.
0134   virtual bool functionEntryOnly() const = 0;
0135 
0136   /// Return true if profile includes a memory profile.
0137   virtual bool hasMemoryProfile() const = 0;
0138 
0139   /// Return true if this has a temporal profile.
0140   virtual bool hasTemporalProfile() const = 0;
0141 
0142   /// Returns a BitsetEnum describing the attributes of the profile. To check
0143   /// individual attributes prefer using the helpers above.
0144   virtual InstrProfKind getProfileKind() const = 0;
0145 
0146   /// Return the PGO symtab. There are three different readers:
0147   /// Raw, Text, and Indexed profile readers. The first two types
0148   /// of readers are used only by llvm-profdata tool, while the indexed
0149   /// profile reader is also used by llvm-cov tool and the compiler (
0150   /// backend or frontend). Since creating PGO symtab can create
0151   /// significant runtime and memory overhead (as it touches data
0152   /// for the whole program), InstrProfSymtab for the indexed profile
0153   /// reader should be created on demand and it is recommended to be
0154   /// only used for dumping purpose with llvm-proftool, not with the
0155   /// compiler.
0156   virtual InstrProfSymtab &getSymtab() = 0;
0157 
0158   /// Compute the sum of counts and return in Sum.
0159   void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
0160 
0161 protected:
0162   std::unique_ptr<InstrProfSymtab> Symtab;
0163   /// A list of temporal profile traces.
0164   SmallVector<TemporalProfTraceTy> TemporalProfTraces;
0165   /// The total number of temporal profile traces seen.
0166   uint64_t TemporalProfTraceStreamSize = 0;
0167 
0168   /// Set the current error and return same.
0169   Error error(instrprof_error Err, const std::string &ErrMsg = "") {
0170     LastError = Err;
0171     LastErrorMsg = ErrMsg;
0172     if (Err == instrprof_error::success)
0173       return Error::success();
0174     return make_error<InstrProfError>(Err, ErrMsg);
0175   }
0176 
0177   Error error(Error &&E) {
0178     handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
0179       LastError = IPE.get();
0180       LastErrorMsg = IPE.getMessage();
0181     });
0182     return make_error<InstrProfError>(LastError, LastErrorMsg);
0183   }
0184 
0185   /// Clear the current error and return a successful one.
0186   Error success() { return error(instrprof_error::success); }
0187 
0188 public:
0189   /// Return true if the reader has finished reading the profile data.
0190   bool isEOF() { return LastError == instrprof_error::eof; }
0191 
0192   /// Return true if the reader encountered an error reading profiling data.
0193   bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
0194 
0195   /// Get the current error.
0196   Error getError() {
0197     if (hasError())
0198       return make_error<InstrProfError>(LastError, LastErrorMsg);
0199     return Error::success();
0200   }
0201 
0202   /// Factory method to create an appropriately typed reader for the given
0203   /// instrprof file.
0204   static Expected<std::unique_ptr<InstrProfReader>> create(
0205       const Twine &Path, vfs::FileSystem &FS,
0206       const InstrProfCorrelator *Correlator = nullptr,
0207       const object::BuildIDFetcher *BIDFetcher = nullptr,
0208       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
0209           InstrProfCorrelator::ProfCorrelatorKind::NONE,
0210       std::function<void(Error)> Warn = nullptr);
0211 
0212   static Expected<std::unique_ptr<InstrProfReader>> create(
0213       std::unique_ptr<MemoryBuffer> Buffer,
0214       const InstrProfCorrelator *Correlator = nullptr,
0215       const object::BuildIDFetcher *BIDFetcher = nullptr,
0216       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
0217           InstrProfCorrelator::ProfCorrelatorKind::NONE,
0218       std::function<void(Error)> Warn = nullptr);
0219 
0220   /// \param Weight for raw profiles use this as the temporal profile trace
0221   ///               weight
0222   /// \returns a list of temporal profile traces.
0223   virtual SmallVector<TemporalProfTraceTy> &
0224   getTemporalProfTraces(std::optional<uint64_t> Weight = {}) {
0225     // For non-raw profiles we ignore the input weight and instead use the
0226     // weights already in the traces.
0227     return TemporalProfTraces;
0228   }
0229   /// \returns the total number of temporal profile traces seen.
0230   uint64_t getTemporalProfTraceStreamSize() {
0231     return TemporalProfTraceStreamSize;
0232   }
0233 };
0234 
0235 /// Reader for the simple text based instrprof format.
0236 ///
0237 /// This format is a simple text format that's suitable for test data. Records
0238 /// are separated by one or more blank lines, and record fields are separated by
0239 /// new lines.
0240 ///
0241 /// Each record consists of a function name, a function hash, a number of
0242 /// counters, and then each counter value, in that order.
0243 class TextInstrProfReader : public InstrProfReader {
0244 private:
0245   /// The profile data file contents.
0246   std::unique_ptr<MemoryBuffer> DataBuffer;
0247   /// Iterator over the profile data.
0248   line_iterator Line;
0249   /// The attributes of the current profile.
0250   InstrProfKind ProfileKind = InstrProfKind::Unknown;
0251 
0252   Error readValueProfileData(InstrProfRecord &Record);
0253 
0254   Error readTemporalProfTraceData();
0255 
0256 public:
0257   TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
0258       : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
0259   TextInstrProfReader(const TextInstrProfReader &) = delete;
0260   TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
0261 
0262   /// Return true if the given buffer is in text instrprof format.
0263   static bool hasFormat(const MemoryBuffer &Buffer);
0264 
0265   // Text format does not have version, so return 0.
0266   uint64_t getVersion() const override { return 0; }
0267 
0268   bool isIRLevelProfile() const override {
0269     return static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation);
0270   }
0271 
0272   bool hasCSIRLevelProfile() const override {
0273     return static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive);
0274   }
0275 
0276   bool instrEntryBBEnabled() const override {
0277     return static_cast<bool>(ProfileKind &
0278                              InstrProfKind::FunctionEntryInstrumentation);
0279   }
0280 
0281   bool instrLoopEntriesEnabled() const override {
0282     return static_cast<bool>(ProfileKind &
0283                              InstrProfKind::LoopEntriesInstrumentation);
0284   }
0285 
0286   bool hasSingleByteCoverage() const override {
0287     return static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage);
0288   }
0289 
0290   bool functionEntryOnly() const override {
0291     return static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly);
0292   }
0293 
0294   bool hasMemoryProfile() const override {
0295     // TODO: Add support for text format memory profiles.
0296     return false;
0297   }
0298 
0299   bool hasTemporalProfile() const override {
0300     return static_cast<bool>(ProfileKind & InstrProfKind::TemporalProfile);
0301   }
0302 
0303   InstrProfKind getProfileKind() const override { return ProfileKind; }
0304 
0305   /// Read the header.
0306   Error readHeader() override;
0307 
0308   /// Read a single record.
0309   Error readNextRecord(NamedInstrProfRecord &Record) override;
0310 
0311   InstrProfSymtab &getSymtab() override {
0312     assert(Symtab);
0313     return *Symtab;
0314   }
0315 };
0316 
0317 /// Reader for the raw instrprof binary format from runtime.
0318 ///
0319 /// This format is a raw memory dump of the instrumentation-based profiling data
0320 /// from the runtime.  It has no index.
0321 ///
0322 /// Templated on the unsigned type whose size matches pointers on the platform
0323 /// that wrote the profile.
0324 template <class IntPtrT>
0325 class RawInstrProfReader : public InstrProfReader {
0326 private:
0327   /// The profile data file contents.
0328   std::unique_ptr<MemoryBuffer> DataBuffer;
0329   /// If available, this hold the ProfileData array used to correlate raw
0330   /// instrumentation data to their functions.
0331   const InstrProfCorrelatorImpl<IntPtrT> *Correlator;
0332   /// Fetches debuginfo by build id to correlate profiles.
0333   const object::BuildIDFetcher *BIDFetcher;
0334   /// Correlates profiles with build id fetcher by fetching debuginfo with build
0335   /// ID.
0336   std::unique_ptr<InstrProfCorrelator> BIDFetcherCorrelator;
0337   /// Indicates if should use debuginfo or binary to correlate with build id
0338   /// fetcher.
0339   InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind;
0340   /// A list of timestamps paired with a function name reference.
0341   std::vector<std::pair<uint64_t, uint64_t>> TemporalProfTimestamps;
0342   bool ShouldSwapBytes;
0343   // The value of the version field of the raw profile data header. The lower 32
0344   // bits specifies the format version and the most significant 32 bits specify
0345   // the variant types of the profile.
0346   uint64_t Version;
0347   uint64_t CountersDelta;
0348   uint64_t BitmapDelta;
0349   uint64_t NamesDelta;
0350   const RawInstrProf::ProfileData<IntPtrT> *Data;
0351   const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
0352   const RawInstrProf::VTableProfileData<IntPtrT> *VTableBegin = nullptr;
0353   const RawInstrProf::VTableProfileData<IntPtrT> *VTableEnd = nullptr;
0354   const char *CountersStart;
0355   const char *CountersEnd;
0356   const char *BitmapStart;
0357   const char *BitmapEnd;
0358   const char *NamesStart;
0359   const char *NamesEnd;
0360   const char *VNamesStart = nullptr;
0361   const char *VNamesEnd = nullptr;
0362   // After value profile is all read, this pointer points to
0363   // the header of next profile data (if exists)
0364   const uint8_t *ValueDataStart;
0365   uint32_t ValueKindLast;
0366   uint32_t CurValueDataSize;
0367   std::vector<llvm::object::BuildID> BinaryIds;
0368 
0369   std::function<void(Error)> Warn;
0370 
0371   /// Maxium counter value 2^56.
0372   static const uint64_t MaxCounterValue = (1ULL << 56);
0373 
0374 public:
0375   RawInstrProfReader(
0376       std::unique_ptr<MemoryBuffer> DataBuffer,
0377       const InstrProfCorrelator *Correlator,
0378       const object::BuildIDFetcher *BIDFetcher,
0379       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
0380       std::function<void(Error)> Warn)
0381       : DataBuffer(std::move(DataBuffer)),
0382         Correlator(dyn_cast_or_null<const InstrProfCorrelatorImpl<IntPtrT>>(
0383             Correlator)),
0384         BIDFetcher(BIDFetcher),
0385         BIDFetcherCorrelatorKind(BIDFetcherCorrelatorKind), Warn(Warn) {}
0386 
0387   RawInstrProfReader(const RawInstrProfReader &) = delete;
0388   RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
0389 
0390   static bool hasFormat(const MemoryBuffer &DataBuffer);
0391   Error readHeader() override;
0392   Error readNextRecord(NamedInstrProfRecord &Record) override;
0393   Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) override;
0394   Error printBinaryIds(raw_ostream &OS) override;
0395 
0396   uint64_t getVersion() const override { return Version; }
0397 
0398   bool isIRLevelProfile() const override {
0399     return (Version & VARIANT_MASK_IR_PROF) != 0;
0400   }
0401 
0402   bool hasCSIRLevelProfile() const override {
0403     return (Version & VARIANT_MASK_CSIR_PROF) != 0;
0404   }
0405 
0406   bool instrEntryBBEnabled() const override {
0407     return (Version & VARIANT_MASK_INSTR_ENTRY) != 0;
0408   }
0409 
0410   bool instrLoopEntriesEnabled() const override {
0411     return (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) != 0;
0412   }
0413 
0414   bool hasSingleByteCoverage() const override {
0415     return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0;
0416   }
0417 
0418   bool functionEntryOnly() const override {
0419     return (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0;
0420   }
0421 
0422   bool hasMemoryProfile() const override {
0423     // Memory profiles have a separate raw format, so this should never be set.
0424     assert(!(Version & VARIANT_MASK_MEMPROF));
0425     return false;
0426   }
0427 
0428   bool hasTemporalProfile() const override {
0429     return (Version & VARIANT_MASK_TEMPORAL_PROF) != 0;
0430   }
0431 
0432   /// Returns a BitsetEnum describing the attributes of the raw instr profile.
0433   InstrProfKind getProfileKind() const override;
0434 
0435   InstrProfSymtab &getSymtab() override {
0436     assert(Symtab.get());
0437     return *Symtab.get();
0438   }
0439 
0440   SmallVector<TemporalProfTraceTy> &
0441   getTemporalProfTraces(std::optional<uint64_t> Weight = {}) override;
0442 
0443 private:
0444   Error createSymtab(InstrProfSymtab &Symtab);
0445   Error readNextHeader(const char *CurrentPos);
0446   Error readHeader(const RawInstrProf::Header &Header);
0447 
0448   template <class IntT> IntT swap(IntT Int) const {
0449     return ShouldSwapBytes ? llvm::byteswap(Int) : Int;
0450   }
0451 
0452   llvm::endianness getDataEndianness() const {
0453     if (!ShouldSwapBytes)
0454       return llvm::endianness::native;
0455     if (llvm::endianness::native == llvm::endianness::little)
0456       return llvm::endianness::big;
0457     else
0458       return llvm::endianness::little;
0459   }
0460 
0461   inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
0462     return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
0463   }
0464 
0465   Error readName(NamedInstrProfRecord &Record);
0466   Error readFuncHash(NamedInstrProfRecord &Record);
0467   Error readRawCounts(InstrProfRecord &Record);
0468   Error readRawBitmapBytes(InstrProfRecord &Record);
0469   Error readValueProfilingData(InstrProfRecord &Record);
0470   bool atEnd() const { return Data == DataEnd; }
0471 
0472   void advanceData() {
0473     // `CountersDelta` is a constant zero when using debug info correlation.
0474     if (!Correlator && !BIDFetcherCorrelator) {
0475       // The initial CountersDelta is the in-memory address difference between
0476       // the data and counts sections:
0477       // start(__llvm_prf_cnts) - start(__llvm_prf_data)
0478       // As we advance to the next record, we maintain the correct CountersDelta
0479       // with respect to the next record.
0480       CountersDelta -= sizeof(*Data);
0481       BitmapDelta -= sizeof(*Data);
0482     }
0483     Data++;
0484     ValueDataStart += CurValueDataSize;
0485   }
0486 
0487   const char *getNextHeaderPos() const {
0488       assert(atEnd());
0489       return (const char *)ValueDataStart;
0490   }
0491 
0492   StringRef getName(uint64_t NameRef) const {
0493     return Symtab->getFuncOrVarName(swap(NameRef));
0494   }
0495 
0496   int getCounterTypeSize() const {
0497     return hasSingleByteCoverage() ? sizeof(uint8_t) : sizeof(uint64_t);
0498   }
0499 };
0500 
0501 using RawInstrProfReader32 = RawInstrProfReader<uint32_t>;
0502 using RawInstrProfReader64 = RawInstrProfReader<uint64_t>;
0503 
0504 namespace IndexedInstrProf {
0505 
0506 enum class HashT : uint32_t;
0507 
0508 } // end namespace IndexedInstrProf
0509 
0510 /// Trait for lookups into the on-disk hash table for the binary instrprof
0511 /// format.
0512 class InstrProfLookupTrait {
0513   std::vector<NamedInstrProfRecord> DataBuffer;
0514   IndexedInstrProf::HashT HashType;
0515   unsigned FormatVersion;
0516   // Endianness of the input value profile data.
0517   // It should be LE by default, but can be changed
0518   // for testing purpose.
0519   llvm::endianness ValueProfDataEndianness = llvm::endianness::little;
0520 
0521 public:
0522   InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
0523       : HashType(HashType), FormatVersion(FormatVersion) {}
0524 
0525   using data_type = ArrayRef<NamedInstrProfRecord>;
0526 
0527   using internal_key_type = StringRef;
0528   using external_key_type = StringRef;
0529   using hash_value_type = uint64_t;
0530   using offset_type = uint64_t;
0531 
0532   static bool EqualKey(StringRef A, StringRef B) { return A == B; }
0533   static StringRef GetInternalKey(StringRef K) { return K; }
0534   static StringRef GetExternalKey(StringRef K) { return K; }
0535 
0536   hash_value_type ComputeHash(StringRef K);
0537 
0538   static std::pair<offset_type, offset_type>
0539   ReadKeyDataLength(const unsigned char *&D) {
0540     using namespace support;
0541 
0542     offset_type KeyLen =
0543         endian::readNext<offset_type, llvm::endianness::little>(D);
0544     offset_type DataLen =
0545         endian::readNext<offset_type, llvm::endianness::little>(D);
0546     return std::make_pair(KeyLen, DataLen);
0547   }
0548 
0549   StringRef ReadKey(const unsigned char *D, offset_type N) {
0550     return StringRef((const char *)D, N);
0551   }
0552 
0553   bool readValueProfilingData(const unsigned char *&D,
0554                               const unsigned char *const End);
0555   data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
0556 
0557   // Used for testing purpose only.
0558   void setValueProfDataEndianness(llvm::endianness Endianness) {
0559     ValueProfDataEndianness = Endianness;
0560   }
0561 };
0562 
0563 struct InstrProfReaderIndexBase {
0564   virtual ~InstrProfReaderIndexBase() = default;
0565 
0566   // Read all the profile records with the same key pointed to the current
0567   // iterator.
0568   virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
0569 
0570   // Read all the profile records with the key equal to FuncName
0571   virtual Error getRecords(StringRef FuncName,
0572                                      ArrayRef<NamedInstrProfRecord> &Data) = 0;
0573   virtual void advanceToNextKey() = 0;
0574   virtual bool atEnd() const = 0;
0575   virtual void setValueProfDataEndianness(llvm::endianness Endianness) = 0;
0576   virtual uint64_t getVersion() const = 0;
0577   virtual bool isIRLevelProfile() const = 0;
0578   virtual bool hasCSIRLevelProfile() const = 0;
0579   virtual bool instrEntryBBEnabled() const = 0;
0580   virtual bool instrLoopEntriesEnabled() const = 0;
0581   virtual bool hasSingleByteCoverage() const = 0;
0582   virtual bool functionEntryOnly() const = 0;
0583   virtual bool hasMemoryProfile() const = 0;
0584   virtual bool hasTemporalProfile() const = 0;
0585   virtual InstrProfKind getProfileKind() const = 0;
0586   virtual Error populateSymtab(InstrProfSymtab &) = 0;
0587 };
0588 
0589 using OnDiskHashTableImplV3 =
0590     OnDiskIterableChainedHashTable<InstrProfLookupTrait>;
0591 
0592 using MemProfRecordHashTable =
0593     OnDiskIterableChainedHashTable<memprof::RecordLookupTrait>;
0594 using MemProfFrameHashTable =
0595     OnDiskIterableChainedHashTable<memprof::FrameLookupTrait>;
0596 using MemProfCallStackHashTable =
0597     OnDiskIterableChainedHashTable<memprof::CallStackLookupTrait>;
0598 
0599 template <typename HashTableImpl>
0600 class InstrProfReaderItaniumRemapper;
0601 
0602 template <typename HashTableImpl>
0603 class InstrProfReaderIndex : public InstrProfReaderIndexBase {
0604 private:
0605   std::unique_ptr<HashTableImpl> HashTable;
0606   typename HashTableImpl::data_iterator RecordIterator;
0607   uint64_t FormatVersion;
0608 
0609   friend class InstrProfReaderItaniumRemapper<HashTableImpl>;
0610 
0611 public:
0612   InstrProfReaderIndex(const unsigned char *Buckets,
0613                        const unsigned char *const Payload,
0614                        const unsigned char *const Base,
0615                        IndexedInstrProf::HashT HashType, uint64_t Version);
0616   ~InstrProfReaderIndex() override = default;
0617 
0618   Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
0619   Error getRecords(StringRef FuncName,
0620                    ArrayRef<NamedInstrProfRecord> &Data) override;
0621   void advanceToNextKey() override { RecordIterator++; }
0622 
0623   bool atEnd() const override {
0624     return RecordIterator == HashTable->data_end();
0625   }
0626 
0627   void setValueProfDataEndianness(llvm::endianness Endianness) override {
0628     HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
0629   }
0630 
0631   uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
0632 
0633   bool isIRLevelProfile() const override {
0634     return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
0635   }
0636 
0637   bool hasCSIRLevelProfile() const override {
0638     return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
0639   }
0640 
0641   bool instrEntryBBEnabled() const override {
0642     return (FormatVersion & VARIANT_MASK_INSTR_ENTRY) != 0;
0643   }
0644 
0645   bool instrLoopEntriesEnabled() const override {
0646     return (FormatVersion & VARIANT_MASK_INSTR_LOOP_ENTRIES) != 0;
0647   }
0648 
0649   bool hasSingleByteCoverage() const override {
0650     return (FormatVersion & VARIANT_MASK_BYTE_COVERAGE) != 0;
0651   }
0652 
0653   bool functionEntryOnly() const override {
0654     return (FormatVersion & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0;
0655   }
0656 
0657   bool hasMemoryProfile() const override {
0658     return (FormatVersion & VARIANT_MASK_MEMPROF) != 0;
0659   }
0660 
0661   bool hasTemporalProfile() const override {
0662     return (FormatVersion & VARIANT_MASK_TEMPORAL_PROF) != 0;
0663   }
0664 
0665   InstrProfKind getProfileKind() const override;
0666 
0667   Error populateSymtab(InstrProfSymtab &Symtab) override {
0668     // FIXME: the create method calls 'finalizeSymtab' and sorts a bunch of
0669     // arrays/maps. Since there are other data sources other than 'HashTable' to
0670     // populate a symtab, it might make sense to have something like this
0671     // 1. Let each data source populate Symtab and init the arrays/maps without
0672     // calling 'finalizeSymtab'
0673     // 2. Call 'finalizeSymtab' once to get all arrays/maps sorted if needed.
0674     return Symtab.create(HashTable->keys());
0675   }
0676 };
0677 
0678 /// Name matcher supporting fuzzy matching of symbol names to names in profiles.
0679 class InstrProfReaderRemapper {
0680 public:
0681   virtual ~InstrProfReaderRemapper() = default;
0682   virtual Error populateRemappings() { return Error::success(); }
0683   virtual Error getRecords(StringRef FuncName,
0684                            ArrayRef<NamedInstrProfRecord> &Data) = 0;
0685 };
0686 
0687 class IndexedMemProfReader {
0688 private:
0689   /// The MemProf version.
0690   memprof::IndexedVersion Version =
0691       static_cast<memprof::IndexedVersion>(memprof::MinimumSupportedVersion);
0692   /// MemProf profile schema (if available).
0693   memprof::MemProfSchema Schema;
0694   /// MemProf record profile data on-disk indexed via llvm::md5(FunctionName).
0695   std::unique_ptr<MemProfRecordHashTable> MemProfRecordTable;
0696   /// MemProf frame profile data on-disk indexed via frame id.
0697   std::unique_ptr<MemProfFrameHashTable> MemProfFrameTable;
0698   /// MemProf call stack data on-disk indexed via call stack id.
0699   std::unique_ptr<MemProfCallStackHashTable> MemProfCallStackTable;
0700   /// The starting address of the frame array.
0701   const unsigned char *FrameBase = nullptr;
0702   /// The starting address of the call stack array.
0703   const unsigned char *CallStackBase = nullptr;
0704   // The number of elements in the radix tree array.
0705   unsigned RadixTreeSize = 0;
0706 
0707   Error deserializeV2(const unsigned char *Start, const unsigned char *Ptr);
0708   Error deserializeV3(const unsigned char *Start, const unsigned char *Ptr);
0709 
0710 public:
0711   IndexedMemProfReader() = default;
0712 
0713   Error deserialize(const unsigned char *Start, uint64_t MemProfOffset);
0714 
0715   Expected<memprof::MemProfRecord>
0716   getMemProfRecord(const uint64_t FuncNameHash) const;
0717 
0718   DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>>
0719   getMemProfCallerCalleePairs() const;
0720 
0721   // Return the entire MemProf profile.
0722   memprof::AllMemProfData getAllMemProfData() const;
0723 };
0724 
0725 /// Reader for the indexed binary instrprof format.
0726 class IndexedInstrProfReader : public InstrProfReader {
0727 private:
0728   /// The profile data file contents.
0729   std::unique_ptr<MemoryBuffer> DataBuffer;
0730   /// The profile remapping file contents.
0731   std::unique_ptr<MemoryBuffer> RemappingBuffer;
0732   /// The index into the profile data.
0733   std::unique_ptr<InstrProfReaderIndexBase> Index;
0734   /// The profile remapping file contents.
0735   std::unique_ptr<InstrProfReaderRemapper> Remapper;
0736   /// Profile summary data.
0737   std::unique_ptr<ProfileSummary> Summary;
0738   /// Context sensitive profile summary data.
0739   std::unique_ptr<ProfileSummary> CS_Summary;
0740   IndexedMemProfReader MemProfReader;
0741   /// The compressed vtable names, to be used for symtab construction.
0742   /// A compiler that reads indexed profiles could construct symtab from module
0743   /// IR so it doesn't need the decompressed names.
0744   StringRef VTableName;
0745   /// A memory buffer holding binary ids.
0746   ArrayRef<uint8_t> BinaryIdsBuffer;
0747 
0748   // Index to the current record in the record array.
0749   unsigned RecordIndex = 0;
0750 
0751   // Read the profile summary. Return a pointer pointing to one byte past the
0752   // end of the summary data if it exists or the input \c Cur.
0753   // \c UseCS indicates whether to use the context-sensitive profile summary.
0754   const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
0755                                    const unsigned char *Cur, bool UseCS);
0756 
0757 public:
0758   IndexedInstrProfReader(
0759       std::unique_ptr<MemoryBuffer> DataBuffer,
0760       std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
0761       : DataBuffer(std::move(DataBuffer)),
0762         RemappingBuffer(std::move(RemappingBuffer)) {}
0763   IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
0764   IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
0765 
0766   /// Return the profile version.
0767   uint64_t getVersion() const override { return Index->getVersion(); }
0768   bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
0769   bool hasCSIRLevelProfile() const override {
0770     return Index->hasCSIRLevelProfile();
0771   }
0772 
0773   bool instrEntryBBEnabled() const override {
0774     return Index->instrEntryBBEnabled();
0775   }
0776 
0777   bool instrLoopEntriesEnabled() const override {
0778     return Index->instrLoopEntriesEnabled();
0779   }
0780 
0781   bool hasSingleByteCoverage() const override {
0782     return Index->hasSingleByteCoverage();
0783   }
0784 
0785   bool functionEntryOnly() const override { return Index->functionEntryOnly(); }
0786 
0787   bool hasMemoryProfile() const override { return Index->hasMemoryProfile(); }
0788 
0789   bool hasTemporalProfile() const override {
0790     return Index->hasTemporalProfile();
0791   }
0792 
0793   /// Returns a BitsetEnum describing the attributes of the indexed instr
0794   /// profile.
0795   InstrProfKind getProfileKind() const override {
0796     return Index->getProfileKind();
0797   }
0798 
0799   /// Return true if the given buffer is in an indexed instrprof format.
0800   static bool hasFormat(const MemoryBuffer &DataBuffer);
0801 
0802   /// Read the file header.
0803   Error readHeader() override;
0804   /// Read a single record.
0805   Error readNextRecord(NamedInstrProfRecord &Record) override;
0806 
0807   /// Return the NamedInstrProfRecord associated with FuncName and FuncHash.
0808   /// When return a hash_mismatch error and MismatchedFuncSum is not nullptr,
0809   /// the sum of all counters in the mismatched function will be set to
0810   /// MismatchedFuncSum. If there are multiple instances of mismatched
0811   /// functions, MismatchedFuncSum returns the maximum. If \c FuncName is not
0812   /// found, try to lookup \c DeprecatedFuncName to handle profiles built by
0813   /// older compilers.
0814   Expected<InstrProfRecord>
0815   getInstrProfRecord(StringRef FuncName, uint64_t FuncHash,
0816                      StringRef DeprecatedFuncName = "",
0817                      uint64_t *MismatchedFuncSum = nullptr);
0818 
0819   /// Return the memprof record for the function identified by
0820   /// llvm::md5(Name).
0821   Expected<memprof::MemProfRecord> getMemProfRecord(uint64_t FuncNameHash) {
0822     return MemProfReader.getMemProfRecord(FuncNameHash);
0823   }
0824 
0825   DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>>
0826   getMemProfCallerCalleePairs() {
0827     return MemProfReader.getMemProfCallerCalleePairs();
0828   }
0829 
0830   memprof::AllMemProfData getAllMemProfData() const {
0831     return MemProfReader.getAllMemProfData();
0832   }
0833 
0834   /// Fill Counts with the profile data for the given function name.
0835   Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
0836                           std::vector<uint64_t> &Counts);
0837 
0838   /// Fill Bitmap with the profile data for the given function name.
0839   Error getFunctionBitmap(StringRef FuncName, uint64_t FuncHash,
0840                           BitVector &Bitmap);
0841 
0842   /// Return the maximum of all known function counts.
0843   /// \c UseCS indicates whether to use the context-sensitive count.
0844   uint64_t getMaximumFunctionCount(bool UseCS) {
0845     if (UseCS) {
0846       assert(CS_Summary && "No context sensitive profile summary");
0847       return CS_Summary->getMaxFunctionCount();
0848     } else {
0849       assert(Summary && "No profile summary");
0850       return Summary->getMaxFunctionCount();
0851     }
0852   }
0853 
0854   /// Factory method to create an indexed reader.
0855   static Expected<std::unique_ptr<IndexedInstrProfReader>>
0856   create(const Twine &Path, vfs::FileSystem &FS,
0857          const Twine &RemappingPath = "");
0858 
0859   static Expected<std::unique_ptr<IndexedInstrProfReader>>
0860   create(std::unique_ptr<MemoryBuffer> Buffer,
0861          std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
0862 
0863   // Used for testing purpose only.
0864   void setValueProfDataEndianness(llvm::endianness Endianness) {
0865     Index->setValueProfDataEndianness(Endianness);
0866   }
0867 
0868   // See description in the base class. This interface is designed
0869   // to be used by llvm-profdata (for dumping). Avoid using this when
0870   // the client is the compiler.
0871   InstrProfSymtab &getSymtab() override;
0872 
0873   /// Return the profile summary.
0874   /// \c UseCS indicates whether to use the context-sensitive summary.
0875   ProfileSummary &getSummary(bool UseCS) {
0876     if (UseCS) {
0877       assert(CS_Summary && "No context sensitive summary");
0878       return *CS_Summary;
0879     } else {
0880       assert(Summary && "No profile summary");
0881       return *Summary;
0882     }
0883   }
0884 
0885   Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) override;
0886   Error printBinaryIds(raw_ostream &OS) override;
0887 };
0888 
0889 } // end namespace llvm
0890 
0891 #endif // LLVM_PROFILEDATA_INSTRPROFREADER_H