1 //=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains support for reading profiling data for clang's 11 // instrumentation based PGO and coverage. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ProfileData/InstrProfReader.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include <cassert> 18 19 using namespace llvm; 20 21 static Expected<std::unique_ptr<MemoryBuffer>> 22 setupMemoryBuffer(const Twine &Path) { 23 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 24 MemoryBuffer::getFileOrSTDIN(Path); 25 if (std::error_code EC = BufferOrErr.getError()) 26 return errorCodeToError(EC); 27 return std::move(BufferOrErr.get()); 28 } 29 30 static Error initializeReader(InstrProfReader &Reader) { 31 return Reader.readHeader(); 32 } 33 34 Expected<std::unique_ptr<InstrProfReader>> 35 InstrProfReader::create(const Twine &Path) { 36 // Set up the buffer to read. 37 auto BufferOrError = setupMemoryBuffer(Path); 38 if (Error E = BufferOrError.takeError()) 39 return std::move(E); 40 return InstrProfReader::create(std::move(BufferOrError.get())); 41 } 42 43 Expected<std::unique_ptr<InstrProfReader>> 44 InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { 45 // Sanity check the buffer. 46 if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) 47 return make_error<InstrProfError>(instrprof_error::too_large); 48 49 std::unique_ptr<InstrProfReader> Result; 50 // Create the reader. 51 if (IndexedInstrProfReader::hasFormat(*Buffer)) 52 Result.reset(new IndexedInstrProfReader(std::move(Buffer))); 53 else if (RawInstrProfReader64::hasFormat(*Buffer)) 54 Result.reset(new RawInstrProfReader64(std::move(Buffer))); 55 else if (RawInstrProfReader32::hasFormat(*Buffer)) 56 Result.reset(new RawInstrProfReader32(std::move(Buffer))); 57 else if (TextInstrProfReader::hasFormat(*Buffer)) 58 Result.reset(new TextInstrProfReader(std::move(Buffer))); 59 else 60 return make_error<InstrProfError>(instrprof_error::unrecognized_format); 61 62 // Initialize the reader and return the result. 63 if (Error E = initializeReader(*Result)) 64 return std::move(E); 65 66 return std::move(Result); 67 } 68 69 Expected<std::unique_ptr<IndexedInstrProfReader>> 70 IndexedInstrProfReader::create(const Twine &Path) { 71 // Set up the buffer to read. 72 auto BufferOrError = setupMemoryBuffer(Path); 73 if (Error E = BufferOrError.takeError()) 74 return std::move(E); 75 return IndexedInstrProfReader::create(std::move(BufferOrError.get())); 76 } 77 78 79 Expected<std::unique_ptr<IndexedInstrProfReader>> 80 IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { 81 // Sanity check the buffer. 82 if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) 83 return make_error<InstrProfError>(instrprof_error::too_large); 84 85 // Create the reader. 86 if (!IndexedInstrProfReader::hasFormat(*Buffer)) 87 return make_error<InstrProfError>(instrprof_error::bad_magic); 88 auto Result = llvm::make_unique<IndexedInstrProfReader>(std::move(Buffer)); 89 90 // Initialize the reader and return the result. 91 if (Error E = initializeReader(*Result)) 92 return std::move(E); 93 94 return std::move(Result); 95 } 96 97 void InstrProfIterator::Increment() { 98 if (auto E = Reader->readNextRecord(Record)) { 99 // Handle errors in the reader. 100 InstrProfError::take(std::move(E)); 101 *this = InstrProfIterator(); 102 } 103 } 104 105 bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { 106 // Verify that this really looks like plain ASCII text by checking a 107 // 'reasonable' number of characters (up to profile magic size). 108 size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t)); 109 StringRef buffer = Buffer.getBufferStart(); 110 return count == 0 || 111 std::all_of(buffer.begin(), buffer.begin() + count, 112 [](char c) { return ::isprint(c) || ::isspace(c); }); 113 } 114 115 // Read the profile variant flag from the header: ":FE" means this is a FE 116 // generated profile. ":IR" means this is an IR level profile. Other strings 117 // with a leading ':' will be reported an error format. 118 Error TextInstrProfReader::readHeader() { 119 Symtab.reset(new InstrProfSymtab()); 120 bool IsIRInstr = false; 121 if (!Line->startswith(":")) { 122 IsIRLevelProfile = false; 123 return success(); 124 } 125 StringRef Str = (Line)->substr(1); 126 if (Str.equals_lower("ir")) 127 IsIRInstr = true; 128 else if (Str.equals_lower("fe")) 129 IsIRInstr = false; 130 else 131 return error(instrprof_error::bad_header); 132 133 ++Line; 134 IsIRLevelProfile = IsIRInstr; 135 return success(); 136 } 137 138 Error 139 TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { 140 141 #define CHECK_LINE_END(Line) \ 142 if (Line.is_at_end()) \ 143 return error(instrprof_error::truncated); 144 #define READ_NUM(Str, Dst) \ 145 if ((Str).getAsInteger(10, (Dst))) \ 146 return error(instrprof_error::malformed); 147 #define VP_READ_ADVANCE(Val) \ 148 CHECK_LINE_END(Line); \ 149 uint32_t Val; \ 150 READ_NUM((*Line), (Val)); \ 151 Line++; 152 153 if (Line.is_at_end()) 154 return success(); 155 156 uint32_t NumValueKinds; 157 if (Line->getAsInteger(10, NumValueKinds)) { 158 // No value profile data 159 return success(); 160 } 161 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1) 162 return error(instrprof_error::malformed); 163 Line++; 164 165 for (uint32_t VK = 0; VK < NumValueKinds; VK++) { 166 VP_READ_ADVANCE(ValueKind); 167 if (ValueKind > IPVK_Last) 168 return error(instrprof_error::malformed); 169 VP_READ_ADVANCE(NumValueSites); 170 if (!NumValueSites) 171 continue; 172 173 Record.reserveSites(VK, NumValueSites); 174 for (uint32_t S = 0; S < NumValueSites; S++) { 175 VP_READ_ADVANCE(NumValueData); 176 177 std::vector<InstrProfValueData> CurrentValues; 178 for (uint32_t V = 0; V < NumValueData; V++) { 179 CHECK_LINE_END(Line); 180 std::pair<StringRef, StringRef> VD = Line->rsplit(':'); 181 uint64_t TakenCount, Value; 182 if (VK == IPVK_IndirectCallTarget) { 183 Symtab->addFuncName(VD.first); 184 Value = IndexedInstrProf::ComputeHash(VD.first); 185 } else { 186 READ_NUM(VD.first, Value); 187 } 188 READ_NUM(VD.second, TakenCount); 189 CurrentValues.push_back({Value, TakenCount}); 190 Line++; 191 } 192 Record.addValueData(VK, S, CurrentValues.data(), NumValueData, nullptr); 193 } 194 } 195 return success(); 196 197 #undef CHECK_LINE_END 198 #undef READ_NUM 199 #undef VP_READ_ADVANCE 200 } 201 202 Error TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { 203 // Skip empty lines and comments. 204 while (!Line.is_at_end() && (Line->empty() || Line->startswith("#"))) 205 ++Line; 206 // If we hit EOF while looking for a name, we're done. 207 if (Line.is_at_end()) { 208 Symtab->finalizeSymtab(); 209 return error(instrprof_error::eof); 210 } 211 212 // Read the function name. 213 Record.Name = *Line++; 214 Symtab->addFuncName(Record.Name); 215 216 // Read the function hash. 217 if (Line.is_at_end()) 218 return error(instrprof_error::truncated); 219 if ((Line++)->getAsInteger(0, Record.Hash)) 220 return error(instrprof_error::malformed); 221 222 // Read the number of counters. 223 uint64_t NumCounters; 224 if (Line.is_at_end()) 225 return error(instrprof_error::truncated); 226 if ((Line++)->getAsInteger(10, NumCounters)) 227 return error(instrprof_error::malformed); 228 if (NumCounters == 0) 229 return error(instrprof_error::malformed); 230 231 // Read each counter and fill our internal storage with the values. 232 Record.Counts.clear(); 233 Record.Counts.reserve(NumCounters); 234 for (uint64_t I = 0; I < NumCounters; ++I) { 235 if (Line.is_at_end()) 236 return error(instrprof_error::truncated); 237 uint64_t Count; 238 if ((Line++)->getAsInteger(10, Count)) 239 return error(instrprof_error::malformed); 240 Record.Counts.push_back(Count); 241 } 242 243 // Check if value profile data exists and read it if so. 244 if (Error E = readValueProfileData(Record)) 245 return E; 246 247 // This is needed to avoid two pass parsing because llvm-profdata 248 // does dumping while reading. 249 Symtab->finalizeSymtab(); 250 return success(); 251 } 252 253 template <class IntPtrT> 254 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 255 if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 256 return false; 257 uint64_t Magic = 258 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 259 return RawInstrProf::getMagic<IntPtrT>() == Magic || 260 sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; 261 } 262 263 template <class IntPtrT> 264 Error RawInstrProfReader<IntPtrT>::readHeader() { 265 if (!hasFormat(*DataBuffer)) 266 return error(instrprof_error::bad_magic); 267 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)) 268 return error(instrprof_error::bad_header); 269 auto *Header = reinterpret_cast<const RawInstrProf::Header *>( 270 DataBuffer->getBufferStart()); 271 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); 272 return readHeader(*Header); 273 } 274 275 template <class IntPtrT> 276 Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { 277 const char *End = DataBuffer->getBufferEnd(); 278 // Skip zero padding between profiles. 279 while (CurrentPos != End && *CurrentPos == 0) 280 ++CurrentPos; 281 // If there's nothing left, we're done. 282 if (CurrentPos == End) 283 return make_error<InstrProfError>(instrprof_error::eof); 284 // If there isn't enough space for another header, this is probably just 285 // garbage at the end of the file. 286 if (CurrentPos + sizeof(RawInstrProf::Header) > End) 287 return make_error<InstrProfError>(instrprof_error::malformed); 288 // The writer ensures each profile is padded to start at an aligned address. 289 if (reinterpret_cast<size_t>(CurrentPos) % alignOf<uint64_t>()) 290 return make_error<InstrProfError>(instrprof_error::malformed); 291 // The magic should have the same byte order as in the previous header. 292 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); 293 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) 294 return make_error<InstrProfError>(instrprof_error::bad_magic); 295 296 // There's another profile to read, so we need to process the header. 297 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); 298 return readHeader(*Header); 299 } 300 301 template <class IntPtrT> 302 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 303 if (Error E = Symtab.create(StringRef(NamesStart, NamesSize))) 304 return error(std::move(E)); 305 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { 306 const IntPtrT FPtr = swap(I->FunctionPointer); 307 if (!FPtr) 308 continue; 309 Symtab.mapAddress(FPtr, I->NameRef); 310 } 311 Symtab.finalizeSymtab(); 312 return success(); 313 } 314 315 template <class IntPtrT> 316 Error RawInstrProfReader<IntPtrT>::readHeader( 317 const RawInstrProf::Header &Header) { 318 Version = swap(Header.Version); 319 if (GET_VERSION(Version) != RawInstrProf::Version) 320 return error(instrprof_error::unsupported_version); 321 322 CountersDelta = swap(Header.CountersDelta); 323 NamesDelta = swap(Header.NamesDelta); 324 auto DataSize = swap(Header.DataSize); 325 auto CountersSize = swap(Header.CountersSize); 326 NamesSize = swap(Header.NamesSize); 327 ValueKindLast = swap(Header.ValueKindLast); 328 329 auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); 330 auto PaddingSize = getNumPaddingBytes(NamesSize); 331 332 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); 333 ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; 334 ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; 335 ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; 336 337 auto *Start = reinterpret_cast<const char *>(&Header); 338 if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) 339 return error(instrprof_error::bad_header); 340 341 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( 342 Start + DataOffset); 343 DataEnd = Data + DataSize; 344 CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); 345 NamesStart = Start + NamesOffset; 346 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); 347 348 std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 349 if (Error E = createSymtab(*NewSymtab.get())) 350 return E; 351 352 Symtab = std::move(NewSymtab); 353 return success(); 354 } 355 356 template <class IntPtrT> 357 Error RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) { 358 Record.Name = getName(Data->NameRef); 359 return success(); 360 } 361 362 template <class IntPtrT> 363 Error RawInstrProfReader<IntPtrT>::readFuncHash(InstrProfRecord &Record) { 364 Record.Hash = swap(Data->FuncHash); 365 return success(); 366 } 367 368 template <class IntPtrT> 369 Error RawInstrProfReader<IntPtrT>::readRawCounts( 370 InstrProfRecord &Record) { 371 uint32_t NumCounters = swap(Data->NumCounters); 372 IntPtrT CounterPtr = Data->CounterPtr; 373 if (NumCounters == 0) 374 return error(instrprof_error::malformed); 375 376 auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); 377 auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); 378 379 // Check bounds. 380 if (RawCounts.data() < CountersStart || 381 RawCounts.data() + RawCounts.size() > NamesStartAsCounter) 382 return error(instrprof_error::malformed); 383 384 if (ShouldSwapBytes) { 385 Record.Counts.clear(); 386 Record.Counts.reserve(RawCounts.size()); 387 for (uint64_t Count : RawCounts) 388 Record.Counts.push_back(swap(Count)); 389 } else 390 Record.Counts = RawCounts; 391 392 return success(); 393 } 394 395 template <class IntPtrT> 396 Error RawInstrProfReader<IntPtrT>::readValueProfilingData( 397 InstrProfRecord &Record) { 398 399 Record.clearValueData(); 400 CurValueDataSize = 0; 401 // Need to match the logic in value profile dumper code in compiler-rt: 402 uint32_t NumValueKinds = 0; 403 for (uint32_t I = 0; I < IPVK_Last + 1; I++) 404 NumValueKinds += (Data->NumValueSites[I] != 0); 405 406 if (!NumValueKinds) 407 return success(); 408 409 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 410 ValueProfData::getValueProfData( 411 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), 412 getDataEndianness()); 413 414 if (Error E = VDataPtrOrErr.takeError()) 415 return E; 416 417 // Note that besides deserialization, this also performs the conversion for 418 // indirect call targets. The function pointers from the raw profile are 419 // remapped into function name hashes. 420 VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); 421 CurValueDataSize = VDataPtrOrErr.get()->getSize(); 422 return success(); 423 } 424 425 template <class IntPtrT> 426 Error RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) { 427 if (atEnd()) 428 // At this point, ValueDataStart field points to the next header. 429 if (Error E = readNextHeader(getNextHeaderPos())) 430 return E; 431 432 // Read name ad set it in Record. 433 if (Error E = readName(Record)) 434 return E; 435 436 // Read FuncHash and set it in Record. 437 if (Error E = readFuncHash(Record)) 438 return E; 439 440 // Read raw counts and set Record. 441 if (Error E = readRawCounts(Record)) 442 return E; 443 444 // Read value data and set Record. 445 if (Error E = readValueProfilingData(Record)) 446 return E; 447 448 // Iterate. 449 advanceData(); 450 return success(); 451 } 452 453 namespace llvm { 454 template class RawInstrProfReader<uint32_t>; 455 template class RawInstrProfReader<uint64_t>; 456 } 457 458 InstrProfLookupTrait::hash_value_type 459 InstrProfLookupTrait::ComputeHash(StringRef K) { 460 return IndexedInstrProf::ComputeHash(HashType, K); 461 } 462 463 typedef InstrProfLookupTrait::data_type data_type; 464 typedef InstrProfLookupTrait::offset_type offset_type; 465 466 bool InstrProfLookupTrait::readValueProfilingData( 467 const unsigned char *&D, const unsigned char *const End) { 468 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 469 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); 470 471 if (VDataPtrOrErr.takeError()) 472 return false; 473 474 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); 475 D += VDataPtrOrErr.get()->TotalSize; 476 477 return true; 478 } 479 480 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 481 offset_type N) { 482 // Check if the data is corrupt. If so, don't try to read it. 483 if (N % sizeof(uint64_t)) 484 return data_type(); 485 486 DataBuffer.clear(); 487 std::vector<uint64_t> CounterBuffer; 488 489 using namespace support; 490 const unsigned char *End = D + N; 491 while (D < End) { 492 // Read hash. 493 if (D + sizeof(uint64_t) >= End) 494 return data_type(); 495 uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); 496 497 // Initialize number of counters for GET_VERSION(FormatVersion) == 1. 498 uint64_t CountsSize = N / sizeof(uint64_t) - 1; 499 // If format version is different then read the number of counters. 500 if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { 501 if (D + sizeof(uint64_t) > End) 502 return data_type(); 503 CountsSize = endian::readNext<uint64_t, little, unaligned>(D); 504 } 505 // Read counter values. 506 if (D + CountsSize * sizeof(uint64_t) > End) 507 return data_type(); 508 509 CounterBuffer.clear(); 510 CounterBuffer.reserve(CountsSize); 511 for (uint64_t J = 0; J < CountsSize; ++J) 512 CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); 513 514 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); 515 516 // Read value profiling data. 517 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && 518 !readValueProfilingData(D, End)) { 519 DataBuffer.clear(); 520 return data_type(); 521 } 522 } 523 return DataBuffer; 524 } 525 526 template <typename HashTableImpl> 527 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 528 StringRef FuncName, ArrayRef<InstrProfRecord> &Data) { 529 auto Iter = HashTable->find(FuncName); 530 if (Iter == HashTable->end()) 531 return make_error<InstrProfError>(instrprof_error::unknown_function); 532 533 Data = (*Iter); 534 if (Data.empty()) 535 return make_error<InstrProfError>(instrprof_error::malformed); 536 537 return Error::success(); 538 } 539 540 template <typename HashTableImpl> 541 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 542 ArrayRef<InstrProfRecord> &Data) { 543 if (atEnd()) 544 return make_error<InstrProfError>(instrprof_error::eof); 545 546 Data = *RecordIterator; 547 548 if (Data.empty()) 549 return make_error<InstrProfError>(instrprof_error::malformed); 550 551 return Error::success(); 552 } 553 554 template <typename HashTableImpl> 555 InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( 556 const unsigned char *Buckets, const unsigned char *const Payload, 557 const unsigned char *const Base, IndexedInstrProf::HashT HashType, 558 uint64_t Version) { 559 FormatVersion = Version; 560 HashTable.reset(HashTableImpl::Create( 561 Buckets, Payload, Base, 562 typename HashTableImpl::InfoType(HashType, Version))); 563 RecordIterator = HashTable->data_begin(); 564 } 565 566 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 567 if (DataBuffer.getBufferSize() < 8) 568 return false; 569 using namespace support; 570 uint64_t Magic = 571 endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); 572 // Verify that it's magical. 573 return Magic == IndexedInstrProf::Magic; 574 } 575 576 const unsigned char * 577 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, 578 const unsigned char *Cur) { 579 using namespace IndexedInstrProf; 580 using namespace support; 581 if (Version >= IndexedInstrProf::Version4) { 582 const IndexedInstrProf::Summary *SummaryInLE = 583 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); 584 uint64_t NFields = 585 endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields); 586 uint64_t NEntries = 587 endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries); 588 uint32_t SummarySize = 589 IndexedInstrProf::Summary::getSize(NFields, NEntries); 590 std::unique_ptr<IndexedInstrProf::Summary> SummaryData = 591 IndexedInstrProf::allocSummary(SummarySize); 592 593 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); 594 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); 595 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) 596 Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]); 597 598 llvm::SummaryEntryVector DetailedSummary; 599 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) { 600 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I); 601 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, 602 Ent.NumBlocks); 603 } 604 // initialize InstrProfSummary using the SummaryData from disk. 605 this->Summary = llvm::make_unique<ProfileSummary>( 606 ProfileSummary::PSK_Instr, DetailedSummary, 607 SummaryData->get(Summary::TotalBlockCount), 608 SummaryData->get(Summary::MaxBlockCount), 609 SummaryData->get(Summary::MaxInternalBlockCount), 610 SummaryData->get(Summary::MaxFunctionCount), 611 SummaryData->get(Summary::TotalNumBlocks), 612 SummaryData->get(Summary::TotalNumFunctions)); 613 return Cur + SummarySize; 614 } else { 615 // For older version of profile data, we need to compute on the fly: 616 using namespace IndexedInstrProf; 617 InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); 618 // FIXME: This only computes an empty summary. Need to call addRecord for 619 // all InstrProfRecords to get the correct summary. 620 this->Summary = Builder.getSummary(); 621 return Cur; 622 } 623 } 624 625 Error IndexedInstrProfReader::readHeader() { 626 const unsigned char *Start = 627 (const unsigned char *)DataBuffer->getBufferStart(); 628 const unsigned char *Cur = Start; 629 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 630 return error(instrprof_error::truncated); 631 632 using namespace support; 633 634 auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); 635 Cur += sizeof(IndexedInstrProf::Header); 636 637 // Check the magic number. 638 uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic); 639 if (Magic != IndexedInstrProf::Magic) 640 return error(instrprof_error::bad_magic); 641 642 // Read the version. 643 uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version); 644 if (GET_VERSION(FormatVersion) > 645 IndexedInstrProf::ProfVersion::CurrentVersion) 646 return error(instrprof_error::unsupported_version); 647 648 Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur); 649 650 // Read the hash type and start offset. 651 IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( 652 endian::byte_swap<uint64_t, little>(Header->HashType)); 653 if (HashType > IndexedInstrProf::HashT::Last) 654 return error(instrprof_error::unsupported_hash_type); 655 656 uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset); 657 658 // The rest of the file is an on disk hash table. 659 InstrProfReaderIndexBase *IndexPtr = nullptr; 660 IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>( 661 Start + HashOffset, Cur, Start, HashType, FormatVersion); 662 Index.reset(IndexPtr); 663 return success(); 664 } 665 666 InstrProfSymtab &IndexedInstrProfReader::getSymtab() { 667 if (Symtab.get()) 668 return *Symtab.get(); 669 670 std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 671 Index->populateSymtab(*NewSymtab.get()); 672 673 Symtab = std::move(NewSymtab); 674 return *Symtab.get(); 675 } 676 677 Expected<InstrProfRecord> 678 IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName, 679 uint64_t FuncHash) { 680 ArrayRef<InstrProfRecord> Data; 681 Error Err = Index->getRecords(FuncName, Data); 682 if (Err) 683 return std::move(Err); 684 // Found it. Look for counters with the right hash. 685 for (unsigned I = 0, E = Data.size(); I < E; ++I) { 686 // Check for a match and fill the vector if there is one. 687 if (Data[I].Hash == FuncHash) { 688 return std::move(Data[I]); 689 } 690 } 691 return error(instrprof_error::hash_mismatch); 692 } 693 694 Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, 695 uint64_t FuncHash, 696 std::vector<uint64_t> &Counts) { 697 Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 698 if (Error E = Record.takeError()) 699 return error(std::move(E)); 700 701 Counts = Record.get().Counts; 702 return success(); 703 } 704 705 Error IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) { 706 static unsigned RecordIndex = 0; 707 708 ArrayRef<InstrProfRecord> Data; 709 710 Error E = Index->getRecords(Data); 711 if (E) 712 return error(std::move(E)); 713 714 Record = Data[RecordIndex++]; 715 if (RecordIndex >= Data.size()) { 716 Index->advanceToNextKey(); 717 RecordIndex = 0; 718 } 719 return success(); 720 } 721