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