1f8d79198SJustin Bogner //=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=// 2f8d79198SJustin Bogner // 3f8d79198SJustin Bogner // The LLVM Compiler Infrastructure 4f8d79198SJustin Bogner // 5f8d79198SJustin Bogner // This file is distributed under the University of Illinois Open Source 6f8d79198SJustin Bogner // License. See LICENSE.TXT for details. 7f8d79198SJustin Bogner // 8f8d79198SJustin Bogner //===----------------------------------------------------------------------===// 9f8d79198SJustin Bogner // 10f8d79198SJustin Bogner // This file contains support for reading profiling data for clang's 11f8d79198SJustin Bogner // instrumentation based PGO and coverage. 12f8d79198SJustin Bogner // 13f8d79198SJustin Bogner //===----------------------------------------------------------------------===// 14f8d79198SJustin Bogner 15f8d79198SJustin Bogner #include "llvm/ProfileData/InstrProfReader.h" 160a446fd5SBenjamin Kramer #include "llvm/ADT/STLExtras.h" 17f8d79198SJustin Bogner #include <cassert> 18f8d79198SJustin Bogner 19f8d79198SJustin Bogner using namespace llvm; 20f8d79198SJustin Bogner 21fcd55607SDiego Novillo static ErrorOr<std::unique_ptr<MemoryBuffer>> 22fcd55607SDiego Novillo setupMemoryBuffer(std::string Path) { 23adf21f2aSRafael Espindola ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 24adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(Path); 25adf21f2aSRafael Espindola if (std::error_code EC = BufferOrErr.getError()) 26f8d79198SJustin Bogner return EC; 272b6c537bSJustin Bogner return std::move(BufferOrErr.get()); 28b7aa2630SJustin Bogner } 29b7aa2630SJustin Bogner 30db4ed0bdSRafael Espindola static std::error_code initializeReader(InstrProfReader &Reader) { 31b7aa2630SJustin Bogner return Reader.readHeader(); 32b7aa2630SJustin Bogner } 33b7aa2630SJustin Bogner 34fcd55607SDiego Novillo ErrorOr<std::unique_ptr<InstrProfReader>> 35fcd55607SDiego Novillo InstrProfReader::create(std::string Path) { 36b7aa2630SJustin Bogner // Set up the buffer to read. 37fcd55607SDiego Novillo auto BufferOrError = setupMemoryBuffer(Path); 38fcd55607SDiego Novillo if (std::error_code EC = BufferOrError.getError()) 39b7aa2630SJustin Bogner return EC; 402b6c537bSJustin Bogner return InstrProfReader::create(std::move(BufferOrError.get())); 412b6c537bSJustin Bogner } 42f8d79198SJustin Bogner 432b6c537bSJustin Bogner ErrorOr<std::unique_ptr<InstrProfReader>> 442b6c537bSJustin Bogner InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { 452b6c537bSJustin Bogner // Sanity check the buffer. 462b6c537bSJustin Bogner if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) 472b6c537bSJustin Bogner return instrprof_error::too_large; 482b6c537bSJustin Bogner 49fcd55607SDiego Novillo std::unique_ptr<InstrProfReader> Result; 5009a67f45SDuncan P. N. Exon Smith // Create the reader. 51b7aa2630SJustin Bogner if (IndexedInstrProfReader::hasFormat(*Buffer)) 52b7aa2630SJustin Bogner Result.reset(new IndexedInstrProfReader(std::move(Buffer))); 53b7aa2630SJustin Bogner else if (RawInstrProfReader64::hasFormat(*Buffer)) 544680361dSDuncan P. N. Exon Smith Result.reset(new RawInstrProfReader64(std::move(Buffer))); 554680361dSDuncan P. N. Exon Smith else if (RawInstrProfReader32::hasFormat(*Buffer)) 564680361dSDuncan P. N. Exon Smith Result.reset(new RawInstrProfReader32(std::move(Buffer))); 574f823667SNathan Slingerland else if (TextInstrProfReader::hasFormat(*Buffer)) 58911ced6bSNathan Slingerland Result.reset(new TextInstrProfReader(std::move(Buffer))); 594f823667SNathan Slingerland else 604f823667SNathan Slingerland return instrprof_error::unrecognized_format; 6109a67f45SDuncan P. N. Exon Smith 62b7aa2630SJustin Bogner // Initialize the reader and return the result. 63fcd55607SDiego Novillo if (std::error_code EC = initializeReader(*Result)) 64fcd55607SDiego Novillo return EC; 65fcd55607SDiego Novillo 66fcd55607SDiego Novillo return std::move(Result); 67b7aa2630SJustin Bogner } 68b7aa2630SJustin Bogner 69ab89ed7dSJustin Bogner ErrorOr<std::unique_ptr<IndexedInstrProfReader>> 70ab89ed7dSJustin Bogner IndexedInstrProfReader::create(std::string Path) { 71b7aa2630SJustin Bogner // Set up the buffer to read. 72fcd55607SDiego Novillo auto BufferOrError = setupMemoryBuffer(Path); 73fcd55607SDiego Novillo if (std::error_code EC = BufferOrError.getError()) 74b7aa2630SJustin Bogner return EC; 752b6c537bSJustin Bogner return IndexedInstrProfReader::create(std::move(BufferOrError.get())); 762b6c537bSJustin Bogner } 77b7aa2630SJustin Bogner 782b6c537bSJustin Bogner 792b6c537bSJustin Bogner ErrorOr<std::unique_ptr<IndexedInstrProfReader>> 802b6c537bSJustin Bogner IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { 812b6c537bSJustin Bogner // Sanity check the buffer. 822b6c537bSJustin Bogner if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) 832b6c537bSJustin Bogner return instrprof_error::too_large; 84ab89ed7dSJustin Bogner 85b7aa2630SJustin Bogner // Create the reader. 86b7aa2630SJustin Bogner if (!IndexedInstrProfReader::hasFormat(*Buffer)) 87b7aa2630SJustin Bogner return instrprof_error::bad_magic; 882b6c537bSJustin Bogner auto Result = llvm::make_unique<IndexedInstrProfReader>(std::move(Buffer)); 89b7aa2630SJustin Bogner 90b7aa2630SJustin Bogner // Initialize the reader and return the result. 91ab89ed7dSJustin Bogner if (std::error_code EC = initializeReader(*Result)) 92ab89ed7dSJustin Bogner return EC; 93ab89ed7dSJustin Bogner 94ab89ed7dSJustin Bogner return std::move(Result); 95f8d79198SJustin Bogner } 96f8d79198SJustin Bogner 97f8d79198SJustin Bogner void InstrProfIterator::Increment() { 98f8d79198SJustin Bogner if (Reader->readNextRecord(Record)) 99f8d79198SJustin Bogner *this = InstrProfIterator(); 100f8d79198SJustin Bogner } 101f8d79198SJustin Bogner 1024f823667SNathan Slingerland bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { 1034f823667SNathan Slingerland // Verify that this really looks like plain ASCII text by checking a 1044f823667SNathan Slingerland // 'reasonable' number of characters (up to profile magic size). 1054f823667SNathan Slingerland size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t)); 1064f823667SNathan Slingerland StringRef buffer = Buffer.getBufferStart(); 1072491dd11SVedant Kumar return count == 0 || 1082491dd11SVedant Kumar std::all_of(buffer.begin(), buffer.begin() + count, 1094f823667SNathan Slingerland [](char c) { return ::isprint(c) || ::isspace(c); }); 1104f823667SNathan Slingerland } 1114f823667SNathan Slingerland 11233c76c0cSRong Xu // Read the profile variant flag from the header: ":FE" means this is a FE 11333c76c0cSRong Xu // generated profile. ":IR" means this is an IR level profile. Other strings 11433c76c0cSRong Xu // with a leading ':' will be reported an error format. 115a716cc5cSXinliang David Li std::error_code TextInstrProfReader::readHeader() { 116a716cc5cSXinliang David Li Symtab.reset(new InstrProfSymtab()); 11733c76c0cSRong Xu bool IsIRInstr = false; 11833c76c0cSRong Xu if (!Line->startswith(":")) { 11933c76c0cSRong Xu IsIRLevelProfile = false; 12033c76c0cSRong Xu return success(); 12133c76c0cSRong Xu } 12233c76c0cSRong Xu StringRef Str = (Line)->substr(1); 12333c76c0cSRong Xu if (Str.equals_lower("ir")) 12433c76c0cSRong Xu IsIRInstr = true; 12533c76c0cSRong Xu else if (Str.equals_lower("fe")) 12633c76c0cSRong Xu IsIRInstr = false; 12733c76c0cSRong Xu else 12833c76c0cSRong Xu return instrprof_error::bad_header; 12933c76c0cSRong Xu 13033c76c0cSRong Xu ++Line; 13133c76c0cSRong Xu IsIRLevelProfile = IsIRInstr; 132a716cc5cSXinliang David Li return success(); 133a716cc5cSXinliang David Li } 134a716cc5cSXinliang David Li 135e3bf4fd3SXinliang David Li std::error_code 136e3bf4fd3SXinliang David Li TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { 137e3bf4fd3SXinliang David Li 138e3bf4fd3SXinliang David Li #define CHECK_LINE_END(Line) \ 139e3bf4fd3SXinliang David Li if (Line.is_at_end()) \ 140e3bf4fd3SXinliang David Li return error(instrprof_error::truncated); 141e3bf4fd3SXinliang David Li #define READ_NUM(Str, Dst) \ 142e3bf4fd3SXinliang David Li if ((Str).getAsInteger(10, (Dst))) \ 143e3bf4fd3SXinliang David Li return error(instrprof_error::malformed); 144e3bf4fd3SXinliang David Li #define VP_READ_ADVANCE(Val) \ 145e3bf4fd3SXinliang David Li CHECK_LINE_END(Line); \ 146e3bf4fd3SXinliang David Li uint32_t Val; \ 147e3bf4fd3SXinliang David Li READ_NUM((*Line), (Val)); \ 148e3bf4fd3SXinliang David Li Line++; 149e3bf4fd3SXinliang David Li 150e3bf4fd3SXinliang David Li if (Line.is_at_end()) 151e3bf4fd3SXinliang David Li return success(); 152a716cc5cSXinliang David Li 153e3bf4fd3SXinliang David Li uint32_t NumValueKinds; 154e3bf4fd3SXinliang David Li if (Line->getAsInteger(10, NumValueKinds)) { 155e3bf4fd3SXinliang David Li // No value profile data 156e3bf4fd3SXinliang David Li return success(); 157e3bf4fd3SXinliang David Li } 158e3bf4fd3SXinliang David Li if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1) 159e3bf4fd3SXinliang David Li return error(instrprof_error::malformed); 160e3bf4fd3SXinliang David Li Line++; 161e3bf4fd3SXinliang David Li 162e3bf4fd3SXinliang David Li for (uint32_t VK = 0; VK < NumValueKinds; VK++) { 163e3bf4fd3SXinliang David Li VP_READ_ADVANCE(ValueKind); 164e3bf4fd3SXinliang David Li if (ValueKind > IPVK_Last) 165e3bf4fd3SXinliang David Li return error(instrprof_error::malformed); 166e3bf4fd3SXinliang David Li VP_READ_ADVANCE(NumValueSites); 167e3bf4fd3SXinliang David Li if (!NumValueSites) 168e3bf4fd3SXinliang David Li continue; 169e3bf4fd3SXinliang David Li 170e3bf4fd3SXinliang David Li Record.reserveSites(VK, NumValueSites); 171e3bf4fd3SXinliang David Li for (uint32_t S = 0; S < NumValueSites; S++) { 172e3bf4fd3SXinliang David Li VP_READ_ADVANCE(NumValueData); 173e3bf4fd3SXinliang David Li 174e3bf4fd3SXinliang David Li std::vector<InstrProfValueData> CurrentValues; 175e3bf4fd3SXinliang David Li for (uint32_t V = 0; V < NumValueData; V++) { 176e3bf4fd3SXinliang David Li CHECK_LINE_END(Line); 177e3bf4fd3SXinliang David Li std::pair<StringRef, StringRef> VD = Line->split(':'); 178e3bf4fd3SXinliang David Li uint64_t TakenCount, Value; 179a716cc5cSXinliang David Li if (VK == IPVK_IndirectCallTarget) { 180a716cc5cSXinliang David Li Symtab->addFuncName(VD.first); 181a716cc5cSXinliang David Li Value = IndexedInstrProf::ComputeHash(VD.first); 182a716cc5cSXinliang David Li } else { 183e3bf4fd3SXinliang David Li READ_NUM(VD.first, Value); 184e3bf4fd3SXinliang David Li } 185a716cc5cSXinliang David Li READ_NUM(VD.second, TakenCount); 186e3bf4fd3SXinliang David Li CurrentValues.push_back({Value, TakenCount}); 187e3bf4fd3SXinliang David Li Line++; 188e3bf4fd3SXinliang David Li } 189e3bf4fd3SXinliang David Li Record.addValueData(VK, S, CurrentValues.data(), NumValueData, nullptr); 190e3bf4fd3SXinliang David Li } 191e3bf4fd3SXinliang David Li } 192e3bf4fd3SXinliang David Li return success(); 193e3bf4fd3SXinliang David Li 194e3bf4fd3SXinliang David Li #undef CHECK_LINE_END 195e3bf4fd3SXinliang David Li #undef READ_NUM 196e3bf4fd3SXinliang David Li #undef VP_READ_ADVANCE 197e3bf4fd3SXinliang David Li } 198e3bf4fd3SXinliang David Li 199db4ed0bdSRafael Espindola std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { 200cf36a366SJustin Bogner // Skip empty lines and comments. 201cf36a366SJustin Bogner while (!Line.is_at_end() && (Line->empty() || Line->startswith("#"))) 202f8d79198SJustin Bogner ++Line; 203f8d79198SJustin Bogner // If we hit EOF while looking for a name, we're done. 204a716cc5cSXinliang David Li if (Line.is_at_end()) { 205a716cc5cSXinliang David Li Symtab->finalizeSymtab(); 206f8d79198SJustin Bogner return error(instrprof_error::eof); 207a716cc5cSXinliang David Li } 208f8d79198SJustin Bogner 209f8d79198SJustin Bogner // Read the function name. 210f8d79198SJustin Bogner Record.Name = *Line++; 211a716cc5cSXinliang David Li Symtab->addFuncName(Record.Name); 212f8d79198SJustin Bogner 213f8d79198SJustin Bogner // Read the function hash. 214f8d79198SJustin Bogner if (Line.is_at_end()) 215f8d79198SJustin Bogner return error(instrprof_error::truncated); 216f95ca075SJustin Bogner if ((Line++)->getAsInteger(0, Record.Hash)) 217f8d79198SJustin Bogner return error(instrprof_error::malformed); 218f8d79198SJustin Bogner 219f8d79198SJustin Bogner // Read the number of counters. 220f8d79198SJustin Bogner uint64_t NumCounters; 221f8d79198SJustin Bogner if (Line.is_at_end()) 222f8d79198SJustin Bogner return error(instrprof_error::truncated); 223f8d79198SJustin Bogner if ((Line++)->getAsInteger(10, NumCounters)) 224f8d79198SJustin Bogner return error(instrprof_error::malformed); 225b59d7c73SJustin Bogner if (NumCounters == 0) 226b59d7c73SJustin Bogner return error(instrprof_error::malformed); 227f8d79198SJustin Bogner 228f8d79198SJustin Bogner // Read each counter and fill our internal storage with the values. 2293a7d44cbSJustin Bogner Record.Counts.clear(); 2303a7d44cbSJustin Bogner Record.Counts.reserve(NumCounters); 231f8d79198SJustin Bogner for (uint64_t I = 0; I < NumCounters; ++I) { 232f8d79198SJustin Bogner if (Line.is_at_end()) 233f8d79198SJustin Bogner return error(instrprof_error::truncated); 234f8d79198SJustin Bogner uint64_t Count; 235f8d79198SJustin Bogner if ((Line++)->getAsInteger(10, Count)) 236f8d79198SJustin Bogner return error(instrprof_error::malformed); 2373a7d44cbSJustin Bogner Record.Counts.push_back(Count); 238f8d79198SJustin Bogner } 239f8d79198SJustin Bogner 240e3bf4fd3SXinliang David Li // Check if value profile data exists and read it if so. 241e3bf4fd3SXinliang David Li if (std::error_code EC = readValueProfileData(Record)) 242e3bf4fd3SXinliang David Li return EC; 243e3bf4fd3SXinliang David Li 244a716cc5cSXinliang David Li // This is needed to avoid two pass parsing because llvm-profdata 245a716cc5cSXinliang David Li // does dumping while reading. 246a716cc5cSXinliang David Li Symtab->finalizeSymtab(); 247f8d79198SJustin Bogner return success(); 248f8d79198SJustin Bogner } 24924b4b653SDuncan P. N. Exon Smith 2504680361dSDuncan P. N. Exon Smith template <class IntPtrT> 2514680361dSDuncan P. N. Exon Smith bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 252d7d83477SDuncan P. N. Exon Smith if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 2534680361dSDuncan P. N. Exon Smith return false; 254d7d83477SDuncan P. N. Exon Smith uint64_t Magic = 255d7d83477SDuncan P. N. Exon Smith *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 256dab183edSXinliang David Li return RawInstrProf::getMagic<IntPtrT>() == Magic || 257dab183edSXinliang David Li sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; 2584680361dSDuncan P. N. Exon Smith } 2594680361dSDuncan P. N. Exon Smith 2604680361dSDuncan P. N. Exon Smith template <class IntPtrT> 261db4ed0bdSRafael Espindola std::error_code RawInstrProfReader<IntPtrT>::readHeader() { 26209a67f45SDuncan P. N. Exon Smith if (!hasFormat(*DataBuffer)) 26309a67f45SDuncan P. N. Exon Smith return error(instrprof_error::bad_magic); 264dab183edSXinliang David Li if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)) 265531bb481SDuncan P. N. Exon Smith return error(instrprof_error::bad_header); 266dab183edSXinliang David Li auto *Header = reinterpret_cast<const RawInstrProf::Header *>( 267dab183edSXinliang David Li DataBuffer->getBufferStart()); 268dab183edSXinliang David Li ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); 26924b4b653SDuncan P. N. Exon Smith return readHeader(*Header); 27024b4b653SDuncan P. N. Exon Smith } 27124b4b653SDuncan P. N. Exon Smith 272a119f323SJustin Bogner template <class IntPtrT> 273db4ed0bdSRafael Espindola std::error_code 274db4ed0bdSRafael Espindola RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { 275a119f323SJustin Bogner const char *End = DataBuffer->getBufferEnd(); 276a119f323SJustin Bogner // Skip zero padding between profiles. 277a119f323SJustin Bogner while (CurrentPos != End && *CurrentPos == 0) 278a119f323SJustin Bogner ++CurrentPos; 279a119f323SJustin Bogner // If there's nothing left, we're done. 280a119f323SJustin Bogner if (CurrentPos == End) 281a119f323SJustin Bogner return instrprof_error::eof; 282a119f323SJustin Bogner // If there isn't enough space for another header, this is probably just 283a119f323SJustin Bogner // garbage at the end of the file. 284dab183edSXinliang David Li if (CurrentPos + sizeof(RawInstrProf::Header) > End) 285a119f323SJustin Bogner return instrprof_error::malformed; 28654b11282SJustin Bogner // The writer ensures each profile is padded to start at an aligned address. 28754b11282SJustin Bogner if (reinterpret_cast<size_t>(CurrentPos) % alignOf<uint64_t>()) 28854b11282SJustin Bogner return instrprof_error::malformed; 289a119f323SJustin Bogner // The magic should have the same byte order as in the previous header. 290a119f323SJustin Bogner uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); 291dab183edSXinliang David Li if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) 292a119f323SJustin Bogner return instrprof_error::bad_magic; 293a119f323SJustin Bogner 294a119f323SJustin Bogner // There's another profile to read, so we need to process the header. 295dab183edSXinliang David Li auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); 296a119f323SJustin Bogner return readHeader(*Header); 297a119f323SJustin Bogner } 298a119f323SJustin Bogner 2994680361dSDuncan P. N. Exon Smith template <class IntPtrT> 300*e44482feSVedant Kumar std::error_code 301*e44482feSVedant Kumar RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 302*e44482feSVedant Kumar std::error_code EC = Symtab.create(StringRef(NamesStart, NamesSize)); 303*e44482feSVedant Kumar if (EC) 304*e44482feSVedant Kumar return EC; 305a716cc5cSXinliang David Li for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { 306a716cc5cSXinliang David Li const IntPtrT FPtr = swap(I->FunctionPointer); 307a716cc5cSXinliang David Li if (!FPtr) 308a716cc5cSXinliang David Li continue; 309a82d6c0aSXinliang David Li Symtab.mapAddress(FPtr, I->NameRef); 310a716cc5cSXinliang David Li } 311a716cc5cSXinliang David Li Symtab.finalizeSymtab(); 312*e44482feSVedant Kumar return success(); 313a716cc5cSXinliang David Li } 314a716cc5cSXinliang David Li 315a716cc5cSXinliang David Li template <class IntPtrT> 316a716cc5cSXinliang David Li std::error_code 317a716cc5cSXinliang David Li RawInstrProfReader<IntPtrT>::readHeader(const RawInstrProf::Header &Header) { 31833c76c0cSRong Xu Version = swap(Header.Version); 31933c76c0cSRong Xu if (GET_VERSION(Version) != RawInstrProf::Version) 32024b4b653SDuncan P. N. Exon Smith return error(instrprof_error::unsupported_version); 32124b4b653SDuncan P. N. Exon Smith 32224b4b653SDuncan P. N. Exon Smith CountersDelta = swap(Header.CountersDelta); 32324b4b653SDuncan P. N. Exon Smith NamesDelta = swap(Header.NamesDelta); 32424b4b653SDuncan P. N. Exon Smith auto DataSize = swap(Header.DataSize); 32524b4b653SDuncan P. N. Exon Smith auto CountersSize = swap(Header.CountersSize); 326a82d6c0aSXinliang David Li NamesSize = swap(Header.NamesSize); 3276fac1741SBetul Buyukkurt auto ValueDataSize = swap(Header.ValueDataSize); 3286fac1741SBetul Buyukkurt ValueKindLast = swap(Header.ValueKindLast); 3296fac1741SBetul Buyukkurt 3306fac1741SBetul Buyukkurt auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); 3316fac1741SBetul Buyukkurt auto PaddingSize = getNumPaddingBytes(NamesSize); 33224b4b653SDuncan P. N. Exon Smith 333dab183edSXinliang David Li ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); 3346fac1741SBetul Buyukkurt ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; 33524b4b653SDuncan P. N. Exon Smith ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; 3366fac1741SBetul Buyukkurt ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; 3376fac1741SBetul Buyukkurt size_t ProfileSize = ValueDataOffset + ValueDataSize; 33824b4b653SDuncan P. N. Exon Smith 339a119f323SJustin Bogner auto *Start = reinterpret_cast<const char *>(&Header); 340a119f323SJustin Bogner if (Start + ProfileSize > DataBuffer->getBufferEnd()) 341531bb481SDuncan P. N. Exon Smith return error(instrprof_error::bad_header); 34224b4b653SDuncan P. N. Exon Smith 343dab183edSXinliang David Li Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( 344dab183edSXinliang David Li Start + DataOffset); 34524b4b653SDuncan P. N. Exon Smith DataEnd = Data + DataSize; 346d7d83477SDuncan P. N. Exon Smith CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); 347d7d83477SDuncan P. N. Exon Smith NamesStart = Start + NamesOffset; 3486fac1741SBetul Buyukkurt ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); 349a119f323SJustin Bogner ProfileEnd = Start + ProfileSize; 35024b4b653SDuncan P. N. Exon Smith 351a716cc5cSXinliang David Li std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 352*e44482feSVedant Kumar if (auto EC = createSymtab(*NewSymtab.get())) 353*e44482feSVedant Kumar return EC; 354*e44482feSVedant Kumar 355a716cc5cSXinliang David Li Symtab = std::move(NewSymtab); 35624b4b653SDuncan P. N. Exon Smith return success(); 35724b4b653SDuncan P. N. Exon Smith } 35824b4b653SDuncan P. N. Exon Smith 3594680361dSDuncan P. N. Exon Smith template <class IntPtrT> 360cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) { 361a82d6c0aSXinliang David Li Record.Name = getName(Data->NameRef); 362cf4a128cSXinliang David Li return success(); 363cf4a128cSXinliang David Li } 364cf4a128cSXinliang David Li 365cf4a128cSXinliang David Li template <class IntPtrT> 366cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readFuncHash( 367cf4a128cSXinliang David Li InstrProfRecord &Record) { 368cf4a128cSXinliang David Li Record.Hash = swap(Data->FuncHash); 369cf4a128cSXinliang David Li return success(); 370cf4a128cSXinliang David Li } 371cf4a128cSXinliang David Li 372cf4a128cSXinliang David Li template <class IntPtrT> 373cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readRawCounts( 374cf4a128cSXinliang David Li InstrProfRecord &Record) { 375b59d7c73SJustin Bogner uint32_t NumCounters = swap(Data->NumCounters); 376cf4a128cSXinliang David Li IntPtrT CounterPtr = Data->CounterPtr; 377b59d7c73SJustin Bogner if (NumCounters == 0) 378b59d7c73SJustin Bogner return error(instrprof_error::malformed); 379cf4a128cSXinliang David Li 380cf4a128cSXinliang David Li auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); 381cf4a128cSXinliang David Li auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); 38224b4b653SDuncan P. N. Exon Smith 38324b4b653SDuncan P. N. Exon Smith // Check bounds. 384cf4a128cSXinliang David Li if (RawCounts.data() < CountersStart || 385d7d83477SDuncan P. N. Exon Smith RawCounts.data() + RawCounts.size() > NamesStartAsCounter) 38624b4b653SDuncan P. N. Exon Smith return error(instrprof_error::malformed); 38724b4b653SDuncan P. N. Exon Smith 38824b4b653SDuncan P. N. Exon Smith if (ShouldSwapBytes) { 3893a7d44cbSJustin Bogner Record.Counts.clear(); 3903a7d44cbSJustin Bogner Record.Counts.reserve(RawCounts.size()); 39124b4b653SDuncan P. N. Exon Smith for (uint64_t Count : RawCounts) 3923a7d44cbSJustin Bogner Record.Counts.push_back(swap(Count)); 39324b4b653SDuncan P. N. Exon Smith } else 39424b4b653SDuncan P. N. Exon Smith Record.Counts = RawCounts; 39524b4b653SDuncan P. N. Exon Smith 396cf4a128cSXinliang David Li return success(); 397cf4a128cSXinliang David Li } 398cf4a128cSXinliang David Li 399cf4a128cSXinliang David Li template <class IntPtrT> 40001cb9bd7SXinliang David Li std::error_code 40101cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readValueProfilingData(InstrProfRecord &Record) { 4026fac1741SBetul Buyukkurt 4036fac1741SBetul Buyukkurt Record.clearValueData(); 404d922c26cSXinliang David Li CurValueDataSize = 0; 405d922c26cSXinliang David Li // Need to match the logic in value profile dumper code in compiler-rt: 406d922c26cSXinliang David Li uint32_t NumValueKinds = 0; 407d922c26cSXinliang David Li for (uint32_t I = 0; I < IPVK_Last + 1; I++) 408d922c26cSXinliang David Li NumValueKinds += (Data->NumValueSites[I] != 0); 409d922c26cSXinliang David Li 410d922c26cSXinliang David Li if (!NumValueKinds) 4116fac1741SBetul Buyukkurt return success(); 4126fac1741SBetul Buyukkurt 41301cb9bd7SXinliang David Li ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 414d922c26cSXinliang David Li ValueProfData::getValueProfData(ValueDataStart, 41501cb9bd7SXinliang David Li (const unsigned char *)ProfileEnd, 41601cb9bd7SXinliang David Li getDataEndianness()); 4176fac1741SBetul Buyukkurt 41801cb9bd7SXinliang David Li if (VDataPtrOrErr.getError()) 41901cb9bd7SXinliang David Li return VDataPtrOrErr.getError(); 4206fac1741SBetul Buyukkurt 4212f36f059SAdam Nemet // Note that besides deserialization, this also performs the conversion for 4222f36f059SAdam Nemet // indirect call targets. The function pointers from the raw profile are 4232f36f059SAdam Nemet // remapped into function name hashes. 424a716cc5cSXinliang David Li VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); 425d922c26cSXinliang David Li CurValueDataSize = VDataPtrOrErr.get()->getSize(); 4266fac1741SBetul Buyukkurt return success(); 4276fac1741SBetul Buyukkurt } 4286fac1741SBetul Buyukkurt 4296fac1741SBetul Buyukkurt template <class IntPtrT> 43001cb9bd7SXinliang David Li std::error_code 43101cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) { 432cf4a128cSXinliang David Li if (atEnd()) 4334c3ab815SXinliang David Li if (std::error_code EC = readNextHeader(ProfileEnd)) 4344c3ab815SXinliang David Li return EC; 435cf4a128cSXinliang David Li 436cf4a128cSXinliang David Li // Read name ad set it in Record. 4374c3ab815SXinliang David Li if (std::error_code EC = readName(Record)) 4384c3ab815SXinliang David Li return EC; 439cf4a128cSXinliang David Li 440cf4a128cSXinliang David Li // Read FuncHash and set it in Record. 4414c3ab815SXinliang David Li if (std::error_code EC = readFuncHash(Record)) 4424c3ab815SXinliang David Li return EC; 443cf4a128cSXinliang David Li 444cf4a128cSXinliang David Li // Read raw counts and set Record. 4454c3ab815SXinliang David Li if (std::error_code EC = readRawCounts(Record)) 4464c3ab815SXinliang David Li return EC; 447cf4a128cSXinliang David Li 4486fac1741SBetul Buyukkurt // Read value data and set Record. 4492d4803e8SXinliang David Li if (std::error_code EC = readValueProfilingData(Record)) 4502d4803e8SXinliang David Li return EC; 4516fac1741SBetul Buyukkurt 45224b4b653SDuncan P. N. Exon Smith // Iterate. 453cf4a128cSXinliang David Li advanceData(); 45424b4b653SDuncan P. N. Exon Smith return success(); 45524b4b653SDuncan P. N. Exon Smith } 4564680361dSDuncan P. N. Exon Smith 4574680361dSDuncan P. N. Exon Smith namespace llvm { 4584680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint32_t>; 4594680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint64_t>; 4604680361dSDuncan P. N. Exon Smith } 461b7aa2630SJustin Bogner 462b5d368e8SJustin Bogner InstrProfLookupTrait::hash_value_type 463b5d368e8SJustin Bogner InstrProfLookupTrait::ComputeHash(StringRef K) { 464b5d368e8SJustin Bogner return IndexedInstrProf::ComputeHash(HashType, K); 465b5d368e8SJustin Bogner } 466b5d368e8SJustin Bogner 4673a7d44cbSJustin Bogner typedef InstrProfLookupTrait::data_type data_type; 4683a7d44cbSJustin Bogner typedef InstrProfLookupTrait::offset_type offset_type; 4693a7d44cbSJustin Bogner 470be969c29SXinliang David Li bool InstrProfLookupTrait::readValueProfilingData( 4719e9a057aSJustin Bogner const unsigned char *&D, const unsigned char *const End) { 47299556877SXinliang David Li ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 47399556877SXinliang David Li ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); 4749e9a057aSJustin Bogner 475ee415895SXinliang David Li if (VDataPtrOrErr.getError()) 4769e9a057aSJustin Bogner return false; 4772004f003SXinliang David Li 478a716cc5cSXinliang David Li VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); 479ee415895SXinliang David Li D += VDataPtrOrErr.get()->TotalSize; 4809e9a057aSJustin Bogner 4819e9a057aSJustin Bogner return true; 4829e9a057aSJustin Bogner } 4839e9a057aSJustin Bogner 4843a7d44cbSJustin Bogner data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 4853a7d44cbSJustin Bogner offset_type N) { 4863a7d44cbSJustin Bogner // Check if the data is corrupt. If so, don't try to read it. 4873a7d44cbSJustin Bogner if (N % sizeof(uint64_t)) 4883a7d44cbSJustin Bogner return data_type(); 4893a7d44cbSJustin Bogner 4903a7d44cbSJustin Bogner DataBuffer.clear(); 4913a7d44cbSJustin Bogner std::vector<uint64_t> CounterBuffer; 4929e9a057aSJustin Bogner 4933a7d44cbSJustin Bogner using namespace support; 4949e9a057aSJustin Bogner const unsigned char *End = D + N; 4959e9a057aSJustin Bogner while (D < End) { 496c758387eSXinliang David Li // Read hash. 4979e9a057aSJustin Bogner if (D + sizeof(uint64_t) >= End) 4989e9a057aSJustin Bogner return data_type(); 4993a7d44cbSJustin Bogner uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); 5003a7d44cbSJustin Bogner 50133c76c0cSRong Xu // Initialize number of counters for GET_VERSION(FormatVersion) == 1. 5029e9a057aSJustin Bogner uint64_t CountsSize = N / sizeof(uint64_t) - 1; 503c758387eSXinliang David Li // If format version is different then read the number of counters. 50433c76c0cSRong Xu if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { 5059e9a057aSJustin Bogner if (D + sizeof(uint64_t) > End) 5063a7d44cbSJustin Bogner return data_type(); 5079e9a057aSJustin Bogner CountsSize = endian::readNext<uint64_t, little, unaligned>(D); 5089e9a057aSJustin Bogner } 509c758387eSXinliang David Li // Read counter values. 5109e9a057aSJustin Bogner if (D + CountsSize * sizeof(uint64_t) > End) 5113a7d44cbSJustin Bogner return data_type(); 5123a7d44cbSJustin Bogner 5133a7d44cbSJustin Bogner CounterBuffer.clear(); 5149e9a057aSJustin Bogner CounterBuffer.reserve(CountsSize); 5159e9a057aSJustin Bogner for (uint64_t J = 0; J < CountsSize; ++J) 5163a7d44cbSJustin Bogner CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); 5173a7d44cbSJustin Bogner 5182004f003SXinliang David Li DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); 5199e9a057aSJustin Bogner 520c758387eSXinliang David Li // Read value profiling data. 52133c76c0cSRong Xu if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && 522a6b2c4f7SXinliang David Li !readValueProfilingData(D, End)) { 5239e9a057aSJustin Bogner DataBuffer.clear(); 5249e9a057aSJustin Bogner return data_type(); 5259e9a057aSJustin Bogner } 5263a7d44cbSJustin Bogner } 5273a7d44cbSJustin Bogner return DataBuffer; 5283a7d44cbSJustin Bogner } 5293a7d44cbSJustin Bogner 530a28306dbSXinliang David Li template <typename HashTableImpl> 531a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords( 532a28306dbSXinliang David Li StringRef FuncName, ArrayRef<InstrProfRecord> &Data) { 533a28306dbSXinliang David Li auto Iter = HashTable->find(FuncName); 534a28306dbSXinliang David Li if (Iter == HashTable->end()) 5354c3ab815SXinliang David Li return instrprof_error::unknown_function; 536140f4c4fSXinliang David Li 537140f4c4fSXinliang David Li Data = (*Iter); 5384c3ab815SXinliang David Li if (Data.empty()) 5394c3ab815SXinliang David Li return instrprof_error::malformed; 540140f4c4fSXinliang David Li 541140f4c4fSXinliang David Li return instrprof_error::success; 542140f4c4fSXinliang David Li } 543140f4c4fSXinliang David Li 544a28306dbSXinliang David Li template <typename HashTableImpl> 545a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords( 546140f4c4fSXinliang David Li ArrayRef<InstrProfRecord> &Data) { 547a28306dbSXinliang David Li if (atEnd()) 548a28306dbSXinliang David Li return instrprof_error::eof; 549140f4c4fSXinliang David Li 550140f4c4fSXinliang David Li Data = *RecordIterator; 551140f4c4fSXinliang David Li 5522d4803e8SXinliang David Li if (Data.empty()) 5532d4803e8SXinliang David Li return instrprof_error::malformed; 554140f4c4fSXinliang David Li 555140f4c4fSXinliang David Li return instrprof_error::success; 556140f4c4fSXinliang David Li } 557140f4c4fSXinliang David Li 558a28306dbSXinliang David Li template <typename HashTableImpl> 559a28306dbSXinliang David Li InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( 560a28306dbSXinliang David Li const unsigned char *Buckets, const unsigned char *const Payload, 561a28306dbSXinliang David Li const unsigned char *const Base, IndexedInstrProf::HashT HashType, 562140f4c4fSXinliang David Li uint64_t Version) { 563140f4c4fSXinliang David Li FormatVersion = Version; 564a28306dbSXinliang David Li HashTable.reset(HashTableImpl::Create( 565a28306dbSXinliang David Li Buckets, Payload, Base, 566a28306dbSXinliang David Li typename HashTableImpl::InfoType(HashType, Version))); 567a28306dbSXinliang David Li RecordIterator = HashTable->data_begin(); 568140f4c4fSXinliang David Li } 569140f4c4fSXinliang David Li 570b7aa2630SJustin Bogner bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 5714c3ab815SXinliang David Li if (DataBuffer.getBufferSize() < 8) 5724c3ab815SXinliang David Li return false; 573b7aa2630SJustin Bogner using namespace support; 574b7aa2630SJustin Bogner uint64_t Magic = 575b7aa2630SJustin Bogner endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); 576c758387eSXinliang David Li // Verify that it's magical. 577b7aa2630SJustin Bogner return Magic == IndexedInstrProf::Magic; 578b7aa2630SJustin Bogner } 579b7aa2630SJustin Bogner 5806c93ee8dSXinliang David Li const unsigned char * 5816c93ee8dSXinliang David Li IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, 5826c93ee8dSXinliang David Li const unsigned char *Cur) { 5836c93ee8dSXinliang David Li using namespace support; 5846c93ee8dSXinliang David Li if (Version >= IndexedInstrProf::Version4) { 5856c93ee8dSXinliang David Li const IndexedInstrProf::Summary *SummaryInLE = 5866c93ee8dSXinliang David Li reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); 5876c93ee8dSXinliang David Li uint64_t NFields = 5886c93ee8dSXinliang David Li endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields); 5896c93ee8dSXinliang David Li uint64_t NEntries = 5906c93ee8dSXinliang David Li endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries); 5916c93ee8dSXinliang David Li uint32_t SummarySize = 5926c93ee8dSXinliang David Li IndexedInstrProf::Summary::getSize(NFields, NEntries); 5936c93ee8dSXinliang David Li std::unique_ptr<IndexedInstrProf::Summary> SummaryData = 5946c93ee8dSXinliang David Li IndexedInstrProf::allocSummary(SummarySize); 5956c93ee8dSXinliang David Li 5966c93ee8dSXinliang David Li const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); 5976c93ee8dSXinliang David Li uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); 5986c93ee8dSXinliang David Li for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) 5996c93ee8dSXinliang David Li Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]); 6006c93ee8dSXinliang David Li 6014309570dSEaswaran Raman // initialize InstrProfSummary using the SummaryData from disk. 6024309570dSEaswaran Raman this->Summary = llvm::make_unique<InstrProfSummary>(*(SummaryData.get())); 6036c93ee8dSXinliang David Li return Cur + SummarySize; 6046c93ee8dSXinliang David Li } else { 6056c93ee8dSXinliang David Li // For older version of profile data, we need to compute on the fly: 6066c93ee8dSXinliang David Li using namespace IndexedInstrProf; 60740ee23dbSEaswaran Raman this->Summary = 60840ee23dbSEaswaran Raman llvm::make_unique<InstrProfSummary>(ProfileSummary::DefaultCutoffs); 6096c93ee8dSXinliang David Li this->Summary->computeDetailedSummary(); 6106c93ee8dSXinliang David Li return Cur; 6116c93ee8dSXinliang David Li } 6126c93ee8dSXinliang David Li } 6136c93ee8dSXinliang David Li 614db4ed0bdSRafael Espindola std::error_code IndexedInstrProfReader::readHeader() { 615a7c9ed57SAaron Ballman const unsigned char *Start = 616a7c9ed57SAaron Ballman (const unsigned char *)DataBuffer->getBufferStart(); 617b7aa2630SJustin Bogner const unsigned char *Cur = Start; 618a7c9ed57SAaron Ballman if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 619b7aa2630SJustin Bogner return error(instrprof_error::truncated); 620b7aa2630SJustin Bogner 621b7aa2630SJustin Bogner using namespace support; 622b7aa2630SJustin Bogner 623dab183edSXinliang David Li auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); 624dab183edSXinliang David Li Cur += sizeof(IndexedInstrProf::Header); 625dab183edSXinliang David Li 626b7aa2630SJustin Bogner // Check the magic number. 627dab183edSXinliang David Li uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic); 628b7aa2630SJustin Bogner if (Magic != IndexedInstrProf::Magic) 629b7aa2630SJustin Bogner return error(instrprof_error::bad_magic); 630b7aa2630SJustin Bogner 631b7aa2630SJustin Bogner // Read the version. 632140f4c4fSXinliang David Li uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version); 63333c76c0cSRong Xu if (GET_VERSION(FormatVersion) > 63433c76c0cSRong Xu IndexedInstrProf::ProfVersion::CurrentVersion) 635b7aa2630SJustin Bogner return error(instrprof_error::unsupported_version); 636b7aa2630SJustin Bogner 6376c93ee8dSXinliang David Li Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur); 638b7aa2630SJustin Bogner 639b7aa2630SJustin Bogner // Read the hash type and start offset. 640b7aa2630SJustin Bogner IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( 641dab183edSXinliang David Li endian::byte_swap<uint64_t, little>(Header->HashType)); 642b7aa2630SJustin Bogner if (HashType > IndexedInstrProf::HashT::Last) 643b7aa2630SJustin Bogner return error(instrprof_error::unsupported_hash_type); 644dab183edSXinliang David Li 645dab183edSXinliang David Li uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset); 646b7aa2630SJustin Bogner 647b7aa2630SJustin Bogner // The rest of the file is an on disk hash table. 648a28306dbSXinliang David Li InstrProfReaderIndexBase *IndexPtr = nullptr; 649a28306dbSXinliang David Li IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>( 650a28306dbSXinliang David Li Start + HashOffset, Cur, Start, HashType, FormatVersion); 651a28306dbSXinliang David Li Index.reset(IndexPtr); 652b7aa2630SJustin Bogner return success(); 653b7aa2630SJustin Bogner } 654b7aa2630SJustin Bogner 655a716cc5cSXinliang David Li InstrProfSymtab &IndexedInstrProfReader::getSymtab() { 656a716cc5cSXinliang David Li if (Symtab.get()) 657a716cc5cSXinliang David Li return *Symtab.get(); 658a716cc5cSXinliang David Li 659a716cc5cSXinliang David Li std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 660a716cc5cSXinliang David Li Index->populateSymtab(*NewSymtab.get()); 661a716cc5cSXinliang David Li 662a716cc5cSXinliang David Li Symtab = std::move(NewSymtab); 663a716cc5cSXinliang David Li return *Symtab.get(); 664a716cc5cSXinliang David Li } 665a716cc5cSXinliang David Li 6666aa216c2SXinliang David Li ErrorOr<InstrProfRecord> 6676aa216c2SXinliang David Li IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName, 6686aa216c2SXinliang David Li uint64_t FuncHash) { 669140f4c4fSXinliang David Li ArrayRef<InstrProfRecord> Data; 670a28306dbSXinliang David Li std::error_code EC = Index->getRecords(FuncName, Data); 6714c3ab815SXinliang David Li if (EC != instrprof_error::success) 6724c3ab815SXinliang David Li return EC; 673821d7471SJustin Bogner // Found it. Look for counters with the right hash. 6743a7d44cbSJustin Bogner for (unsigned I = 0, E = Data.size(); I < E; ++I) { 675821d7471SJustin Bogner // Check for a match and fill the vector if there is one. 6763a7d44cbSJustin Bogner if (Data[I].Hash == FuncHash) { 6772004f003SXinliang David Li return std::move(Data[I]); 678b7aa2630SJustin Bogner } 679821d7471SJustin Bogner } 680821d7471SJustin Bogner return error(instrprof_error::hash_mismatch); 681821d7471SJustin Bogner } 682b7aa2630SJustin Bogner 6836aa216c2SXinliang David Li std::error_code 6846aa216c2SXinliang David Li IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, uint64_t FuncHash, 6856aa216c2SXinliang David Li std::vector<uint64_t> &Counts) { 6862004f003SXinliang David Li ErrorOr<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 6876aa216c2SXinliang David Li if (std::error_code EC = Record.getError()) 6886aa216c2SXinliang David Li return EC; 6892004f003SXinliang David Li 6902004f003SXinliang David Li Counts = Record.get().Counts; 6912004f003SXinliang David Li return success(); 6922004f003SXinliang David Li } 6932004f003SXinliang David Li 694140f4c4fSXinliang David Li std::error_code IndexedInstrProfReader::readNextRecord( 695140f4c4fSXinliang David Li InstrProfRecord &Record) { 6963a7d44cbSJustin Bogner static unsigned RecordIndex = 0; 697140f4c4fSXinliang David Li 698140f4c4fSXinliang David Li ArrayRef<InstrProfRecord> Data; 699140f4c4fSXinliang David Li 700a28306dbSXinliang David Li std::error_code EC = Index->getRecords(Data); 7014c3ab815SXinliang David Li if (EC != instrprof_error::success) 7024c3ab815SXinliang David Li return error(EC); 703140f4c4fSXinliang David Li 7043a7d44cbSJustin Bogner Record = Data[RecordIndex++]; 7053a7d44cbSJustin Bogner if (RecordIndex >= Data.size()) { 706a28306dbSXinliang David Li Index->advanceToNextKey(); 7073a7d44cbSJustin Bogner RecordIndex = 0; 708821d7471SJustin Bogner } 709b7aa2630SJustin Bogner return success(); 710b7aa2630SJustin Bogner } 711