1 //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains support for reading profiling data for clang's 10 // instrumentation based PGO and coverage. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ProfileData/InstrProfReader.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/IR/ProfileSummary.h" 20 #include "llvm/ProfileData/InstrProf.h" 21 #include "llvm/ProfileData/MemProf.h" 22 #include "llvm/ProfileData/ProfileCommon.h" 23 #include "llvm/ProfileData/SymbolRemappingReader.h" 24 #include "llvm/Support/Endian.h" 25 #include "llvm/Support/Error.h" 26 #include "llvm/Support/ErrorOr.h" 27 #include "llvm/Support/FormatVariadic.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/VirtualFileSystem.h" 30 #include <algorithm> 31 #include <cstddef> 32 #include <cstdint> 33 #include <limits> 34 #include <memory> 35 #include <optional> 36 #include <system_error> 37 #include <utility> 38 #include <vector> 39 40 using namespace llvm; 41 42 // Extracts the variant information from the top 32 bits in the version and 43 // returns an enum specifying the variants present. 44 static InstrProfKind getProfileKindFromVersion(uint64_t Version) { 45 InstrProfKind ProfileKind = InstrProfKind::Unknown; 46 if (Version & VARIANT_MASK_IR_PROF) { 47 ProfileKind |= InstrProfKind::IRInstrumentation; 48 } 49 if (Version & VARIANT_MASK_CSIR_PROF) { 50 ProfileKind |= InstrProfKind::ContextSensitive; 51 } 52 if (Version & VARIANT_MASK_INSTR_ENTRY) { 53 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation; 54 } 55 if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) { 56 ProfileKind |= InstrProfKind::LoopEntriesInstrumentation; 57 } 58 if (Version & VARIANT_MASK_BYTE_COVERAGE) { 59 ProfileKind |= InstrProfKind::SingleByteCoverage; 60 } 61 if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) { 62 ProfileKind |= InstrProfKind::FunctionEntryOnly; 63 } 64 if (Version & VARIANT_MASK_MEMPROF) { 65 ProfileKind |= InstrProfKind::MemProf; 66 } 67 if (Version & VARIANT_MASK_TEMPORAL_PROF) { 68 ProfileKind |= InstrProfKind::TemporalProfile; 69 } 70 return ProfileKind; 71 } 72 73 static Expected<std::unique_ptr<MemoryBuffer>> 74 setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) { 75 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN() 76 : FS.getBufferForFile(Filename); 77 if (std::error_code EC = BufferOrErr.getError()) 78 return errorCodeToError(EC); 79 return std::move(BufferOrErr.get()); 80 } 81 82 static Error initializeReader(InstrProfReader &Reader) { 83 return Reader.readHeader(); 84 } 85 86 /// Read a list of binary ids from a profile that consist of 87 /// a. uint64_t binary id length 88 /// b. uint8_t binary id data 89 /// c. uint8_t padding (if necessary) 90 /// This function is shared between raw and indexed profiles. 91 /// Raw profiles are in host-endian format, and indexed profiles are in 92 /// little-endian format. So, this function takes an argument indicating the 93 /// associated endian format to read the binary ids correctly. 94 static Error 95 readBinaryIdsInternal(const MemoryBuffer &DataBuffer, 96 ArrayRef<uint8_t> BinaryIdsBuffer, 97 std::vector<llvm::object::BuildID> &BinaryIds, 98 const llvm::endianness Endian) { 99 using namespace support; 100 101 const uint64_t BinaryIdsSize = BinaryIdsBuffer.size(); 102 const uint8_t *BinaryIdsStart = BinaryIdsBuffer.data(); 103 104 if (BinaryIdsSize == 0) 105 return Error::success(); 106 107 const uint8_t *BI = BinaryIdsStart; 108 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize; 109 const uint8_t *End = 110 reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd()); 111 112 while (BI < BIEnd) { 113 size_t Remaining = BIEnd - BI; 114 // There should be enough left to read the binary id length. 115 if (Remaining < sizeof(uint64_t)) 116 return make_error<InstrProfError>( 117 instrprof_error::malformed, 118 "not enough data to read binary id length"); 119 120 uint64_t BILen = endian::readNext<uint64_t>(BI, Endian); 121 if (BILen == 0) 122 return make_error<InstrProfError>(instrprof_error::malformed, 123 "binary id length is 0"); 124 125 Remaining = BIEnd - BI; 126 // There should be enough left to read the binary id data. 127 if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t))) 128 return make_error<InstrProfError>( 129 instrprof_error::malformed, "not enough data to read binary id data"); 130 131 // Add binary id to the binary ids list. 132 BinaryIds.push_back(object::BuildID(BI, BI + BILen)); 133 134 // Increment by binary id data length, which aligned to the size of uint64. 135 BI += alignToPowerOf2(BILen, sizeof(uint64_t)); 136 if (BI > End) 137 return make_error<InstrProfError>( 138 instrprof_error::malformed, 139 "binary id section is greater than buffer size"); 140 } 141 142 return Error::success(); 143 } 144 145 static void printBinaryIdsInternal(raw_ostream &OS, 146 ArrayRef<llvm::object::BuildID> BinaryIds) { 147 OS << "Binary IDs: \n"; 148 for (const auto &BI : BinaryIds) { 149 for (auto I : BI) 150 OS << format("%02x", I); 151 OS << "\n"; 152 } 153 } 154 155 Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create( 156 const Twine &Path, vfs::FileSystem &FS, 157 const InstrProfCorrelator *Correlator, 158 const object::BuildIDFetcher *BIDFetcher, 159 const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind, 160 std::function<void(Error)> Warn) { 161 // Set up the buffer to read. 162 auto BufferOrError = setupMemoryBuffer(Path, FS); 163 if (Error E = BufferOrError.takeError()) 164 return std::move(E); 165 return InstrProfReader::create(std::move(BufferOrError.get()), Correlator, 166 BIDFetcher, BIDFetcherCorrelatorKind, Warn); 167 } 168 169 Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create( 170 std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator, 171 const object::BuildIDFetcher *BIDFetcher, 172 const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind, 173 std::function<void(Error)> Warn) { 174 if (Buffer->getBufferSize() == 0) 175 return make_error<InstrProfError>(instrprof_error::empty_raw_profile); 176 177 std::unique_ptr<InstrProfReader> Result; 178 // Create the reader. 179 if (IndexedInstrProfReader::hasFormat(*Buffer)) 180 Result.reset(new IndexedInstrProfReader(std::move(Buffer))); 181 else if (RawInstrProfReader64::hasFormat(*Buffer)) 182 Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator, 183 BIDFetcher, BIDFetcherCorrelatorKind, 184 Warn)); 185 else if (RawInstrProfReader32::hasFormat(*Buffer)) 186 Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator, 187 BIDFetcher, BIDFetcherCorrelatorKind, 188 Warn)); 189 else if (TextInstrProfReader::hasFormat(*Buffer)) 190 Result.reset(new TextInstrProfReader(std::move(Buffer))); 191 else 192 return make_error<InstrProfError>(instrprof_error::unrecognized_format); 193 194 // Initialize the reader and return the result. 195 if (Error E = initializeReader(*Result)) 196 return std::move(E); 197 198 return std::move(Result); 199 } 200 201 Expected<std::unique_ptr<IndexedInstrProfReader>> 202 IndexedInstrProfReader::create(const Twine &Path, vfs::FileSystem &FS, 203 const Twine &RemappingPath) { 204 // Set up the buffer to read. 205 auto BufferOrError = setupMemoryBuffer(Path, FS); 206 if (Error E = BufferOrError.takeError()) 207 return std::move(E); 208 209 // Set up the remapping buffer if requested. 210 std::unique_ptr<MemoryBuffer> RemappingBuffer; 211 std::string RemappingPathStr = RemappingPath.str(); 212 if (!RemappingPathStr.empty()) { 213 auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS); 214 if (Error E = RemappingBufferOrError.takeError()) 215 return std::move(E); 216 RemappingBuffer = std::move(RemappingBufferOrError.get()); 217 } 218 219 return IndexedInstrProfReader::create(std::move(BufferOrError.get()), 220 std::move(RemappingBuffer)); 221 } 222 223 Expected<std::unique_ptr<IndexedInstrProfReader>> 224 IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer, 225 std::unique_ptr<MemoryBuffer> RemappingBuffer) { 226 // Create the reader. 227 if (!IndexedInstrProfReader::hasFormat(*Buffer)) 228 return make_error<InstrProfError>(instrprof_error::bad_magic); 229 auto Result = std::make_unique<IndexedInstrProfReader>( 230 std::move(Buffer), std::move(RemappingBuffer)); 231 232 // Initialize the reader and return the result. 233 if (Error E = initializeReader(*Result)) 234 return std::move(E); 235 236 return std::move(Result); 237 } 238 239 bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { 240 // Verify that this really looks like plain ASCII text by checking a 241 // 'reasonable' number of characters (up to profile magic size). 242 size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t)); 243 StringRef buffer = Buffer.getBufferStart(); 244 return count == 0 || 245 std::all_of(buffer.begin(), buffer.begin() + count, 246 [](char c) { return isPrint(c) || isSpace(c); }); 247 } 248 249 // Read the profile variant flag from the header: ":FE" means this is a FE 250 // generated profile. ":IR" means this is an IR level profile. Other strings 251 // with a leading ':' will be reported an error format. 252 Error TextInstrProfReader::readHeader() { 253 Symtab.reset(new InstrProfSymtab()); 254 255 while (Line->starts_with(":")) { 256 StringRef Str = Line->substr(1); 257 if (Str.equals_insensitive("ir")) 258 ProfileKind |= InstrProfKind::IRInstrumentation; 259 else if (Str.equals_insensitive("fe")) 260 ProfileKind |= InstrProfKind::FrontendInstrumentation; 261 else if (Str.equals_insensitive("csir")) { 262 ProfileKind |= InstrProfKind::IRInstrumentation; 263 ProfileKind |= InstrProfKind::ContextSensitive; 264 } else if (Str.equals_insensitive("entry_first")) 265 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation; 266 else if (Str.equals_insensitive("not_entry_first")) 267 ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation; 268 else if (Str.equals_insensitive("instrument_loop_entries")) 269 ProfileKind |= InstrProfKind::LoopEntriesInstrumentation; 270 else if (Str.equals_insensitive("single_byte_coverage")) 271 ProfileKind |= InstrProfKind::SingleByteCoverage; 272 else if (Str.equals_insensitive("temporal_prof_traces")) { 273 ProfileKind |= InstrProfKind::TemporalProfile; 274 if (auto Err = readTemporalProfTraceData()) 275 return error(std::move(Err)); 276 } else 277 return error(instrprof_error::bad_header); 278 ++Line; 279 } 280 return success(); 281 } 282 283 /// Temporal profile trace data is stored in the header immediately after 284 /// ":temporal_prof_traces". The first integer is the number of traces, the 285 /// second integer is the stream size, then the following lines are the actual 286 /// traces which consist of a weight and a comma separated list of function 287 /// names. 288 Error TextInstrProfReader::readTemporalProfTraceData() { 289 if ((++Line).is_at_end()) 290 return error(instrprof_error::eof); 291 292 uint32_t NumTraces; 293 if (Line->getAsInteger(0, NumTraces)) 294 return error(instrprof_error::malformed); 295 296 if ((++Line).is_at_end()) 297 return error(instrprof_error::eof); 298 299 if (Line->getAsInteger(0, TemporalProfTraceStreamSize)) 300 return error(instrprof_error::malformed); 301 302 for (uint32_t i = 0; i < NumTraces; i++) { 303 if ((++Line).is_at_end()) 304 return error(instrprof_error::eof); 305 306 TemporalProfTraceTy Trace; 307 if (Line->getAsInteger(0, Trace.Weight)) 308 return error(instrprof_error::malformed); 309 310 if ((++Line).is_at_end()) 311 return error(instrprof_error::eof); 312 313 SmallVector<StringRef> FuncNames; 314 Line->split(FuncNames, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 315 for (auto &FuncName : FuncNames) 316 Trace.FunctionNameRefs.push_back( 317 IndexedInstrProf::ComputeHash(FuncName.trim())); 318 TemporalProfTraces.push_back(std::move(Trace)); 319 } 320 return success(); 321 } 322 323 Error 324 TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { 325 326 #define CHECK_LINE_END(Line) \ 327 if (Line.is_at_end()) \ 328 return error(instrprof_error::truncated); 329 #define READ_NUM(Str, Dst) \ 330 if ((Str).getAsInteger(10, (Dst))) \ 331 return error(instrprof_error::malformed); 332 #define VP_READ_ADVANCE(Val) \ 333 CHECK_LINE_END(Line); \ 334 uint32_t Val; \ 335 READ_NUM((*Line), (Val)); \ 336 Line++; 337 338 if (Line.is_at_end()) 339 return success(); 340 341 uint32_t NumValueKinds; 342 if (Line->getAsInteger(10, NumValueKinds)) { 343 // No value profile data 344 return success(); 345 } 346 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1) 347 return error(instrprof_error::malformed, 348 "number of value kinds is invalid"); 349 Line++; 350 351 for (uint32_t VK = 0; VK < NumValueKinds; VK++) { 352 VP_READ_ADVANCE(ValueKind); 353 if (ValueKind > IPVK_Last) 354 return error(instrprof_error::malformed, "value kind is invalid"); 355 ; 356 VP_READ_ADVANCE(NumValueSites); 357 if (!NumValueSites) 358 continue; 359 360 Record.reserveSites(VK, NumValueSites); 361 for (uint32_t S = 0; S < NumValueSites; S++) { 362 VP_READ_ADVANCE(NumValueData); 363 364 std::vector<InstrProfValueData> CurrentValues; 365 for (uint32_t V = 0; V < NumValueData; V++) { 366 CHECK_LINE_END(Line); 367 std::pair<StringRef, StringRef> VD = Line->rsplit(':'); 368 uint64_t TakenCount, Value; 369 if (ValueKind == IPVK_IndirectCallTarget) { 370 if (InstrProfSymtab::isExternalSymbol(VD.first)) { 371 Value = 0; 372 } else { 373 if (Error E = Symtab->addFuncName(VD.first)) 374 return E; 375 Value = IndexedInstrProf::ComputeHash(VD.first); 376 } 377 } else if (ValueKind == IPVK_VTableTarget) { 378 if (InstrProfSymtab::isExternalSymbol(VD.first)) 379 Value = 0; 380 else { 381 if (Error E = Symtab->addVTableName(VD.first)) 382 return E; 383 Value = IndexedInstrProf::ComputeHash(VD.first); 384 } 385 } else { 386 READ_NUM(VD.first, Value); 387 } 388 READ_NUM(VD.second, TakenCount); 389 CurrentValues.push_back({Value, TakenCount}); 390 Line++; 391 } 392 assert(CurrentValues.size() == NumValueData); 393 Record.addValueData(ValueKind, S, CurrentValues, nullptr); 394 } 395 } 396 return success(); 397 398 #undef CHECK_LINE_END 399 #undef READ_NUM 400 #undef VP_READ_ADVANCE 401 } 402 403 Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { 404 // Skip empty lines and comments. 405 while (!Line.is_at_end() && (Line->empty() || Line->starts_with("#"))) 406 ++Line; 407 // If we hit EOF while looking for a name, we're done. 408 if (Line.is_at_end()) { 409 return error(instrprof_error::eof); 410 } 411 412 // Read the function name. 413 Record.Name = *Line++; 414 if (Error E = Symtab->addFuncName(Record.Name)) 415 return error(std::move(E)); 416 417 // Read the function hash. 418 if (Line.is_at_end()) 419 return error(instrprof_error::truncated); 420 if ((Line++)->getAsInteger(0, Record.Hash)) 421 return error(instrprof_error::malformed, 422 "function hash is not a valid integer"); 423 424 // Read the number of counters. 425 uint64_t NumCounters; 426 if (Line.is_at_end()) 427 return error(instrprof_error::truncated); 428 if ((Line++)->getAsInteger(10, NumCounters)) 429 return error(instrprof_error::malformed, 430 "number of counters is not a valid integer"); 431 if (NumCounters == 0) 432 return error(instrprof_error::malformed, "number of counters is zero"); 433 434 // Read each counter and fill our internal storage with the values. 435 Record.Clear(); 436 Record.Counts.reserve(NumCounters); 437 for (uint64_t I = 0; I < NumCounters; ++I) { 438 if (Line.is_at_end()) 439 return error(instrprof_error::truncated); 440 uint64_t Count; 441 if ((Line++)->getAsInteger(10, Count)) 442 return error(instrprof_error::malformed, "count is invalid"); 443 Record.Counts.push_back(Count); 444 } 445 446 // Bitmap byte information is indicated with special character. 447 if (Line->starts_with("$")) { 448 Record.BitmapBytes.clear(); 449 // Read the number of bitmap bytes. 450 uint64_t NumBitmapBytes; 451 if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes)) 452 return error(instrprof_error::malformed, 453 "number of bitmap bytes is not a valid integer"); 454 if (NumBitmapBytes != 0) { 455 // Read each bitmap and fill our internal storage with the values. 456 Record.BitmapBytes.reserve(NumBitmapBytes); 457 for (uint8_t I = 0; I < NumBitmapBytes; ++I) { 458 if (Line.is_at_end()) 459 return error(instrprof_error::truncated); 460 uint8_t BitmapByte; 461 if ((Line++)->getAsInteger(0, BitmapByte)) 462 return error(instrprof_error::malformed, 463 "bitmap byte is not a valid integer"); 464 Record.BitmapBytes.push_back(BitmapByte); 465 } 466 } 467 } 468 469 // Check if value profile data exists and read it if so. 470 if (Error E = readValueProfileData(Record)) 471 return error(std::move(E)); 472 473 return success(); 474 } 475 476 template <class IntPtrT> 477 InstrProfKind RawInstrProfReader<IntPtrT>::getProfileKind() const { 478 return getProfileKindFromVersion(Version); 479 } 480 481 template <class IntPtrT> 482 SmallVector<TemporalProfTraceTy> & 483 RawInstrProfReader<IntPtrT>::getTemporalProfTraces( 484 std::optional<uint64_t> Weight) { 485 if (TemporalProfTimestamps.empty()) { 486 assert(TemporalProfTraces.empty()); 487 return TemporalProfTraces; 488 } 489 // Sort functions by their timestamps to build the trace. 490 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end()); 491 TemporalProfTraceTy Trace; 492 if (Weight) 493 Trace.Weight = *Weight; 494 for (auto &[TimestampValue, NameRef] : TemporalProfTimestamps) 495 Trace.FunctionNameRefs.push_back(NameRef); 496 TemporalProfTraces = {std::move(Trace)}; 497 return TemporalProfTraces; 498 } 499 500 template <class IntPtrT> 501 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 502 if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 503 return false; 504 uint64_t Magic = 505 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 506 return RawInstrProf::getMagic<IntPtrT>() == Magic || 507 llvm::byteswap(RawInstrProf::getMagic<IntPtrT>()) == Magic; 508 } 509 510 template <class IntPtrT> 511 Error RawInstrProfReader<IntPtrT>::readHeader() { 512 if (!hasFormat(*DataBuffer)) 513 return error(instrprof_error::bad_magic); 514 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)) 515 return error(instrprof_error::bad_header); 516 auto *Header = reinterpret_cast<const RawInstrProf::Header *>( 517 DataBuffer->getBufferStart()); 518 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); 519 return readHeader(*Header); 520 } 521 522 template <class IntPtrT> 523 Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { 524 const char *End = DataBuffer->getBufferEnd(); 525 // Skip zero padding between profiles. 526 while (CurrentPos != End && *CurrentPos == 0) 527 ++CurrentPos; 528 // If there's nothing left, we're done. 529 if (CurrentPos == End) 530 return make_error<InstrProfError>(instrprof_error::eof); 531 // If there isn't enough space for another header, this is probably just 532 // garbage at the end of the file. 533 if (CurrentPos + sizeof(RawInstrProf::Header) > End) 534 return make_error<InstrProfError>(instrprof_error::malformed, 535 "not enough space for another header"); 536 // The writer ensures each profile is padded to start at an aligned address. 537 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t)) 538 return make_error<InstrProfError>(instrprof_error::malformed, 539 "insufficient padding"); 540 // The magic should have the same byte order as in the previous header. 541 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); 542 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) 543 return make_error<InstrProfError>(instrprof_error::bad_magic); 544 545 // There's another profile to read, so we need to process the header. 546 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); 547 return readHeader(*Header); 548 } 549 550 template <class IntPtrT> 551 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { 552 if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart), 553 StringRef(VNamesStart, VNamesEnd - VNamesStart))) 554 return error(std::move(E)); 555 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { 556 const IntPtrT FPtr = swap(I->FunctionPointer); 557 if (!FPtr) 558 continue; 559 Symtab.mapAddress(FPtr, swap(I->NameRef)); 560 } 561 562 if (VTableBegin != nullptr && VTableEnd != nullptr) { 563 for (const RawInstrProf::VTableProfileData<IntPtrT> *I = VTableBegin; 564 I != VTableEnd; ++I) { 565 const IntPtrT VPtr = swap(I->VTablePointer); 566 if (!VPtr) 567 continue; 568 // Map both begin and end address to the name hash, since the instrumented 569 // address could be somewhere in the middle. 570 // VPtr is of type uint32_t or uint64_t so 'VPtr + I->VTableSize' marks 571 // the end of vtable address. 572 Symtab.mapVTableAddress(VPtr, VPtr + swap(I->VTableSize), 573 swap(I->VTableNameHash)); 574 } 575 } 576 return success(); 577 } 578 579 template <class IntPtrT> 580 Error RawInstrProfReader<IntPtrT>::readHeader( 581 const RawInstrProf::Header &Header) { 582 Version = swap(Header.Version); 583 if (GET_VERSION(Version) != RawInstrProf::Version) 584 return error(instrprof_error::raw_profile_version_mismatch, 585 ("Profile uses raw profile format version = " + 586 Twine(GET_VERSION(Version)) + 587 "; expected version = " + Twine(RawInstrProf::Version) + 588 "\nPLEASE update this tool to version in the raw profile, or " 589 "regenerate raw profile with expected version.") 590 .str()); 591 592 uint64_t BinaryIdSize = swap(Header.BinaryIdsSize); 593 // Binary id start just after the header if exists. 594 const uint8_t *BinaryIdStart = 595 reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header); 596 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize; 597 const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd(); 598 if (BinaryIdSize % sizeof(uint64_t) || BinaryIdEnd > BufferEnd) 599 return error(instrprof_error::bad_header); 600 ArrayRef<uint8_t> BinaryIdsBuffer(BinaryIdStart, BinaryIdSize); 601 if (!BinaryIdsBuffer.empty()) { 602 if (Error Err = readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer, 603 BinaryIds, getDataEndianness())) 604 return Err; 605 } 606 607 CountersDelta = swap(Header.CountersDelta); 608 BitmapDelta = swap(Header.BitmapDelta); 609 NamesDelta = swap(Header.NamesDelta); 610 auto NumData = swap(Header.NumData); 611 auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters); 612 auto CountersSize = swap(Header.NumCounters) * getCounterTypeSize(); 613 auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters); 614 auto NumBitmapBytes = swap(Header.NumBitmapBytes); 615 auto PaddingBytesAfterBitmapBytes = swap(Header.PaddingBytesAfterBitmapBytes); 616 auto NamesSize = swap(Header.NamesSize); 617 auto VTableNameSize = swap(Header.VNamesSize); 618 auto NumVTables = swap(Header.NumVTables); 619 ValueKindLast = swap(Header.ValueKindLast); 620 621 auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>); 622 auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize); 623 auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize); 624 625 auto VTableSectionSize = 626 NumVTables * sizeof(RawInstrProf::VTableProfileData<IntPtrT>); 627 auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize); 628 629 // Profile data starts after profile header and binary ids if exist. 630 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdSize; 631 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters; 632 ptrdiff_t BitmapOffset = 633 CountersOffset + CountersSize + PaddingBytesAfterCounters; 634 ptrdiff_t NamesOffset = 635 BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes; 636 ptrdiff_t VTableProfDataOffset = 637 NamesOffset + NamesSize + PaddingBytesAfterNames; 638 ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize + 639 PaddingBytesAfterVTableProfData; 640 ptrdiff_t ValueDataOffset = 641 VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames; 642 643 auto *Start = reinterpret_cast<const char *>(&Header); 644 if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) 645 return error(instrprof_error::bad_header); 646 647 if (BIDFetcher) { 648 std::vector<object::BuildID> BinaryIDs; 649 if (Error E = readBinaryIds(BinaryIDs)) 650 return E; 651 if (auto E = InstrProfCorrelator::get("", BIDFetcherCorrelatorKind, 652 BIDFetcher, BinaryIDs) 653 .moveInto(BIDFetcherCorrelator)) { 654 return E; 655 } 656 if (auto Err = BIDFetcherCorrelator->correlateProfileData(0)) 657 return Err; 658 } 659 660 if (Correlator) { 661 // These sizes in the raw file are zero because we constructed them in the 662 // Correlator. 663 if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 && 664 NamesDelta == 0)) 665 return error(instrprof_error::unexpected_correlation_info); 666 Data = Correlator->getDataPointer(); 667 DataEnd = Data + Correlator->getDataSize(); 668 NamesStart = Correlator->getNamesPointer(); 669 NamesEnd = NamesStart + Correlator->getNamesSize(); 670 } else if (BIDFetcherCorrelator) { 671 InstrProfCorrelatorImpl<IntPtrT> *BIDFetcherCorrelatorImpl = 672 dyn_cast_or_null<InstrProfCorrelatorImpl<IntPtrT>>( 673 BIDFetcherCorrelator.get()); 674 Data = BIDFetcherCorrelatorImpl->getDataPointer(); 675 DataEnd = Data + BIDFetcherCorrelatorImpl->getDataSize(); 676 NamesStart = BIDFetcherCorrelatorImpl->getNamesPointer(); 677 NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->getNamesSize(); 678 } else { 679 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( 680 Start + DataOffset); 681 DataEnd = Data + NumData; 682 VTableBegin = 683 reinterpret_cast<const RawInstrProf::VTableProfileData<IntPtrT> *>( 684 Start + VTableProfDataOffset); 685 VTableEnd = VTableBegin + NumVTables; 686 NamesStart = Start + NamesOffset; 687 NamesEnd = NamesStart + NamesSize; 688 VNamesStart = Start + VTableNameOffset; 689 VNamesEnd = VNamesStart + VTableNameSize; 690 } 691 692 CountersStart = Start + CountersOffset; 693 CountersEnd = CountersStart + CountersSize; 694 BitmapStart = Start + BitmapOffset; 695 BitmapEnd = BitmapStart + NumBitmapBytes; 696 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); 697 698 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>(); 699 if (Error E = createSymtab(*NewSymtab)) 700 return E; 701 702 Symtab = std::move(NewSymtab); 703 return success(); 704 } 705 706 template <class IntPtrT> 707 Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) { 708 Record.Name = getName(Data->NameRef); 709 return success(); 710 } 711 712 template <class IntPtrT> 713 Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) { 714 Record.Hash = swap(Data->FuncHash); 715 return success(); 716 } 717 718 template <class IntPtrT> 719 Error RawInstrProfReader<IntPtrT>::readRawCounts( 720 InstrProfRecord &Record) { 721 uint32_t NumCounters = swap(Data->NumCounters); 722 if (NumCounters == 0) 723 return error(instrprof_error::malformed, "number of counters is zero"); 724 725 ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta; 726 if (CounterBaseOffset < 0) 727 return error( 728 instrprof_error::malformed, 729 ("counter offset " + Twine(CounterBaseOffset) + " is negative").str()); 730 731 if (CounterBaseOffset >= CountersEnd - CountersStart) 732 return error(instrprof_error::malformed, 733 ("counter offset " + Twine(CounterBaseOffset) + 734 " is greater than the maximum counter offset " + 735 Twine(CountersEnd - CountersStart - 1)) 736 .str()); 737 738 uint64_t MaxNumCounters = 739 (CountersEnd - (CountersStart + CounterBaseOffset)) / 740 getCounterTypeSize(); 741 if (NumCounters > MaxNumCounters) 742 return error(instrprof_error::malformed, 743 ("number of counters " + Twine(NumCounters) + 744 " is greater than the maximum number of counters " + 745 Twine(MaxNumCounters)) 746 .str()); 747 748 Record.Counts.clear(); 749 Record.Counts.reserve(NumCounters); 750 for (uint32_t I = 0; I < NumCounters; I++) { 751 const char *Ptr = 752 CountersStart + CounterBaseOffset + I * getCounterTypeSize(); 753 if (I == 0 && hasTemporalProfile()) { 754 uint64_t TimestampValue = swap(*reinterpret_cast<const uint64_t *>(Ptr)); 755 if (TimestampValue != 0 && 756 TimestampValue != std::numeric_limits<uint64_t>::max()) { 757 TemporalProfTimestamps.emplace_back(TimestampValue, 758 swap(Data->NameRef)); 759 TemporalProfTraceStreamSize = 1; 760 } 761 if (hasSingleByteCoverage()) { 762 // In coverage mode, getCounterTypeSize() returns 1 byte but our 763 // timestamp field has size uint64_t. Increment I so that the next 764 // iteration of this for loop points to the byte after the timestamp 765 // field, i.e., I += 8. 766 I += 7; 767 } 768 continue; 769 } 770 if (hasSingleByteCoverage()) { 771 // A value of zero signifies the block is covered. 772 Record.Counts.push_back(*Ptr == 0 ? 1 : 0); 773 } else { 774 uint64_t CounterValue = swap(*reinterpret_cast<const uint64_t *>(Ptr)); 775 if (CounterValue > MaxCounterValue && Warn) 776 Warn(make_error<InstrProfError>( 777 instrprof_error::counter_value_too_large, Twine(CounterValue))); 778 779 Record.Counts.push_back(CounterValue); 780 } 781 } 782 783 return success(); 784 } 785 786 template <class IntPtrT> 787 Error RawInstrProfReader<IntPtrT>::readRawBitmapBytes(InstrProfRecord &Record) { 788 uint32_t NumBitmapBytes = swap(Data->NumBitmapBytes); 789 790 Record.BitmapBytes.clear(); 791 Record.BitmapBytes.reserve(NumBitmapBytes); 792 793 // It's possible MCDC is either not enabled or only used for some functions 794 // and not others. So if we record 0 bytes, just move on. 795 if (NumBitmapBytes == 0) 796 return success(); 797 798 // BitmapDelta decreases as we advance to the next data record. 799 ptrdiff_t BitmapOffset = swap(Data->BitmapPtr) - BitmapDelta; 800 if (BitmapOffset < 0) 801 return error( 802 instrprof_error::malformed, 803 ("bitmap offset " + Twine(BitmapOffset) + " is negative").str()); 804 805 if (BitmapOffset >= BitmapEnd - BitmapStart) 806 return error(instrprof_error::malformed, 807 ("bitmap offset " + Twine(BitmapOffset) + 808 " is greater than the maximum bitmap offset " + 809 Twine(BitmapEnd - BitmapStart - 1)) 810 .str()); 811 812 uint64_t MaxNumBitmapBytes = 813 (BitmapEnd - (BitmapStart + BitmapOffset)) / sizeof(uint8_t); 814 if (NumBitmapBytes > MaxNumBitmapBytes) 815 return error(instrprof_error::malformed, 816 ("number of bitmap bytes " + Twine(NumBitmapBytes) + 817 " is greater than the maximum number of bitmap bytes " + 818 Twine(MaxNumBitmapBytes)) 819 .str()); 820 821 for (uint32_t I = 0; I < NumBitmapBytes; I++) { 822 const char *Ptr = BitmapStart + BitmapOffset + I; 823 Record.BitmapBytes.push_back(swap(*Ptr)); 824 } 825 826 return success(); 827 } 828 829 template <class IntPtrT> 830 Error RawInstrProfReader<IntPtrT>::readValueProfilingData( 831 InstrProfRecord &Record) { 832 Record.clearValueData(); 833 CurValueDataSize = 0; 834 // Need to match the logic in value profile dumper code in compiler-rt: 835 uint32_t NumValueKinds = 0; 836 for (uint32_t I = 0; I < IPVK_Last + 1; I++) 837 NumValueKinds += (Data->NumValueSites[I] != 0); 838 839 if (!NumValueKinds) 840 return success(); 841 842 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 843 ValueProfData::getValueProfData( 844 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), 845 getDataEndianness()); 846 847 if (Error E = VDataPtrOrErr.takeError()) 848 return E; 849 850 // Note that besides deserialization, this also performs the conversion for 851 // indirect call targets. The function pointers from the raw profile are 852 // remapped into function name hashes. 853 VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get()); 854 CurValueDataSize = VDataPtrOrErr.get()->getSize(); 855 return success(); 856 } 857 858 template <class IntPtrT> 859 Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) { 860 // Keep reading profiles that consist of only headers and no profile data and 861 // counters. 862 while (atEnd()) 863 // At this point, ValueDataStart field points to the next header. 864 if (Error E = readNextHeader(getNextHeaderPos())) 865 return error(std::move(E)); 866 867 // Read name and set it in Record. 868 if (Error E = readName(Record)) 869 return error(std::move(E)); 870 871 // Read FuncHash and set it in Record. 872 if (Error E = readFuncHash(Record)) 873 return error(std::move(E)); 874 875 // Read raw counts and set Record. 876 if (Error E = readRawCounts(Record)) 877 return error(std::move(E)); 878 879 // Read raw bitmap bytes and set Record. 880 if (Error E = readRawBitmapBytes(Record)) 881 return error(std::move(E)); 882 883 // Read value data and set Record. 884 if (Error E = readValueProfilingData(Record)) 885 return error(std::move(E)); 886 887 // Iterate. 888 advanceData(); 889 return success(); 890 } 891 892 template <class IntPtrT> 893 Error RawInstrProfReader<IntPtrT>::readBinaryIds( 894 std::vector<llvm::object::BuildID> &BinaryIds) { 895 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(), 896 this->BinaryIds.end()); 897 return Error::success(); 898 } 899 900 template <class IntPtrT> 901 Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) { 902 if (!BinaryIds.empty()) 903 printBinaryIdsInternal(OS, BinaryIds); 904 return Error::success(); 905 } 906 907 namespace llvm { 908 909 template class RawInstrProfReader<uint32_t>; 910 template class RawInstrProfReader<uint64_t>; 911 912 } // end namespace llvm 913 914 InstrProfLookupTrait::hash_value_type 915 InstrProfLookupTrait::ComputeHash(StringRef K) { 916 return IndexedInstrProf::ComputeHash(HashType, K); 917 } 918 919 using data_type = InstrProfLookupTrait::data_type; 920 using offset_type = InstrProfLookupTrait::offset_type; 921 922 bool InstrProfLookupTrait::readValueProfilingData( 923 const unsigned char *&D, const unsigned char *const End) { 924 Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = 925 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); 926 927 if (VDataPtrOrErr.takeError()) 928 return false; 929 930 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); 931 D += VDataPtrOrErr.get()->TotalSize; 932 933 return true; 934 } 935 936 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, 937 offset_type N) { 938 using namespace support; 939 940 // Check if the data is corrupt. If so, don't try to read it. 941 if (N % sizeof(uint64_t)) 942 return data_type(); 943 944 DataBuffer.clear(); 945 std::vector<uint64_t> CounterBuffer; 946 std::vector<uint8_t> BitmapByteBuffer; 947 948 const unsigned char *End = D + N; 949 while (D < End) { 950 // Read hash. 951 if (D + sizeof(uint64_t) >= End) 952 return data_type(); 953 uint64_t Hash = endian::readNext<uint64_t, llvm::endianness::little>(D); 954 955 // Initialize number of counters for GET_VERSION(FormatVersion) == 1. 956 uint64_t CountsSize = N / sizeof(uint64_t) - 1; 957 // If format version is different then read the number of counters. 958 if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) { 959 if (D + sizeof(uint64_t) > End) 960 return data_type(); 961 CountsSize = endian::readNext<uint64_t, llvm::endianness::little>(D); 962 } 963 // Read counter values. 964 if (D + CountsSize * sizeof(uint64_t) > End) 965 return data_type(); 966 967 CounterBuffer.clear(); 968 CounterBuffer.reserve(CountsSize); 969 for (uint64_t J = 0; J < CountsSize; ++J) 970 CounterBuffer.push_back( 971 endian::readNext<uint64_t, llvm::endianness::little>(D)); 972 973 // Read bitmap bytes for GET_VERSION(FormatVersion) > 10. 974 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version10) { 975 uint64_t BitmapBytes = 0; 976 if (D + sizeof(uint64_t) > End) 977 return data_type(); 978 BitmapBytes = endian::readNext<uint64_t, llvm::endianness::little>(D); 979 // Read bitmap byte values. 980 if (D + BitmapBytes * sizeof(uint8_t) > End) 981 return data_type(); 982 BitmapByteBuffer.clear(); 983 BitmapByteBuffer.reserve(BitmapBytes); 984 for (uint64_t J = 0; J < BitmapBytes; ++J) 985 BitmapByteBuffer.push_back(static_cast<uint8_t>( 986 endian::readNext<uint64_t, llvm::endianness::little>(D))); 987 } 988 989 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer), 990 std::move(BitmapByteBuffer)); 991 992 // Read value profiling data. 993 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && 994 !readValueProfilingData(D, End)) { 995 DataBuffer.clear(); 996 return data_type(); 997 } 998 } 999 return DataBuffer; 1000 } 1001 1002 template <typename HashTableImpl> 1003 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 1004 StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) { 1005 auto Iter = HashTable->find(FuncName); 1006 if (Iter == HashTable->end()) 1007 return make_error<InstrProfError>(instrprof_error::unknown_function); 1008 1009 Data = (*Iter); 1010 if (Data.empty()) 1011 return make_error<InstrProfError>(instrprof_error::malformed, 1012 "profile data is empty"); 1013 1014 return Error::success(); 1015 } 1016 1017 template <typename HashTableImpl> 1018 Error InstrProfReaderIndex<HashTableImpl>::getRecords( 1019 ArrayRef<NamedInstrProfRecord> &Data) { 1020 if (atEnd()) 1021 return make_error<InstrProfError>(instrprof_error::eof); 1022 1023 Data = *RecordIterator; 1024 1025 if (Data.empty()) 1026 return make_error<InstrProfError>(instrprof_error::malformed, 1027 "profile data is empty"); 1028 1029 return Error::success(); 1030 } 1031 1032 template <typename HashTableImpl> 1033 InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( 1034 const unsigned char *Buckets, const unsigned char *const Payload, 1035 const unsigned char *const Base, IndexedInstrProf::HashT HashType, 1036 uint64_t Version) { 1037 FormatVersion = Version; 1038 HashTable.reset(HashTableImpl::Create( 1039 Buckets, Payload, Base, 1040 typename HashTableImpl::InfoType(HashType, Version))); 1041 RecordIterator = HashTable->data_begin(); 1042 } 1043 1044 template <typename HashTableImpl> 1045 InstrProfKind InstrProfReaderIndex<HashTableImpl>::getProfileKind() const { 1046 return getProfileKindFromVersion(FormatVersion); 1047 } 1048 1049 namespace { 1050 /// A remapper that does not apply any remappings. 1051 class InstrProfReaderNullRemapper : public InstrProfReaderRemapper { 1052 InstrProfReaderIndexBase &Underlying; 1053 1054 public: 1055 InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying) 1056 : Underlying(Underlying) {} 1057 1058 Error getRecords(StringRef FuncName, 1059 ArrayRef<NamedInstrProfRecord> &Data) override { 1060 return Underlying.getRecords(FuncName, Data); 1061 } 1062 }; 1063 } // namespace 1064 1065 /// A remapper that applies remappings based on a symbol remapping file. 1066 template <typename HashTableImpl> 1067 class llvm::InstrProfReaderItaniumRemapper 1068 : public InstrProfReaderRemapper { 1069 public: 1070 InstrProfReaderItaniumRemapper( 1071 std::unique_ptr<MemoryBuffer> RemapBuffer, 1072 InstrProfReaderIndex<HashTableImpl> &Underlying) 1073 : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) { 1074 } 1075 1076 /// Extract the original function name from a PGO function name. 1077 static StringRef extractName(StringRef Name) { 1078 // We can have multiple pieces separated by kGlobalIdentifierDelimiter ( 1079 // semicolon now and colon in older profiles); there can be pieces both 1080 // before and after the mangled name. Find the first part that starts with 1081 // '_Z'; we'll assume that's the mangled name we want. 1082 std::pair<StringRef, StringRef> Parts = {StringRef(), Name}; 1083 while (true) { 1084 Parts = Parts.second.split(GlobalIdentifierDelimiter); 1085 if (Parts.first.starts_with("_Z")) 1086 return Parts.first; 1087 if (Parts.second.empty()) 1088 return Name; 1089 } 1090 } 1091 1092 /// Given a mangled name extracted from a PGO function name, and a new 1093 /// form for that mangled name, reconstitute the name. 1094 static void reconstituteName(StringRef OrigName, StringRef ExtractedName, 1095 StringRef Replacement, 1096 SmallVectorImpl<char> &Out) { 1097 Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size()); 1098 Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin()); 1099 Out.insert(Out.end(), Replacement.begin(), Replacement.end()); 1100 Out.insert(Out.end(), ExtractedName.end(), OrigName.end()); 1101 } 1102 1103 Error populateRemappings() override { 1104 if (Error E = Remappings.read(*RemapBuffer)) 1105 return E; 1106 for (StringRef Name : Underlying.HashTable->keys()) { 1107 StringRef RealName = extractName(Name); 1108 if (auto Key = Remappings.insert(RealName)) { 1109 // FIXME: We could theoretically map the same equivalence class to 1110 // multiple names in the profile data. If that happens, we should 1111 // return NamedInstrProfRecords from all of them. 1112 MappedNames.insert({Key, RealName}); 1113 } 1114 } 1115 return Error::success(); 1116 } 1117 1118 Error getRecords(StringRef FuncName, 1119 ArrayRef<NamedInstrProfRecord> &Data) override { 1120 StringRef RealName = extractName(FuncName); 1121 if (auto Key = Remappings.lookup(RealName)) { 1122 StringRef Remapped = MappedNames.lookup(Key); 1123 if (!Remapped.empty()) { 1124 if (RealName.begin() == FuncName.begin() && 1125 RealName.end() == FuncName.end()) 1126 FuncName = Remapped; 1127 else { 1128 // Try rebuilding the name from the given remapping. 1129 SmallString<256> Reconstituted; 1130 reconstituteName(FuncName, RealName, Remapped, Reconstituted); 1131 Error E = Underlying.getRecords(Reconstituted, Data); 1132 if (!E) 1133 return E; 1134 1135 // If we failed because the name doesn't exist, fall back to asking 1136 // about the original name. 1137 if (Error Unhandled = handleErrors( 1138 std::move(E), [](std::unique_ptr<InstrProfError> Err) { 1139 return Err->get() == instrprof_error::unknown_function 1140 ? Error::success() 1141 : Error(std::move(Err)); 1142 })) 1143 return Unhandled; 1144 } 1145 } 1146 } 1147 return Underlying.getRecords(FuncName, Data); 1148 } 1149 1150 private: 1151 /// The memory buffer containing the remapping configuration. Remappings 1152 /// holds pointers into this buffer. 1153 std::unique_ptr<MemoryBuffer> RemapBuffer; 1154 1155 /// The mangling remapper. 1156 SymbolRemappingReader Remappings; 1157 1158 /// Mapping from mangled name keys to the name used for the key in the 1159 /// profile data. 1160 /// FIXME: Can we store a location within the on-disk hash table instead of 1161 /// redoing lookup? 1162 DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames; 1163 1164 /// The real profile data reader. 1165 InstrProfReaderIndex<HashTableImpl> &Underlying; 1166 }; 1167 1168 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { 1169 using namespace support; 1170 1171 if (DataBuffer.getBufferSize() < 8) 1172 return false; 1173 uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>( 1174 DataBuffer.getBufferStart()); 1175 // Verify that it's magical. 1176 return Magic == IndexedInstrProf::Magic; 1177 } 1178 1179 const unsigned char * 1180 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, 1181 const unsigned char *Cur, bool UseCS) { 1182 using namespace IndexedInstrProf; 1183 using namespace support; 1184 1185 if (Version >= IndexedInstrProf::Version4) { 1186 const IndexedInstrProf::Summary *SummaryInLE = 1187 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); 1188 uint64_t NFields = endian::byte_swap<uint64_t, llvm::endianness::little>( 1189 SummaryInLE->NumSummaryFields); 1190 uint64_t NEntries = endian::byte_swap<uint64_t, llvm::endianness::little>( 1191 SummaryInLE->NumCutoffEntries); 1192 uint32_t SummarySize = 1193 IndexedInstrProf::Summary::getSize(NFields, NEntries); 1194 std::unique_ptr<IndexedInstrProf::Summary> SummaryData = 1195 IndexedInstrProf::allocSummary(SummarySize); 1196 1197 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); 1198 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); 1199 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) 1200 Dst[I] = endian::byte_swap<uint64_t, llvm::endianness::little>(Src[I]); 1201 1202 SummaryEntryVector DetailedSummary; 1203 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) { 1204 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I); 1205 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, 1206 Ent.NumBlocks); 1207 } 1208 std::unique_ptr<llvm::ProfileSummary> &Summary = 1209 UseCS ? this->CS_Summary : this->Summary; 1210 1211 // initialize InstrProfSummary using the SummaryData from disk. 1212 Summary = std::make_unique<ProfileSummary>( 1213 UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr, 1214 DetailedSummary, SummaryData->get(Summary::TotalBlockCount), 1215 SummaryData->get(Summary::MaxBlockCount), 1216 SummaryData->get(Summary::MaxInternalBlockCount), 1217 SummaryData->get(Summary::MaxFunctionCount), 1218 SummaryData->get(Summary::TotalNumBlocks), 1219 SummaryData->get(Summary::TotalNumFunctions)); 1220 return Cur + SummarySize; 1221 } else { 1222 // The older versions do not support a profile summary. This just computes 1223 // an empty summary, which will not result in accurate hot/cold detection. 1224 // We would need to call addRecord for all NamedInstrProfRecords to get the 1225 // correct summary. However, this version is old (prior to early 2016) and 1226 // has not been supporting an accurate summary for several years. 1227 InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); 1228 Summary = Builder.getSummary(); 1229 return Cur; 1230 } 1231 } 1232 1233 Error IndexedMemProfReader::deserializeV2(const unsigned char *Start, 1234 const unsigned char *Ptr) { 1235 // The value returned from RecordTableGenerator.Emit. 1236 const uint64_t RecordTableOffset = 1237 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1238 // The offset in the stream right before invoking 1239 // FrameTableGenerator.Emit. 1240 const uint64_t FramePayloadOffset = 1241 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1242 // The value returned from FrameTableGenerator.Emit. 1243 const uint64_t FrameTableOffset = 1244 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1245 1246 // The offset in the stream right before invoking 1247 // CallStackTableGenerator.Emit. 1248 uint64_t CallStackPayloadOffset = 0; 1249 // The value returned from CallStackTableGenerator.Emit. 1250 uint64_t CallStackTableOffset = 0; 1251 if (Version >= memprof::Version2) { 1252 CallStackPayloadOffset = 1253 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1254 CallStackTableOffset = 1255 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1256 } 1257 1258 // Read the schema. 1259 auto SchemaOr = memprof::readMemProfSchema(Ptr); 1260 if (!SchemaOr) 1261 return SchemaOr.takeError(); 1262 Schema = SchemaOr.get(); 1263 1264 // Now initialize the table reader with a pointer into data buffer. 1265 MemProfRecordTable.reset(MemProfRecordHashTable::Create( 1266 /*Buckets=*/Start + RecordTableOffset, 1267 /*Payload=*/Ptr, 1268 /*Base=*/Start, memprof::RecordLookupTrait(Version, Schema))); 1269 1270 // Initialize the frame table reader with the payload and bucket offsets. 1271 MemProfFrameTable.reset(MemProfFrameHashTable::Create( 1272 /*Buckets=*/Start + FrameTableOffset, 1273 /*Payload=*/Start + FramePayloadOffset, 1274 /*Base=*/Start)); 1275 1276 if (Version >= memprof::Version2) 1277 MemProfCallStackTable.reset(MemProfCallStackHashTable::Create( 1278 /*Buckets=*/Start + CallStackTableOffset, 1279 /*Payload=*/Start + CallStackPayloadOffset, 1280 /*Base=*/Start)); 1281 1282 return Error::success(); 1283 } 1284 1285 Error IndexedMemProfReader::deserializeV3(const unsigned char *Start, 1286 const unsigned char *Ptr) { 1287 // The offset in the stream right before invoking 1288 // CallStackTableGenerator.Emit. 1289 const uint64_t CallStackPayloadOffset = 1290 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1291 // The offset in the stream right before invoking RecordTableGenerator.Emit. 1292 const uint64_t RecordPayloadOffset = 1293 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1294 // The value returned from RecordTableGenerator.Emit. 1295 const uint64_t RecordTableOffset = 1296 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1297 1298 // Read the schema. 1299 auto SchemaOr = memprof::readMemProfSchema(Ptr); 1300 if (!SchemaOr) 1301 return SchemaOr.takeError(); 1302 Schema = SchemaOr.get(); 1303 1304 FrameBase = Ptr; 1305 CallStackBase = Start + CallStackPayloadOffset; 1306 1307 // Compute the number of elements in the radix tree array. Since we use this 1308 // to reserve enough bits in a BitVector, it's totally OK if we overestimate 1309 // this number a little bit because of padding just before the next section. 1310 RadixTreeSize = (RecordPayloadOffset - CallStackPayloadOffset) / 1311 sizeof(memprof::LinearFrameId); 1312 1313 // Now initialize the table reader with a pointer into data buffer. 1314 MemProfRecordTable.reset(MemProfRecordHashTable::Create( 1315 /*Buckets=*/Start + RecordTableOffset, 1316 /*Payload=*/Start + RecordPayloadOffset, 1317 /*Base=*/Start, memprof::RecordLookupTrait(memprof::Version3, Schema))); 1318 1319 return Error::success(); 1320 } 1321 1322 Error IndexedMemProfReader::deserialize(const unsigned char *Start, 1323 uint64_t MemProfOffset) { 1324 const unsigned char *Ptr = Start + MemProfOffset; 1325 1326 // Read the MemProf version number. 1327 const uint64_t FirstWord = 1328 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1329 1330 if (FirstWord == memprof::Version2 || FirstWord == memprof::Version3) { 1331 // Everything is good. We can proceed to deserialize the rest. 1332 Version = static_cast<memprof::IndexedVersion>(FirstWord); 1333 } else { 1334 return make_error<InstrProfError>( 1335 instrprof_error::unsupported_version, 1336 formatv("MemProf version {} not supported; " 1337 "requires version between {} and {}, inclusive", 1338 FirstWord, memprof::MinimumSupportedVersion, 1339 memprof::MaximumSupportedVersion)); 1340 } 1341 1342 switch (Version) { 1343 case memprof::Version2: 1344 if (Error E = deserializeV2(Start, Ptr)) 1345 return E; 1346 break; 1347 case memprof::Version3: 1348 if (Error E = deserializeV3(Start, Ptr)) 1349 return E; 1350 break; 1351 } 1352 1353 return Error::success(); 1354 } 1355 1356 Error IndexedInstrProfReader::readHeader() { 1357 using namespace support; 1358 1359 const unsigned char *Start = 1360 (const unsigned char *)DataBuffer->getBufferStart(); 1361 const unsigned char *Cur = Start; 1362 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) 1363 return error(instrprof_error::truncated); 1364 1365 auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start); 1366 if (!HeaderOr) 1367 return HeaderOr.takeError(); 1368 1369 const IndexedInstrProf::Header *Header = &HeaderOr.get(); 1370 Cur += Header->size(); 1371 1372 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur, 1373 /* UseCS */ false); 1374 if (Header->Version & VARIANT_MASK_CSIR_PROF) 1375 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur, 1376 /* UseCS */ true); 1377 // Read the hash type and start offset. 1378 IndexedInstrProf::HashT HashType = 1379 static_cast<IndexedInstrProf::HashT>(Header->HashType); 1380 if (HashType > IndexedInstrProf::HashT::Last) 1381 return error(instrprof_error::unsupported_hash_type); 1382 1383 // The hash table with profile counts comes next. 1384 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>( 1385 Start + Header->HashOffset, Cur, Start, HashType, Header->Version); 1386 1387 // The MemProfOffset field in the header is only valid when the format 1388 // version is higher than 8 (when it was introduced). 1389 if (Header->getIndexedProfileVersion() >= 8 && 1390 Header->Version & VARIANT_MASK_MEMPROF) { 1391 if (Error E = MemProfReader.deserialize(Start, Header->MemProfOffset)) 1392 return E; 1393 } 1394 1395 // BinaryIdOffset field in the header is only valid when the format version 1396 // is higher than 9 (when it was introduced). 1397 if (Header->getIndexedProfileVersion() >= 9) { 1398 const unsigned char *Ptr = Start + Header->BinaryIdOffset; 1399 // Read binary ids size. 1400 uint64_t BinaryIdsSize = 1401 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1402 if (BinaryIdsSize % sizeof(uint64_t)) 1403 return error(instrprof_error::bad_header); 1404 // Set the binary ids start. 1405 BinaryIdsBuffer = ArrayRef<uint8_t>(Ptr, BinaryIdsSize); 1406 if (Ptr > (const unsigned char *)DataBuffer->getBufferEnd()) 1407 return make_error<InstrProfError>(instrprof_error::malformed, 1408 "corrupted binary ids"); 1409 } 1410 1411 if (Header->getIndexedProfileVersion() >= 12) { 1412 const unsigned char *Ptr = Start + Header->VTableNamesOffset; 1413 1414 uint64_t CompressedVTableNamesLen = 1415 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1416 1417 // Writer first writes the length of compressed string, and then the actual 1418 // content. 1419 const char *VTableNamePtr = (const char *)Ptr; 1420 if (VTableNamePtr > (const char *)DataBuffer->getBufferEnd()) 1421 return make_error<InstrProfError>(instrprof_error::truncated); 1422 1423 VTableName = StringRef(VTableNamePtr, CompressedVTableNamesLen); 1424 } 1425 1426 if (Header->getIndexedProfileVersion() >= 10 && 1427 Header->Version & VARIANT_MASK_TEMPORAL_PROF) { 1428 const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset; 1429 const auto *PtrEnd = (const unsigned char *)DataBuffer->getBufferEnd(); 1430 // Expect at least two 64 bit fields: NumTraces, and TraceStreamSize 1431 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd) 1432 return error(instrprof_error::truncated); 1433 const uint64_t NumTraces = 1434 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1435 TemporalProfTraceStreamSize = 1436 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1437 for (unsigned i = 0; i < NumTraces; i++) { 1438 // Expect at least two 64 bit fields: Weight and NumFunctions 1439 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd) 1440 return error(instrprof_error::truncated); 1441 TemporalProfTraceTy Trace; 1442 Trace.Weight = 1443 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1444 const uint64_t NumFunctions = 1445 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1446 // Expect at least NumFunctions 64 bit fields 1447 if (Ptr + NumFunctions * sizeof(uint64_t) > PtrEnd) 1448 return error(instrprof_error::truncated); 1449 for (unsigned j = 0; j < NumFunctions; j++) { 1450 const uint64_t NameRef = 1451 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); 1452 Trace.FunctionNameRefs.push_back(NameRef); 1453 } 1454 TemporalProfTraces.push_back(std::move(Trace)); 1455 } 1456 } 1457 1458 // Load the remapping table now if requested. 1459 if (RemappingBuffer) { 1460 Remapper = 1461 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>( 1462 std::move(RemappingBuffer), *IndexPtr); 1463 if (Error E = Remapper->populateRemappings()) 1464 return E; 1465 } else { 1466 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr); 1467 } 1468 Index = std::move(IndexPtr); 1469 1470 return success(); 1471 } 1472 1473 InstrProfSymtab &IndexedInstrProfReader::getSymtab() { 1474 if (Symtab) 1475 return *Symtab; 1476 1477 auto NewSymtab = std::make_unique<InstrProfSymtab>(); 1478 1479 if (Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) { 1480 auto [ErrCode, Msg] = InstrProfError::take(std::move(E)); 1481 consumeError(error(ErrCode, Msg)); 1482 } 1483 1484 // finalizeSymtab is called inside populateSymtab. 1485 if (Error E = Index->populateSymtab(*NewSymtab)) { 1486 auto [ErrCode, Msg] = InstrProfError::take(std::move(E)); 1487 consumeError(error(ErrCode, Msg)); 1488 } 1489 1490 Symtab = std::move(NewSymtab); 1491 return *Symtab; 1492 } 1493 1494 Expected<InstrProfRecord> IndexedInstrProfReader::getInstrProfRecord( 1495 StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName, 1496 uint64_t *MismatchedFuncSum) { 1497 ArrayRef<NamedInstrProfRecord> Data; 1498 uint64_t FuncSum = 0; 1499 auto Err = Remapper->getRecords(FuncName, Data); 1500 if (Err) { 1501 // If we don't find FuncName, try DeprecatedFuncName to handle profiles 1502 // built by older compilers. 1503 auto Err2 = 1504 handleErrors(std::move(Err), [&](const InstrProfError &IE) -> Error { 1505 if (IE.get() != instrprof_error::unknown_function) 1506 return make_error<InstrProfError>(IE); 1507 if (auto Err = Remapper->getRecords(DeprecatedFuncName, Data)) 1508 return Err; 1509 return Error::success(); 1510 }); 1511 if (Err2) 1512 return std::move(Err2); 1513 } 1514 // Found it. Look for counters with the right hash. 1515 1516 // A flag to indicate if the records are from the same type 1517 // of profile (i.e cs vs nocs). 1518 bool CSBitMatch = false; 1519 auto getFuncSum = [](ArrayRef<uint64_t> Counts) { 1520 uint64_t ValueSum = 0; 1521 for (uint64_t CountValue : Counts) { 1522 if (CountValue == (uint64_t)-1) 1523 continue; 1524 // Handle overflow -- if that happens, return max. 1525 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum) 1526 return std::numeric_limits<uint64_t>::max(); 1527 ValueSum += CountValue; 1528 } 1529 return ValueSum; 1530 }; 1531 1532 for (const NamedInstrProfRecord &I : Data) { 1533 // Check for a match and fill the vector if there is one. 1534 if (I.Hash == FuncHash) 1535 return std::move(I); 1536 if (NamedInstrProfRecord::hasCSFlagInHash(I.Hash) == 1537 NamedInstrProfRecord::hasCSFlagInHash(FuncHash)) { 1538 CSBitMatch = true; 1539 if (MismatchedFuncSum == nullptr) 1540 continue; 1541 FuncSum = std::max(FuncSum, getFuncSum(I.Counts)); 1542 } 1543 } 1544 if (CSBitMatch) { 1545 if (MismatchedFuncSum != nullptr) 1546 *MismatchedFuncSum = FuncSum; 1547 return error(instrprof_error::hash_mismatch); 1548 } 1549 return error(instrprof_error::unknown_function); 1550 } 1551 1552 static Expected<memprof::MemProfRecord> 1553 getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord, 1554 MemProfFrameHashTable &MemProfFrameTable, 1555 MemProfCallStackHashTable &MemProfCallStackTable) { 1556 memprof::FrameIdConverter<MemProfFrameHashTable> FrameIdConv( 1557 MemProfFrameTable); 1558 1559 memprof::CallStackIdConverter<MemProfCallStackHashTable> CSIdConv( 1560 MemProfCallStackTable, FrameIdConv); 1561 1562 memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv); 1563 1564 // Check that all call stack ids were successfully converted to call stacks. 1565 if (CSIdConv.LastUnmappedId) { 1566 return make_error<InstrProfError>( 1567 instrprof_error::hash_mismatch, 1568 "memprof call stack not found for call stack id " + 1569 Twine(*CSIdConv.LastUnmappedId)); 1570 } 1571 1572 // Check that all frame ids were successfully converted to frames. 1573 if (FrameIdConv.LastUnmappedId) { 1574 return make_error<InstrProfError>(instrprof_error::hash_mismatch, 1575 "memprof frame not found for frame id " + 1576 Twine(*FrameIdConv.LastUnmappedId)); 1577 } 1578 1579 return Record; 1580 } 1581 1582 static Expected<memprof::MemProfRecord> 1583 getMemProfRecordV3(const memprof::IndexedMemProfRecord &IndexedRecord, 1584 const unsigned char *FrameBase, 1585 const unsigned char *CallStackBase) { 1586 memprof::LinearFrameIdConverter FrameIdConv(FrameBase); 1587 memprof::LinearCallStackIdConverter CSIdConv(CallStackBase, FrameIdConv); 1588 memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv); 1589 return Record; 1590 } 1591 1592 Expected<memprof::MemProfRecord> 1593 IndexedMemProfReader::getMemProfRecord(const uint64_t FuncNameHash) const { 1594 // TODO: Add memprof specific errors. 1595 if (MemProfRecordTable == nullptr) 1596 return make_error<InstrProfError>(instrprof_error::invalid_prof, 1597 "no memprof data available in profile"); 1598 auto Iter = MemProfRecordTable->find(FuncNameHash); 1599 if (Iter == MemProfRecordTable->end()) 1600 return make_error<InstrProfError>( 1601 instrprof_error::unknown_function, 1602 "memprof record not found for function hash " + Twine(FuncNameHash)); 1603 1604 const memprof::IndexedMemProfRecord &IndexedRecord = *Iter; 1605 switch (Version) { 1606 case memprof::Version2: 1607 assert(MemProfFrameTable && "MemProfFrameTable must be available"); 1608 assert(MemProfCallStackTable && "MemProfCallStackTable must be available"); 1609 return getMemProfRecordV2(IndexedRecord, *MemProfFrameTable, 1610 *MemProfCallStackTable); 1611 case memprof::Version3: 1612 assert(!MemProfFrameTable && "MemProfFrameTable must not be available"); 1613 assert(!MemProfCallStackTable && 1614 "MemProfCallStackTable must not be available"); 1615 assert(FrameBase && "FrameBase must be available"); 1616 assert(CallStackBase && "CallStackBase must be available"); 1617 return getMemProfRecordV3(IndexedRecord, FrameBase, CallStackBase); 1618 } 1619 1620 return make_error<InstrProfError>( 1621 instrprof_error::unsupported_version, 1622 formatv("MemProf version {} not supported; " 1623 "requires version between {} and {}, inclusive", 1624 Version, memprof::MinimumSupportedVersion, 1625 memprof::MaximumSupportedVersion)); 1626 } 1627 1628 DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>> 1629 IndexedMemProfReader::getMemProfCallerCalleePairs() const { 1630 assert(MemProfRecordTable); 1631 assert(Version == memprof::Version3); 1632 1633 memprof::LinearFrameIdConverter FrameIdConv(FrameBase); 1634 memprof::CallerCalleePairExtractor Extractor(CallStackBase, FrameIdConv, 1635 RadixTreeSize); 1636 1637 // The set of linear call stack IDs that we need to traverse from. We expect 1638 // the set to be dense, so we use a BitVector. 1639 BitVector Worklist(RadixTreeSize); 1640 1641 // Collect the set of linear call stack IDs. Since we expect a lot of 1642 // duplicates, we first collect them in the form of a bit vector before 1643 // processing them. 1644 for (const memprof::IndexedMemProfRecord &IndexedRecord : 1645 MemProfRecordTable->data()) { 1646 for (const memprof::IndexedAllocationInfo &IndexedAI : 1647 IndexedRecord.AllocSites) 1648 Worklist.set(IndexedAI.CSId); 1649 } 1650 1651 // Collect caller-callee pairs for each linear call stack ID in Worklist. 1652 for (unsigned CS : Worklist.set_bits()) 1653 Extractor(CS); 1654 1655 DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>> Pairs = 1656 std::move(Extractor.CallerCalleePairs); 1657 1658 // Sort each call list by the source location. 1659 for (auto &[CallerGUID, CallList] : Pairs) { 1660 llvm::sort(CallList); 1661 CallList.erase(llvm::unique(CallList), CallList.end()); 1662 } 1663 1664 return Pairs; 1665 } 1666 1667 memprof::AllMemProfData IndexedMemProfReader::getAllMemProfData() const { 1668 memprof::AllMemProfData AllMemProfData; 1669 AllMemProfData.HeapProfileRecords.reserve( 1670 MemProfRecordTable->getNumEntries()); 1671 for (uint64_t Key : MemProfRecordTable->keys()) { 1672 auto Record = getMemProfRecord(Key); 1673 if (Record.takeError()) 1674 continue; 1675 memprof::GUIDMemProfRecordPair Pair; 1676 Pair.GUID = Key; 1677 Pair.Record = std::move(*Record); 1678 AllMemProfData.HeapProfileRecords.push_back(std::move(Pair)); 1679 } 1680 return AllMemProfData; 1681 } 1682 1683 Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, 1684 uint64_t FuncHash, 1685 std::vector<uint64_t> &Counts) { 1686 Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 1687 if (Error E = Record.takeError()) 1688 return error(std::move(E)); 1689 1690 Counts = Record.get().Counts; 1691 return success(); 1692 } 1693 1694 Error IndexedInstrProfReader::getFunctionBitmap(StringRef FuncName, 1695 uint64_t FuncHash, 1696 BitVector &Bitmap) { 1697 Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); 1698 if (Error E = Record.takeError()) 1699 return error(std::move(E)); 1700 1701 const auto &BitmapBytes = Record.get().BitmapBytes; 1702 size_t I = 0, E = BitmapBytes.size(); 1703 Bitmap.resize(E * CHAR_BIT); 1704 BitVector::apply( 1705 [&](auto X) { 1706 using XTy = decltype(X); 1707 alignas(XTy) uint8_t W[sizeof(X)]; 1708 size_t N = std::min(E - I, sizeof(W)); 1709 std::memset(W, 0, sizeof(W)); 1710 std::memcpy(W, &BitmapBytes[I], N); 1711 I += N; 1712 return support::endian::read<XTy, llvm::endianness::little, 1713 support::aligned>(W); 1714 }, 1715 Bitmap, Bitmap); 1716 assert(I == E); 1717 1718 return success(); 1719 } 1720 1721 Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { 1722 ArrayRef<NamedInstrProfRecord> Data; 1723 1724 Error E = Index->getRecords(Data); 1725 if (E) 1726 return error(std::move(E)); 1727 1728 Record = Data[RecordIndex++]; 1729 if (RecordIndex >= Data.size()) { 1730 Index->advanceToNextKey(); 1731 RecordIndex = 0; 1732 } 1733 return success(); 1734 } 1735 1736 Error IndexedInstrProfReader::readBinaryIds( 1737 std::vector<llvm::object::BuildID> &BinaryIds) { 1738 return readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer, BinaryIds, 1739 llvm::endianness::little); 1740 } 1741 1742 Error IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) { 1743 std::vector<llvm::object::BuildID> BinaryIds; 1744 if (Error E = readBinaryIds(BinaryIds)) 1745 return E; 1746 printBinaryIdsInternal(OS, BinaryIds); 1747 return Error::success(); 1748 } 1749 1750 void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) { 1751 uint64_t NumFuncs = 0; 1752 for (const auto &Func : *this) { 1753 if (isIRLevelProfile()) { 1754 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash); 1755 if (FuncIsCS != IsCS) 1756 continue; 1757 } 1758 Func.accumulateCounts(Sum); 1759 ++NumFuncs; 1760 } 1761 Sum.NumEntries = NumFuncs; 1762 } 1763