+typedef RawInstrProfReader<uint32_t> RawInstrProfReader32;
+typedef RawInstrProfReader<uint64_t> RawInstrProfReader64;
+
+namespace IndexedInstrProf {
+enum class HashT : uint32_t;
+}
+
+/// Trait for lookups into the on-disk hash table for the binary instrprof
+/// format.
+class InstrProfLookupTrait {
+ std::vector<InstrProfRecord> DataBuffer;
+ IndexedInstrProf::HashT HashType;
+ unsigned FormatVersion;
+ // Endianness of the input value profile data.
+ // It should be LE by default, but can be changed
+ // for testing purpose.
+ support::endianness ValueProfDataEndianness;
+ std::vector<std::pair<uint64_t, const char *>> HashKeys;
+
+public:
+ InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
+ : HashType(HashType), FormatVersion(FormatVersion),
+ ValueProfDataEndianness(support::little) {}
+
+ typedef ArrayRef<InstrProfRecord> data_type;
+
+ typedef StringRef internal_key_type;
+ typedef StringRef external_key_type;
+ typedef uint64_t hash_value_type;
+ typedef uint64_t offset_type;
+
+ static bool EqualKey(StringRef A, StringRef B) { return A == B; }
+ static StringRef GetInternalKey(StringRef K) { return K; }
+ static StringRef GetExternalKey(StringRef K) { return K; }
+
+ hash_value_type ComputeHash(StringRef K);
+
+ void setHashKeys(std::vector<std::pair<uint64_t, const char *>> HashKeys) {
+ this->HashKeys = std::move(HashKeys);
+ }
+ static std::pair<offset_type, offset_type>
+ ReadKeyDataLength(const unsigned char *&D) {
+ using namespace support;
+ offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
+ offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ StringRef ReadKey(const unsigned char *D, offset_type N) {
+ return StringRef((const char *)D, N);
+ }
+
+ bool readValueProfilingData(const unsigned char *&D,
+ const unsigned char *const End);
+ data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
+
+ // Used for testing purpose only.
+ void setValueProfDataEndianness(support::endianness Endianness) {
+ ValueProfDataEndianness = Endianness;
+ }
+};
+
+struct InstrProfReaderIndexBase {
+ // Read all the profile records with the same key pointed to the current
+ // iterator.
+ virtual std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
+ // Read all the profile records with the key equal to FuncName
+ virtual std::error_code getRecords(StringRef FuncName,
+ ArrayRef<InstrProfRecord> &Data) = 0;
+ virtual void advanceToNextKey() = 0;
+ virtual bool atEnd() const = 0;
+ virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
+ virtual ~InstrProfReaderIndexBase() {}
+ virtual uint64_t getVersion() const = 0;
+};
+
+typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait>
+ OnDiskHashTableImplV3;
+
+template <typename HashTableImpl>
+class InstrProfReaderIndex : public InstrProfReaderIndexBase {
+
+private:
+ std::unique_ptr<HashTableImpl> HashTable;
+ typename HashTableImpl::data_iterator RecordIterator;
+ uint64_t FormatVersion;
+
+ // String table for holding a unique copy of all the strings in the profile.
+ InstrProfStringTable StringTable;
+
+public:
+ InstrProfReaderIndex(const unsigned char *Buckets,
+ const unsigned char *const Payload,
+ const unsigned char *const Base,
+ IndexedInstrProf::HashT HashType, uint64_t Version);
+
+ std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) override;
+ std::error_code getRecords(StringRef FuncName,
+ ArrayRef<InstrProfRecord> &Data) override;
+ void advanceToNextKey() override { RecordIterator++; }
+ bool atEnd() const override {
+ return RecordIterator == HashTable->data_end();
+ }
+ void setValueProfDataEndianness(support::endianness Endianness) override {
+ HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
+ }
+ ~InstrProfReaderIndex() override {}
+ uint64_t getVersion() const override { return FormatVersion; }
+};
+
+/// Reader for the indexed binary instrprof format.
+class IndexedInstrProfReader : public InstrProfReader {
+private:
+ /// The profile data file contents.
+ std::unique_ptr<MemoryBuffer> DataBuffer;
+ /// The index into the profile data.
+ std::unique_ptr<InstrProfReaderIndexBase> Index;
+ /// The maximal execution count among all functions.
+ uint64_t MaxFunctionCount;
+
+ IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
+ IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
+
+public:
+ uint64_t getVersion() const { return Index->getVersion(); }
+ IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
+ : DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
+
+ /// Return true if the given buffer is in an indexed instrprof format.
+ static bool hasFormat(const MemoryBuffer &DataBuffer);
+
+ /// Read the file header.
+ std::error_code readHeader() override;
+ /// Read a single record.
+ std::error_code readNextRecord(InstrProfRecord &Record) override;
+
+ /// Return the pointer to InstrProfRecord associated with FuncName
+ /// and FuncHash
+ ErrorOr<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
+ uint64_t FuncHash);
+
+ /// Fill Counts with the profile data for the given function name.
+ std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
+ std::vector<uint64_t> &Counts);
+
+ /// Return the maximum of all known function counts.
+ uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
+
+ /// Factory method to create an indexed reader.
+ static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ create(std::string Path);
+
+ static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ create(std::unique_ptr<MemoryBuffer> Buffer);
+
+ // Used for testing purpose only.
+ void setValueProfDataEndianness(support::endianness Endianness) {
+ Index->setValueProfDataEndianness(Endianness);
+ }
+};
+