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/ArrayRef.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/IR/ProfileSummary.h" 20 #include "llvm/ProfileData/InstrProf.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 if (Error E = Symtab->addFuncName(VD.first)) 204 return E; 205 Value = IndexedInstrProf::ComputeHash(VD.first); 206 } else { 207 READ_NUM(VD.first, Value); 208 } 209 READ_NUM(VD.second, TakenCount); 210 CurrentValues.push_back({Value, TakenCount}); 211 Line++; 212 } 213 Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData, 214 nullptr); 215 } 216 } 217 return success(); 218 219 #undef CHECK_LINE_END 220 #undef READ_NUM 221 #undef VP_READ_ADVANCE 222 } 223 224 Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { 225 // Skip empty lines and comments. 226 while (!Line.is_at_end() && (Line->empty() || Line->startswith("#"))) 227 ++Line; 228 // If we hit EOF while looking for a name, we're done. 229 if (Line.is_at_end()) { 230 Symtab->finalizeSymtab(); 231 return error(instrprof_error::eof); 232 } 233 234 // Read the function name. 235 Record.Name = *Line++; 236 if (Error E = Symtab->addFuncName(Record.Name)) 237 return E; 238 239 // Read the function hash. 240 if (Line.is_at_end()) 241 return error(instrprof_error::truncated); 242 if ((Line++)->getAsInteger(0, Record.Hash)) 243 return error(instrprof_error::malformed); 244 245 // Read the number of counters. 246 uint64_t NumCounters; 247 if (Line.is_at_end()) 248 return error(instrprof_error::truncated); 249 if ((Line++)->getAsInteger(10, NumCounters)) 250 return error(instrprof_error::malformed); 251 if (NumCounters == 0) 252 return error(instrprof_error::malformed); 253 254 // Read each counter and fill our internal storage with the values. 255 Record.Clear(); 256 Record.Counts.reserve(NumCounters); 257 for (uint64_t I = 0; I < NumCounters; ++I) { 258 if (Line.is_at_end()) 259 return error(instrprof_error::truncated); 260 uint64_t Count; 261 if ((Line++)->getAsInteger(10, Count)) 262 return error(instrprof_error::malformed); 263 Record.Counts.push_back(Count); 264 } 265 266 // Check if value profile data exists and read it if so. 267 if (Error E = readValueProfileData(Record)) 268 return E; 269 270 // This is needed to avoid two pass parsing because llvm-profdata 271 // does dumping while reading. 272 Symtab->finalizeSymtab(); 273 return success(); 274 } 275 276 template <class IntPtrT> 277 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 278 if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 279 return false; 280 uint64_t Magic = 281 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 282 return RawInstrProf::getMagic<IntPtrT>() == Magic || 283 sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; 284 } 285 286 template <class IntPtrT> 287 Error RawInstrProfReader<IntPtrT>::readHeader() { 288 if (!hasFormat(*DataBuffer)) 289 return error(instrprof_error::bad_magic); 290 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)) 291 return error(instrprof_error::bad_header); 292 auto *Header = reinterpret_cast<const RawInstrProf::Header *>( 293 DataBuffer->getBufferStart()); 294 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); 295 return readHeader(*Header); 296 } 297 298 template <class IntPtrT> 299 Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { 300 const char *End = DataBuffer->getBufferEnd(); 301 // Skip zero padding between profiles. 302 while (CurrentPos != End && *CurrentPos == 0) 303 ++CurrentPos; 304 // If there's nothing left, we're done. 305 if (CurrentPos == End) 306 return make_error<InstrProfError>(instrprof_error::eof); 307 // If there isn't enough space for another header, this is probably just 308 // garbage at the end of the file. 309 if (CurrentPos + sizeof(RawInstrProf::Header) > End) 310 return make_error<InstrProfError>(instrprof_error::malformed); 311 // The writer ensures each profile is padded to start at an aligned address. 312 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t)) 313 return make_error<InstrProfError>(instrprof_error::malformed); 314 // The magic should have the same byte order as in the previous header. 315 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); 316 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) 317 return make_error<InstrProfError>(instrprof_error::bad_magic); 318 319 // There's another profile to read, so we need to process the header. 320 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); 321 return readHeader(*Header); 322 } 323 324 template <class IntPtrT> 325 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 326 if (Error E = Symtab.create(StringRef(NamesStart, NamesSize))) 327 return error(std::move(E)); 328 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { 329 const IntPtrT FPtr = swap(I->FunctionPointer); 330 if (!FPtr) 331 continue; 332 Symtab.mapAddress(FPtr, I->NameRef); 333 } 334 Symtab.finalizeSymtab(); 335 return success(); 336 } 337 338 template <class IntPtrT> 339 Error RawInstrProfReader<IntPtrT>::readHeader( 340 const RawInstrProf::Header &Header) { 341 Version = swap(Header.Version); 342 if (GET_VERSION(Version) != RawInstrProf::Version) 343 return error(instrprof_error::unsupported_version); 344 345 CountersDelta = swap(Header.CountersDelta); 346 NamesDelta = swap(Header.NamesDelta); 347 auto DataSize = swap(Header.DataSize); 348 auto CountersSize = swap(Header.CountersSize); 349 NamesSize = swap(Header.NamesSize); 350 ValueKindLast = swap(Header.ValueKindLast); 351 352 auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); 353 auto PaddingSize = getNumPaddingBytes(NamesSize); 354 355 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); 356 ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; 357 ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; 358 ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; 359 360 auto *Start = reinterpret_cast<const char *>(&Header); 361 if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) 362 return error(instrprof_error::bad_header); 363 364 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( 365 Start + DataOffset); 366 DataEnd = Data + DataSize; 367 CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); 368 NamesStart = Start + NamesOffset; 369 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); 370 371 std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 372 if (Error E = createSymtab(*NewSymtab.get())) 373 return E; 374 375 Symtab = std::move(NewSymtab); 376 return success(); 377 } 378 379 template <class IntPtrT> 380 Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) { 381 Record.Name = getName(Data->NameRef); 382 return success(); 383 } 384 385 template <class IntPtrT> 386 Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) { 387 Record.Hash = swap(Data->FuncHash); 388 return success(); 389 } 390 391 template <class IntPtrT> 392 Error RawInstrProfReader<IntPtrT>::readRawCounts( 393 InstrProfRecord &Record) { 394 uint32_t NumCounters = swap(Data->NumCounters); 395 IntPtrT CounterPtr = Data->CounterPtr; 396 if (NumCounters == 0) 397 return error(instrprof_error::malformed); 398 399 auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); 400 auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); 401 402 // Check bounds. 403 if (RawCounts.data() < CountersStart || 404 RawCounts.data() + RawCounts.size() > NamesStartAsCounter) 405 return error(instrprof_error::malformed); 406 407 if (ShouldSwapBytes) { 408 Record.Counts.clear(); 409 Record.Counts.reserve(RawCounts.size()); 410 for (uint64_t Count : RawCounts) 411 Record.Counts.push_back(swap(Count)); 412 } else 413 Record.Counts = RawCounts; 414 415 return success(); 416 } 417 418 template <class IntPtrT> 419 Error RawInstrProfReader<IntPtrT>::readValueProfilingData( 420 InstrProfRecord &Record) { 421 Record.clearValueData(); 422 CurValueDataSize = 0; 423 // Need to match the logic in value profile dumper code in compiler-rt: 424 uint32_t NumValueKinds = 0; 425 for (uint32_t I = 0; I < IPVK_Last + 1; I++) 426 NumValueKinds += (Data->NumValueSites[I] != 0); 427 428 if (!NumValueKinds) 429 return success(); 430 431 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 432 ValueProfData::getValueProfData( 433 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), 434 getDataEndianness()); 435 436 if (Error E = VDataPtrOrErr.takeError()) 437 return E; 438 439 // Note that besides deserialization, this also performs the conversion for 440 // indirect call targets. The function pointers from the raw profile are 441 // remapped into function name hashes. 442 VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); 443 CurValueDataSize = VDataPtrOrErr.get()->getSize(); 444 return success(); 445 } 446 447 template <class IntPtrT> 448 Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) { 449 if (atEnd()) 450 // At this point, ValueDataStart field points to the next header. 451 if (Error E = readNextHeader(getNextHeaderPos())) 452 return E; 453 454 // Read name ad set it in Record. 455 if (Error E = readName(Record)) 456 return E; 457 458 // Read FuncHash and set it in Record. 459 if (Error E = readFuncHash(Record)) 460 return E; 461 462 // Read raw counts and set Record. 463 if (Error E = readRawCounts(Record)) 464 return E; 465 466 // Read value data and set Record. 467 if (Error E = readValueProfilingData(Record)) 468 return E; 469 470 // Iterate. 471 advanceData(); 472 return success(); 473 } 474 475 namespace llvm { 476 477 template class RawInstrProfReader<uint32_t>; 478 template class RawInstrProfReader<uint64_t>; 479 480 } // end namespace llvm 481 482 InstrProfLookupTrait::hash_value_type 483 InstrProfLookupTrait::ComputeHash(StringRef K) { 484 return IndexedInstrProf::ComputeHash(HashType, K); 485 } 486 487 using data_type = InstrProfLookupTrait::data_type; 488 using offset_type = InstrProfLookupTrait::offset_type; 489 490 bool InstrProfLookupTrait::readValueProfilingData( 491 const unsigned char *&D, const unsigned char *const End) { 492 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 493 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); 494 495 if (VDataPtrOrErr.takeError()) 496 return false; 497 498 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); 499 D += VDataPtrOrErr.get()->TotalSize; 500 501 return true; 502 } 503 504 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 505 offset_type N) { 506 using namespace support; 507 508 // Check if the data is corrupt. If so, don't try to read it. 509 if (N % sizeof(uint64_t)) 510 return data_type(); 511 512 DataBuffer.clear(); 513 std::vector<uint64_t> CounterBuffer; 514 515 const unsigned char *End = D + N; 516 while (D < End) { 517 // Read hash. 518 if (D + sizeof(uint64_t) >= End) 519 return data_type(); 520 uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); 521 522 // Initialize number of counters for GET_VERSION(FormatVersion) == 1. 523 uint64_t CountsSize = N / sizeof(uint64_t) - 1; 524 // If format version is different then read the number of counters. 525 if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { 526 if (D + sizeof(uint64_t) > End) 527 return data_type(); 528 CountsSize = endian::readNext<uint64_t, little, unaligned>(D); 529 } 530 // Read counter values. 531 if (D + CountsSize * sizeof(uint64_t) > End) 532 return data_type(); 533 534 CounterBuffer.clear(); 535 CounterBuffer.reserve(CountsSize); 536 for (uint64_t J = 0; J < CountsSize; ++J) 537 CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); 538 539 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); 540 541 // Read value profiling data. 542 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && 543 !readValueProfilingData(D, End)) { 544 DataBuffer.clear(); 545 return data_type(); 546 } 547 } 548 return DataBuffer; 549 } 550 551 template <typename HashTableImpl> 552 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 553 StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) { 554 auto Iter = HashTable->find(FuncName); 555 if (Iter == HashTable->end()) 556 return make_error<InstrProfError>(instrprof_error::unknown_function); 557 558 Data = (*Iter); 559 if (Data.empty()) 560 return make_error<InstrProfError>(instrprof_error::malformed); 561 562 return Error::success(); 563 } 564 565 template <typename HashTableImpl> 566 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 567 ArrayRef<NamedInstrProfRecord> &Data) { 568 if (atEnd()) 569 return make_error<InstrProfError>(instrprof_error::eof); 570 571 Data = *RecordIterator; 572 573 if (Data.empty()) 574 return make_error<InstrProfError>(instrprof_error::malformed); 575 576 return Error::success(); 577 } 578 579 template <typename HashTableImpl> 580 InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( 581 const unsigned char *Buckets, const unsigned char *const Payload, 582 const unsigned char *const Base, IndexedInstrProf::HashT HashType, 583 uint64_t Version) { 584 FormatVersion = Version; 585 HashTable.reset(HashTableImpl::Create( 586 Buckets, Payload, Base, 587 typename HashTableImpl::InfoType(HashType, Version))); 588 RecordIterator = HashTable->data_begin(); 589 } 590 591 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 592 using namespace support; 593 594 if (DataBuffer.getBufferSize() < 8) 595 return false; 596 uint64_t Magic = 597 endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); 598 // Verify that it's magical. 599 return Magic == IndexedInstrProf::Magic; 600 } 601 602 const unsigned char * 603 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, 604 const unsigned char *Cur) { 605 using namespace IndexedInstrProf; 606 using namespace support; 607 608 if (Version >= IndexedInstrProf::Version4) { 609 const IndexedInstrProf::Summary *SummaryInLE = 610 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); 611 uint64_t NFields = 612 endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields); 613 uint64_t NEntries = 614 endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries); 615 uint32_t SummarySize = 616 IndexedInstrProf::Summary::getSize(NFields, NEntries); 617 std::unique_ptr<IndexedInstrProf::Summary> SummaryData = 618 IndexedInstrProf::allocSummary(SummarySize); 619 620 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); 621 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); 622 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) 623 Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]); 624 625 SummaryEntryVector DetailedSummary; 626 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) { 627 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I); 628 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, 629 Ent.NumBlocks); 630 } 631 // initialize InstrProfSummary using the SummaryData from disk. 632 this->Summary = llvm::make_unique<ProfileSummary>( 633 ProfileSummary::PSK_Instr, DetailedSummary, 634 SummaryData->get(Summary::TotalBlockCount), 635 SummaryData->get(Summary::MaxBlockCount), 636 SummaryData->get(Summary::MaxInternalBlockCount), 637 SummaryData->get(Summary::MaxFunctionCount), 638 SummaryData->get(Summary::TotalNumBlocks), 639 SummaryData->get(Summary::TotalNumFunctions)); 640 return Cur + SummarySize; 641 } else { 642 // For older version of profile data, we need to compute on the fly: 643 using namespace IndexedInstrProf; 644 645 InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); 646 // FIXME: This only computes an empty summary. Need to call addRecord for 647 // all NamedInstrProfRecords to get the correct summary. 648 this->Summary = Builder.getSummary(); 649 return Cur; 650 } 651 } 652 653 Error IndexedInstrProfReader::readHeader() { 654 using namespace support; 655 656 const unsigned char *Start = 657 (const unsigned char *)DataBuffer->getBufferStart(); 658 const unsigned char *Cur = Start; 659 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 660 return error(instrprof_error::truncated); 661 662 auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); 663 Cur += sizeof(IndexedInstrProf::Header); 664 665 // Check the magic number. 666 uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic); 667 if (Magic != IndexedInstrProf::Magic) 668 return error(instrprof_error::bad_magic); 669 670 // Read the version. 671 uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version); 672 if (GET_VERSION(FormatVersion) > 673 IndexedInstrProf::ProfVersion::CurrentVersion) 674 return error(instrprof_error::unsupported_version); 675 676 Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur); 677 678 // Read the hash type and start offset. 679 IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( 680 endian::byte_swap<uint64_t, little>(Header->HashType)); 681 if (HashType > IndexedInstrProf::HashT::Last) 682 return error(instrprof_error::unsupported_hash_type); 683 684 uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset); 685 686 // The rest of the file is an on disk hash table. 687 InstrProfReaderIndexBase *IndexPtr = nullptr; 688 IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>( 689 Start + HashOffset, Cur, Start, HashType, FormatVersion); 690 Index.reset(IndexPtr); 691 return success(); 692 } 693 694 InstrProfSymtab &IndexedInstrProfReader::getSymtab() { 695 if (Symtab.get()) 696 return *Symtab.get(); 697 698 std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); 699 if (Error E = Index->populateSymtab(*NewSymtab.get())) { 700 consumeError(error(InstrProfError::take(std::move(E)))); 701 } 702 703 Symtab = std::move(NewSymtab); 704 return *Symtab.get(); 705 } 706 707 Expected<InstrProfRecord> 708 IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName, 709 uint64_t FuncHash) { 710 ArrayRef<NamedInstrProfRecord> Data; 711 Error Err = Index->getRecords(FuncName, Data); 712 if (Err) 713 return std::move(Err); 714 // Found it. Look for counters with the right hash. 715 for (unsigned I = 0, E = Data.size(); I < E; ++I) { 716 // Check for a match and fill the vector if there is one. 717 if (Data[I].Hash == FuncHash) { 718 return std::move(Data[I]); 719 } 720 } 721 return error(instrprof_error::hash_mismatch); 722 } 723 724 Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, 725 uint64_t FuncHash, 726 std::vector<uint64_t> &Counts) { 727 Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 728 if (Error E = Record.takeError()) 729 return error(std::move(E)); 730 731 Counts = Record.get().Counts; 732 return success(); 733 } 734 735 Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { 736 static unsigned RecordIndex = 0; 737 738 ArrayRef<NamedInstrProfRecord> Data; 739 740 Error E = Index->getRecords(Data); 741 if (E) 742 return error(std::move(E)); 743 744 Record = Data[RecordIndex++]; 745 if (RecordIndex >= Data.size()) { 746 Index->advanceToNextKey(); 747 RecordIndex = 0; 748 } 749 return success(); 750 } 751