+typedef InstrProfLookupTrait::data_type data_type;
+typedef InstrProfLookupTrait::offset_type offset_type;
+
+bool InstrProfLookupTrait::ReadValueProfilingData(
+ const unsigned char *&D, const unsigned char *const End) {
+ ErrorOr<std::unique_ptr<IndexedInstrProf::ValueProfData>> VDataPtrOrErr =
+ IndexedInstrProf::ValueProfData::getValueProfData(
+ D, End, ValueProfDataEndianness);
+
+ if (VDataPtrOrErr.getError())
+ return false;
+
+ VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), &HashKeys);
+ D += VDataPtrOrErr.get()->TotalSize;
+
+ return true;
+}
+
+data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
+ offset_type N) {
+ // Check if the data is corrupt. If so, don't try to read it.
+ if (N % sizeof(uint64_t))
+ return data_type();
+
+ DataBuffer.clear();
+ std::vector<uint64_t> CounterBuffer;
+
+ using namespace support;
+ const unsigned char *End = D + N;
+ while (D < End) {
+ // Read hash.
+ if (D + sizeof(uint64_t) >= End)
+ return data_type();
+ uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
+
+ // Initialize number of counters for FormatVersion == 1.
+ uint64_t CountsSize = N / sizeof(uint64_t) - 1;
+ // If format version is different then read the number of counters.
+ if (FormatVersion != 1) {
+ if (D + sizeof(uint64_t) > End)
+ return data_type();
+ CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
+ }
+ // Read counter values.
+ if (D + CountsSize * sizeof(uint64_t) > End)
+ return data_type();
+
+ CounterBuffer.clear();
+ CounterBuffer.reserve(CountsSize);
+ for (uint64_t J = 0; J < CountsSize; ++J)
+ CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
+
+ DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
+
+ // Read value profiling data.
+ if (FormatVersion > 2 && !ReadValueProfilingData(D, End)) {
+ DataBuffer.clear();
+ return data_type();
+ }
+ }
+ return DataBuffer;
+}
+
+std::error_code
+InstrProfReaderIndex::getRecords(StringRef FuncName,
+ ArrayRef<InstrProfRecord> &Data) {
+ auto Iter = Index->find(FuncName);
+ if (Iter == Index->end())
+ return instrprof_error::unknown_function;
+
+ Data = (*Iter);
+ if (Data.empty())
+ return instrprof_error::malformed;
+
+ return instrprof_error::success;
+}
+
+std::error_code InstrProfReaderIndex::getRecords(
+ ArrayRef<InstrProfRecord> &Data) {
+ if (atEnd()) return instrprof_error::eof;
+
+ Data = *RecordIterator;
+
+ if (Data.empty()) return instrprof_error::malformed;
+
+ return instrprof_error::success;
+}
+
+void InstrProfReaderIndex::Init(const unsigned char *Buckets,
+ const unsigned char *const Payload,
+ const unsigned char *const Base,
+ IndexedInstrProf::HashT HashType,
+ uint64_t Version) {
+ FormatVersion = Version;
+ Index.reset(IndexType::Create(Buckets, Payload, Base,
+ InstrProfLookupTrait(HashType, Version)));
+ // Form the map of hash values to const char* keys in profiling data.
+ std::vector<std::pair<uint64_t, const char *>> HashKeys;
+ for (auto Key : Index->keys()) {
+ const char *KeyTableRef = StringTable.insertString(Key);
+ HashKeys.push_back(std::make_pair(ComputeHash(HashType, Key), KeyTableRef));
+ }
+ std::sort(HashKeys.begin(), HashKeys.end(), less_first());
+ HashKeys.erase(std::unique(HashKeys.begin(), HashKeys.end()), HashKeys.end());
+ // Set the hash key map for the InstrLookupTrait
+ Index->getInfoObj().setHashKeys(std::move(HashKeys));
+ RecordIterator = Index->data_begin();
+}
+