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