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> 300a716cc5cSXinliang David Li void RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 301a82d6c0aSXinliang David Li Symtab.create(StringRef(NamesStart, NamesSize)); 302a716cc5cSXinliang David Li for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { 303a716cc5cSXinliang David Li const IntPtrT FPtr = swap(I->FunctionPointer); 304a716cc5cSXinliang David Li if (!FPtr) 305a716cc5cSXinliang David Li continue; 306a82d6c0aSXinliang David Li Symtab.mapAddress(FPtr, I->NameRef); 307a716cc5cSXinliang David Li } 308a716cc5cSXinliang David Li Symtab.finalizeSymtab(); 309a716cc5cSXinliang David Li } 310a716cc5cSXinliang David Li 311a716cc5cSXinliang David Li template <class IntPtrT> 312a716cc5cSXinliang David Li std::error_code 313a716cc5cSXinliang David Li RawInstrProfReader<IntPtrT>::readHeader(const RawInstrProf::Header &Header) { 31433c76c0cSRong Xu Version = swap(Header.Version); 31533c76c0cSRong Xu if (GET_VERSION(Version) != RawInstrProf::Version) 31624b4b653SDuncan P. N. Exon Smith return error(instrprof_error::unsupported_version); 31724b4b653SDuncan P. N. Exon Smith 31824b4b653SDuncan P. N. Exon Smith CountersDelta = swap(Header.CountersDelta); 31924b4b653SDuncan P. N. Exon Smith NamesDelta = swap(Header.NamesDelta); 32024b4b653SDuncan P. N. Exon Smith auto DataSize = swap(Header.DataSize); 32124b4b653SDuncan P. N. Exon Smith auto CountersSize = swap(Header.CountersSize); 322a82d6c0aSXinliang David Li NamesSize = swap(Header.NamesSize); 3236fac1741SBetul Buyukkurt auto ValueDataSize = swap(Header.ValueDataSize); 3246fac1741SBetul Buyukkurt ValueKindLast = swap(Header.ValueKindLast); 3256fac1741SBetul Buyukkurt 3266fac1741SBetul Buyukkurt auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); 3276fac1741SBetul Buyukkurt auto PaddingSize = getNumPaddingBytes(NamesSize); 32824b4b653SDuncan P. N. Exon Smith 329dab183edSXinliang David Li ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); 3306fac1741SBetul Buyukkurt ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; 33124b4b653SDuncan P. N. Exon Smith ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; 3326fac1741SBetul Buyukkurt ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; 3336fac1741SBetul Buyukkurt size_t ProfileSize = ValueDataOffset + ValueDataSize; 33424b4b653SDuncan P. N. Exon Smith 335a119f323SJustin Bogner auto *Start = reinterpret_cast<const char *>(&Header); 336a119f323SJustin Bogner if (Start + ProfileSize > DataBuffer->getBufferEnd()) 337531bb481SDuncan P. N. Exon Smith return error(instrprof_error::bad_header); 33824b4b653SDuncan P. N. Exon Smith 339dab183edSXinliang David Li Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( 340dab183edSXinliang David Li Start + DataOffset); 34124b4b653SDuncan P. N. Exon Smith DataEnd = Data + DataSize; 342d7d83477SDuncan P. N. Exon Smith CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); 343d7d83477SDuncan P. N. Exon Smith NamesStart = Start + NamesOffset; 3446fac1741SBetul Buyukkurt ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); 345a119f323SJustin Bogner ProfileEnd = Start + ProfileSize; 34624b4b653SDuncan P. N. Exon Smith 347a716cc5cSXinliang David Li std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 348a716cc5cSXinliang David Li createSymtab(*NewSymtab.get()); 349a716cc5cSXinliang David Li Symtab = std::move(NewSymtab); 35024b4b653SDuncan P. N. Exon Smith return success(); 35124b4b653SDuncan P. N. Exon Smith } 35224b4b653SDuncan P. N. Exon Smith 3534680361dSDuncan P. N. Exon Smith template <class IntPtrT> 354cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) { 355a82d6c0aSXinliang David Li Record.Name = getName(Data->NameRef); 356cf4a128cSXinliang David Li return success(); 357cf4a128cSXinliang David Li } 358cf4a128cSXinliang David Li 359cf4a128cSXinliang David Li template <class IntPtrT> 360cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readFuncHash( 361cf4a128cSXinliang David Li InstrProfRecord &Record) { 362cf4a128cSXinliang David Li Record.Hash = swap(Data->FuncHash); 363cf4a128cSXinliang David Li return success(); 364cf4a128cSXinliang David Li } 365cf4a128cSXinliang David Li 366cf4a128cSXinliang David Li template <class IntPtrT> 367cf4a128cSXinliang David Li std::error_code RawInstrProfReader<IntPtrT>::readRawCounts( 368cf4a128cSXinliang David Li InstrProfRecord &Record) { 369b59d7c73SJustin Bogner uint32_t NumCounters = swap(Data->NumCounters); 370cf4a128cSXinliang David Li IntPtrT CounterPtr = Data->CounterPtr; 371b59d7c73SJustin Bogner if (NumCounters == 0) 372b59d7c73SJustin Bogner return error(instrprof_error::malformed); 373cf4a128cSXinliang David Li 374cf4a128cSXinliang David Li auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); 375cf4a128cSXinliang David Li auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); 37624b4b653SDuncan P. N. Exon Smith 37724b4b653SDuncan P. N. Exon Smith // Check bounds. 378cf4a128cSXinliang David Li if (RawCounts.data() < CountersStart || 379d7d83477SDuncan P. N. Exon Smith RawCounts.data() + RawCounts.size() > NamesStartAsCounter) 38024b4b653SDuncan P. N. Exon Smith return error(instrprof_error::malformed); 38124b4b653SDuncan P. N. Exon Smith 38224b4b653SDuncan P. N. Exon Smith if (ShouldSwapBytes) { 3833a7d44cbSJustin Bogner Record.Counts.clear(); 3843a7d44cbSJustin Bogner Record.Counts.reserve(RawCounts.size()); 38524b4b653SDuncan P. N. Exon Smith for (uint64_t Count : RawCounts) 3863a7d44cbSJustin Bogner Record.Counts.push_back(swap(Count)); 38724b4b653SDuncan P. N. Exon Smith } else 38824b4b653SDuncan P. N. Exon Smith Record.Counts = RawCounts; 38924b4b653SDuncan P. N. Exon Smith 390cf4a128cSXinliang David Li return success(); 391cf4a128cSXinliang David Li } 392cf4a128cSXinliang David Li 393cf4a128cSXinliang David Li template <class IntPtrT> 39401cb9bd7SXinliang David Li std::error_code 39501cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readValueProfilingData(InstrProfRecord &Record) { 3966fac1741SBetul Buyukkurt 3976fac1741SBetul Buyukkurt Record.clearValueData(); 398d922c26cSXinliang David Li CurValueDataSize = 0; 399d922c26cSXinliang David Li // Need to match the logic in value profile dumper code in compiler-rt: 400d922c26cSXinliang David Li uint32_t NumValueKinds = 0; 401d922c26cSXinliang David Li for (uint32_t I = 0; I < IPVK_Last + 1; I++) 402d922c26cSXinliang David Li NumValueKinds += (Data->NumValueSites[I] != 0); 403d922c26cSXinliang David Li 404d922c26cSXinliang David Li if (!NumValueKinds) 4056fac1741SBetul Buyukkurt return success(); 4066fac1741SBetul Buyukkurt 40701cb9bd7SXinliang David Li ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 408d922c26cSXinliang David Li ValueProfData::getValueProfData(ValueDataStart, 40901cb9bd7SXinliang David Li (const unsigned char *)ProfileEnd, 41001cb9bd7SXinliang David Li getDataEndianness()); 4116fac1741SBetul Buyukkurt 41201cb9bd7SXinliang David Li if (VDataPtrOrErr.getError()) 41301cb9bd7SXinliang David Li return VDataPtrOrErr.getError(); 4146fac1741SBetul Buyukkurt 415a716cc5cSXinliang David Li VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); 416d922c26cSXinliang David Li CurValueDataSize = VDataPtrOrErr.get()->getSize(); 4176fac1741SBetul Buyukkurt return success(); 4186fac1741SBetul Buyukkurt } 4196fac1741SBetul Buyukkurt 4206fac1741SBetul Buyukkurt template <class IntPtrT> 42101cb9bd7SXinliang David Li std::error_code 42201cb9bd7SXinliang David Li RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) { 423cf4a128cSXinliang David Li if (atEnd()) 4244c3ab815SXinliang David Li if (std::error_code EC = readNextHeader(ProfileEnd)) 4254c3ab815SXinliang David Li return EC; 426cf4a128cSXinliang David Li 427cf4a128cSXinliang David Li // Read name ad set it in Record. 4284c3ab815SXinliang David Li if (std::error_code EC = readName(Record)) 4294c3ab815SXinliang David Li return EC; 430cf4a128cSXinliang David Li 431cf4a128cSXinliang David Li // Read FuncHash and set it in Record. 4324c3ab815SXinliang David Li if (std::error_code EC = readFuncHash(Record)) 4334c3ab815SXinliang David Li return EC; 434cf4a128cSXinliang David Li 435cf4a128cSXinliang David Li // Read raw counts and set Record. 4364c3ab815SXinliang David Li if (std::error_code EC = readRawCounts(Record)) 4374c3ab815SXinliang David Li return EC; 438cf4a128cSXinliang David Li 4396fac1741SBetul Buyukkurt // Read value data and set Record. 4402d4803e8SXinliang David Li if (std::error_code EC = readValueProfilingData(Record)) 4412d4803e8SXinliang David Li return EC; 4426fac1741SBetul Buyukkurt 44324b4b653SDuncan P. N. Exon Smith // Iterate. 444cf4a128cSXinliang David Li advanceData(); 44524b4b653SDuncan P. N. Exon Smith return success(); 44624b4b653SDuncan P. N. Exon Smith } 4474680361dSDuncan P. N. Exon Smith 4484680361dSDuncan P. N. Exon Smith namespace llvm { 4494680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint32_t>; 4504680361dSDuncan P. N. Exon Smith template class RawInstrProfReader<uint64_t>; 4514680361dSDuncan P. N. Exon Smith } 452b7aa2630SJustin Bogner 453b5d368e8SJustin Bogner InstrProfLookupTrait::hash_value_type 454b5d368e8SJustin Bogner InstrProfLookupTrait::ComputeHash(StringRef K) { 455b5d368e8SJustin Bogner return IndexedInstrProf::ComputeHash(HashType, K); 456b5d368e8SJustin Bogner } 457b5d368e8SJustin Bogner 4583a7d44cbSJustin Bogner typedef InstrProfLookupTrait::data_type data_type; 4593a7d44cbSJustin Bogner typedef InstrProfLookupTrait::offset_type offset_type; 4603a7d44cbSJustin Bogner 461be969c29SXinliang David Li bool InstrProfLookupTrait::readValueProfilingData( 4629e9a057aSJustin Bogner const unsigned char *&D, const unsigned char *const End) { 46399556877SXinliang David Li ErrorOr<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 46499556877SXinliang David Li ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); 4659e9a057aSJustin Bogner 466ee415895SXinliang David Li if (VDataPtrOrErr.getError()) 4679e9a057aSJustin Bogner return false; 4682004f003SXinliang David Li 469a716cc5cSXinliang David Li VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); 470ee415895SXinliang David Li D += VDataPtrOrErr.get()->TotalSize; 4719e9a057aSJustin Bogner 4729e9a057aSJustin Bogner return true; 4739e9a057aSJustin Bogner } 4749e9a057aSJustin Bogner 4753a7d44cbSJustin Bogner data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 4763a7d44cbSJustin Bogner offset_type N) { 4773a7d44cbSJustin Bogner // Check if the data is corrupt. If so, don't try to read it. 4783a7d44cbSJustin Bogner if (N % sizeof(uint64_t)) 4793a7d44cbSJustin Bogner return data_type(); 4803a7d44cbSJustin Bogner 4813a7d44cbSJustin Bogner DataBuffer.clear(); 4823a7d44cbSJustin Bogner std::vector<uint64_t> CounterBuffer; 4839e9a057aSJustin Bogner 4843a7d44cbSJustin Bogner using namespace support; 4859e9a057aSJustin Bogner const unsigned char *End = D + N; 4869e9a057aSJustin Bogner while (D < End) { 487c758387eSXinliang David Li // Read hash. 4889e9a057aSJustin Bogner if (D + sizeof(uint64_t) >= End) 4899e9a057aSJustin Bogner return data_type(); 4903a7d44cbSJustin Bogner uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); 4913a7d44cbSJustin Bogner 49233c76c0cSRong Xu // Initialize number of counters for GET_VERSION(FormatVersion) == 1. 4939e9a057aSJustin Bogner uint64_t CountsSize = N / sizeof(uint64_t) - 1; 494c758387eSXinliang David Li // If format version is different then read the number of counters. 49533c76c0cSRong Xu if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { 4969e9a057aSJustin Bogner if (D + sizeof(uint64_t) > End) 4973a7d44cbSJustin Bogner return data_type(); 4989e9a057aSJustin Bogner CountsSize = endian::readNext<uint64_t, little, unaligned>(D); 4999e9a057aSJustin Bogner } 500c758387eSXinliang David Li // Read counter values. 5019e9a057aSJustin Bogner if (D + CountsSize * sizeof(uint64_t) > End) 5023a7d44cbSJustin Bogner return data_type(); 5033a7d44cbSJustin Bogner 5043a7d44cbSJustin Bogner CounterBuffer.clear(); 5059e9a057aSJustin Bogner CounterBuffer.reserve(CountsSize); 5069e9a057aSJustin Bogner for (uint64_t J = 0; J < CountsSize; ++J) 5073a7d44cbSJustin Bogner CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); 5083a7d44cbSJustin Bogner 5092004f003SXinliang David Li DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); 5109e9a057aSJustin Bogner 511c758387eSXinliang David Li // Read value profiling data. 51233c76c0cSRong Xu if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && 513a6b2c4f7SXinliang David Li !readValueProfilingData(D, End)) { 5149e9a057aSJustin Bogner DataBuffer.clear(); 5159e9a057aSJustin Bogner return data_type(); 5169e9a057aSJustin Bogner } 5173a7d44cbSJustin Bogner } 5183a7d44cbSJustin Bogner return DataBuffer; 5193a7d44cbSJustin Bogner } 5203a7d44cbSJustin Bogner 521a28306dbSXinliang David Li template <typename HashTableImpl> 522a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords( 523a28306dbSXinliang David Li StringRef FuncName, ArrayRef<InstrProfRecord> &Data) { 524a28306dbSXinliang David Li auto Iter = HashTable->find(FuncName); 525a28306dbSXinliang David Li if (Iter == HashTable->end()) 5264c3ab815SXinliang David Li return instrprof_error::unknown_function; 527140f4c4fSXinliang David Li 528140f4c4fSXinliang David Li Data = (*Iter); 5294c3ab815SXinliang David Li if (Data.empty()) 5304c3ab815SXinliang David Li return instrprof_error::malformed; 531140f4c4fSXinliang David Li 532140f4c4fSXinliang David Li return instrprof_error::success; 533140f4c4fSXinliang David Li } 534140f4c4fSXinliang David Li 535a28306dbSXinliang David Li template <typename HashTableImpl> 536a28306dbSXinliang David Li std::error_code InstrProfReaderIndex<HashTableImpl>::getRecords( 537140f4c4fSXinliang David Li ArrayRef<InstrProfRecord> &Data) { 538a28306dbSXinliang David Li if (atEnd()) 539a28306dbSXinliang David Li return instrprof_error::eof; 540140f4c4fSXinliang David Li 541140f4c4fSXinliang David Li Data = *RecordIterator; 542140f4c4fSXinliang David Li 5432d4803e8SXinliang David Li if (Data.empty()) 5442d4803e8SXinliang David Li return instrprof_error::malformed; 545140f4c4fSXinliang David Li 546140f4c4fSXinliang David Li return instrprof_error::success; 547140f4c4fSXinliang David Li } 548140f4c4fSXinliang David Li 549a28306dbSXinliang David Li template <typename HashTableImpl> 550a28306dbSXinliang David Li InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( 551a28306dbSXinliang David Li const unsigned char *Buckets, const unsigned char *const Payload, 552a28306dbSXinliang David Li const unsigned char *const Base, IndexedInstrProf::HashT HashType, 553140f4c4fSXinliang David Li uint64_t Version) { 554140f4c4fSXinliang David Li FormatVersion = Version; 555a28306dbSXinliang David Li HashTable.reset(HashTableImpl::Create( 556a28306dbSXinliang David Li Buckets, Payload, Base, 557a28306dbSXinliang David Li typename HashTableImpl::InfoType(HashType, Version))); 558a28306dbSXinliang David Li RecordIterator = HashTable->data_begin(); 559140f4c4fSXinliang David Li } 560140f4c4fSXinliang David Li 561b7aa2630SJustin Bogner bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 5624c3ab815SXinliang David Li if (DataBuffer.getBufferSize() < 8) 5634c3ab815SXinliang David Li return false; 564b7aa2630SJustin Bogner using namespace support; 565b7aa2630SJustin Bogner uint64_t Magic = 566b7aa2630SJustin Bogner endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); 567c758387eSXinliang David Li // Verify that it's magical. 568b7aa2630SJustin Bogner return Magic == IndexedInstrProf::Magic; 569b7aa2630SJustin Bogner } 570b7aa2630SJustin Bogner 5716c93ee8dSXinliang David Li const unsigned char * 5726c93ee8dSXinliang David Li IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, 5736c93ee8dSXinliang David Li const unsigned char *Cur) { 5746c93ee8dSXinliang David Li using namespace support; 5756c93ee8dSXinliang David Li if (Version >= IndexedInstrProf::Version4) { 5766c93ee8dSXinliang David Li const IndexedInstrProf::Summary *SummaryInLE = 5776c93ee8dSXinliang David Li reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); 5786c93ee8dSXinliang David Li uint64_t NFields = 5796c93ee8dSXinliang David Li endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields); 5806c93ee8dSXinliang David Li uint64_t NEntries = 5816c93ee8dSXinliang David Li endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries); 5826c93ee8dSXinliang David Li uint32_t SummarySize = 5836c93ee8dSXinliang David Li IndexedInstrProf::Summary::getSize(NFields, NEntries); 5846c93ee8dSXinliang David Li std::unique_ptr<IndexedInstrProf::Summary> SummaryData = 5856c93ee8dSXinliang David Li IndexedInstrProf::allocSummary(SummarySize); 5866c93ee8dSXinliang David Li 5876c93ee8dSXinliang David Li const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); 5886c93ee8dSXinliang David Li uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); 5896c93ee8dSXinliang David Li for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) 5906c93ee8dSXinliang David Li Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]); 5916c93ee8dSXinliang David Li 5924309570dSEaswaran Raman // initialize InstrProfSummary using the SummaryData from disk. 5934309570dSEaswaran Raman this->Summary = llvm::make_unique<InstrProfSummary>(*(SummaryData.get())); 5946c93ee8dSXinliang David Li return Cur + SummarySize; 5956c93ee8dSXinliang David Li } else { 5966c93ee8dSXinliang David Li // For older version of profile data, we need to compute on the fly: 5976c93ee8dSXinliang David Li using namespace IndexedInstrProf; 598*40ee23dbSEaswaran Raman this->Summary = 599*40ee23dbSEaswaran Raman llvm::make_unique<InstrProfSummary>(ProfileSummary::DefaultCutoffs); 6006c93ee8dSXinliang David Li this->Summary->computeDetailedSummary(); 6016c93ee8dSXinliang David Li return Cur; 6026c93ee8dSXinliang David Li } 6036c93ee8dSXinliang David Li } 6046c93ee8dSXinliang David Li 605db4ed0bdSRafael Espindola std::error_code IndexedInstrProfReader::readHeader() { 606a7c9ed57SAaron Ballman const unsigned char *Start = 607a7c9ed57SAaron Ballman (const unsigned char *)DataBuffer->getBufferStart(); 608b7aa2630SJustin Bogner const unsigned char *Cur = Start; 609a7c9ed57SAaron Ballman if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 610b7aa2630SJustin Bogner return error(instrprof_error::truncated); 611b7aa2630SJustin Bogner 612b7aa2630SJustin Bogner using namespace support; 613b7aa2630SJustin Bogner 614dab183edSXinliang David Li auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); 615dab183edSXinliang David Li Cur += sizeof(IndexedInstrProf::Header); 616dab183edSXinliang David Li 617b7aa2630SJustin Bogner // Check the magic number. 618dab183edSXinliang David Li uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic); 619b7aa2630SJustin Bogner if (Magic != IndexedInstrProf::Magic) 620b7aa2630SJustin Bogner return error(instrprof_error::bad_magic); 621b7aa2630SJustin Bogner 622b7aa2630SJustin Bogner // Read the version. 623140f4c4fSXinliang David Li uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version); 62433c76c0cSRong Xu if (GET_VERSION(FormatVersion) > 62533c76c0cSRong Xu IndexedInstrProf::ProfVersion::CurrentVersion) 626b7aa2630SJustin Bogner return error(instrprof_error::unsupported_version); 627b7aa2630SJustin Bogner 6286c93ee8dSXinliang David Li Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur); 629b7aa2630SJustin Bogner 630b7aa2630SJustin Bogner // Read the hash type and start offset. 631b7aa2630SJustin Bogner IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( 632dab183edSXinliang David Li endian::byte_swap<uint64_t, little>(Header->HashType)); 633b7aa2630SJustin Bogner if (HashType > IndexedInstrProf::HashT::Last) 634b7aa2630SJustin Bogner return error(instrprof_error::unsupported_hash_type); 635dab183edSXinliang David Li 636dab183edSXinliang David Li uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset); 637b7aa2630SJustin Bogner 638b7aa2630SJustin Bogner // The rest of the file is an on disk hash table. 639a28306dbSXinliang David Li InstrProfReaderIndexBase *IndexPtr = nullptr; 640a28306dbSXinliang David Li IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>( 641a28306dbSXinliang David Li Start + HashOffset, Cur, Start, HashType, FormatVersion); 642a28306dbSXinliang David Li Index.reset(IndexPtr); 643b7aa2630SJustin Bogner return success(); 644b7aa2630SJustin Bogner } 645b7aa2630SJustin Bogner 646a716cc5cSXinliang David Li InstrProfSymtab &IndexedInstrProfReader::getSymtab() { 647a716cc5cSXinliang David Li if (Symtab.get()) 648a716cc5cSXinliang David Li return *Symtab.get(); 649a716cc5cSXinliang David Li 650a716cc5cSXinliang David Li std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 651a716cc5cSXinliang David Li Index->populateSymtab(*NewSymtab.get()); 652a716cc5cSXinliang David Li 653a716cc5cSXinliang David Li Symtab = std::move(NewSymtab); 654a716cc5cSXinliang David Li return *Symtab.get(); 655a716cc5cSXinliang David Li } 656a716cc5cSXinliang David Li 6576aa216c2SXinliang David Li ErrorOr<InstrProfRecord> 6586aa216c2SXinliang David Li IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName, 6596aa216c2SXinliang David Li uint64_t FuncHash) { 660140f4c4fSXinliang David Li ArrayRef<InstrProfRecord> Data; 661a28306dbSXinliang David Li std::error_code EC = Index->getRecords(FuncName, Data); 6624c3ab815SXinliang David Li if (EC != instrprof_error::success) 6634c3ab815SXinliang David Li return EC; 664821d7471SJustin Bogner // Found it. Look for counters with the right hash. 6653a7d44cbSJustin Bogner for (unsigned I = 0, E = Data.size(); I < E; ++I) { 666821d7471SJustin Bogner // Check for a match and fill the vector if there is one. 6673a7d44cbSJustin Bogner if (Data[I].Hash == FuncHash) { 6682004f003SXinliang David Li return std::move(Data[I]); 669b7aa2630SJustin Bogner } 670821d7471SJustin Bogner } 671821d7471SJustin Bogner return error(instrprof_error::hash_mismatch); 672821d7471SJustin Bogner } 673b7aa2630SJustin Bogner 6746aa216c2SXinliang David Li std::error_code 6756aa216c2SXinliang David Li IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, uint64_t FuncHash, 6766aa216c2SXinliang David Li std::vector<uint64_t> &Counts) { 6772004f003SXinliang David Li ErrorOr<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 6786aa216c2SXinliang David Li if (std::error_code EC = Record.getError()) 6796aa216c2SXinliang David Li return EC; 6802004f003SXinliang David Li 6812004f003SXinliang David Li Counts = Record.get().Counts; 6822004f003SXinliang David Li return success(); 6832004f003SXinliang David Li } 6842004f003SXinliang David Li 685140f4c4fSXinliang David Li std::error_code IndexedInstrProfReader::readNextRecord( 686140f4c4fSXinliang David Li InstrProfRecord &Record) { 6873a7d44cbSJustin Bogner static unsigned RecordIndex = 0; 688140f4c4fSXinliang David Li 689140f4c4fSXinliang David Li ArrayRef<InstrProfRecord> Data; 690140f4c4fSXinliang David Li 691a28306dbSXinliang David Li std::error_code EC = Index->getRecords(Data); 6924c3ab815SXinliang David Li if (EC != instrprof_error::success) 6934c3ab815SXinliang David Li return error(EC); 694140f4c4fSXinliang David Li 6953a7d44cbSJustin Bogner Record = Data[RecordIndex++]; 6963a7d44cbSJustin Bogner if (RecordIndex >= Data.size()) { 697a28306dbSXinliang David Li Index->advanceToNextKey(); 6983a7d44cbSJustin Bogner RecordIndex = 0; 699821d7471SJustin Bogner } 700b7aa2630SJustin Bogner return success(); 701b7aa2630SJustin Bogner } 702