1 //===- SampleProfReader.cpp - Read LLVM sample profile data ---------------===// 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 implements the class that reads LLVM sample profiles. It 10 // supports three file formats: text, binary and gcov. 11 // 12 // The textual representation is useful for debugging and testing purposes. The 13 // binary representation is more compact, resulting in smaller file sizes. 14 // 15 // The gcov encoding is the one generated by GCC's AutoFDO profile creation 16 // tool (https://github.com/google/autofdo) 17 // 18 // All three encodings can be used interchangeably as an input sample profile. 19 // 20 //===----------------------------------------------------------------------===// 21 22 #include "llvm/ProfileData/SampleProfReader.h" 23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/IR/Module.h" 27 #include "llvm/IR/ProfileSummary.h" 28 #include "llvm/ProfileData/ProfileCommon.h" 29 #include "llvm/ProfileData/SampleProf.h" 30 #include "llvm/Support/CommandLine.h" 31 #include "llvm/Support/Compression.h" 32 #include "llvm/Support/ErrorOr.h" 33 #include "llvm/Support/JSON.h" 34 #include "llvm/Support/LEB128.h" 35 #include "llvm/Support/LineIterator.h" 36 #include "llvm/Support/MD5.h" 37 #include "llvm/Support/MemoryBuffer.h" 38 #include "llvm/Support/VirtualFileSystem.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <algorithm> 41 #include <cstddef> 42 #include <cstdint> 43 #include <limits> 44 #include <memory> 45 #include <system_error> 46 #include <vector> 47 48 using namespace llvm; 49 using namespace sampleprof; 50 51 #define DEBUG_TYPE "samplepgo-reader" 52 53 // This internal option specifies if the profile uses FS discriminators. 54 // It only applies to text, binary and compact binary format profiles. 55 // For ext-binary format profiles, the flag is set in the summary. 56 static cl::opt<bool> ProfileIsFSDisciminator( 57 "profile-isfs", cl::Hidden, cl::init(false), 58 cl::desc("Profile uses flow sensitive discriminators")); 59 60 /// Dump the function profile for \p FName. 61 /// 62 /// \param FContext Name + context of the function to print. 63 /// \param OS Stream to emit the output to. 64 void SampleProfileReader::dumpFunctionProfile(SampleContext FContext, 65 raw_ostream &OS) { 66 OS << "Function: " << FContext.toString() << ": " << Profiles[FContext]; 67 } 68 69 /// Dump all the function profiles found on stream \p OS. 70 void SampleProfileReader::dump(raw_ostream &OS) { 71 std::vector<NameFunctionSamples> V; 72 sortFuncProfiles(Profiles, V); 73 for (const auto &I : V) 74 dumpFunctionProfile(I.first, OS); 75 } 76 77 static void dumpFunctionProfileJson(const FunctionSamples &S, 78 json::OStream &JOS, bool TopLevel = false) { 79 auto DumpBody = [&](const BodySampleMap &BodySamples) { 80 for (const auto &I : BodySamples) { 81 const LineLocation &Loc = I.first; 82 const SampleRecord &Sample = I.second; 83 JOS.object([&] { 84 JOS.attribute("line", Loc.LineOffset); 85 if (Loc.Discriminator) 86 JOS.attribute("discriminator", Loc.Discriminator); 87 JOS.attribute("samples", Sample.getSamples()); 88 89 auto CallTargets = Sample.getSortedCallTargets(); 90 if (!CallTargets.empty()) { 91 JOS.attributeArray("calls", [&] { 92 for (const auto &J : CallTargets) { 93 JOS.object([&] { 94 JOS.attribute("function", J.first); 95 JOS.attribute("samples", J.second); 96 }); 97 } 98 }); 99 } 100 }); 101 } 102 }; 103 104 auto DumpCallsiteSamples = [&](const CallsiteSampleMap &CallsiteSamples) { 105 for (const auto &I : CallsiteSamples) 106 for (const auto &FS : I.second) { 107 const LineLocation &Loc = I.first; 108 const FunctionSamples &CalleeSamples = FS.second; 109 JOS.object([&] { 110 JOS.attribute("line", Loc.LineOffset); 111 if (Loc.Discriminator) 112 JOS.attribute("discriminator", Loc.Discriminator); 113 JOS.attributeArray( 114 "samples", [&] { dumpFunctionProfileJson(CalleeSamples, JOS); }); 115 }); 116 } 117 }; 118 119 JOS.object([&] { 120 JOS.attribute("name", S.getName()); 121 JOS.attribute("total", S.getTotalSamples()); 122 if (TopLevel) 123 JOS.attribute("head", S.getHeadSamples()); 124 125 const auto &BodySamples = S.getBodySamples(); 126 if (!BodySamples.empty()) 127 JOS.attributeArray("body", [&] { DumpBody(BodySamples); }); 128 129 const auto &CallsiteSamples = S.getCallsiteSamples(); 130 if (!CallsiteSamples.empty()) 131 JOS.attributeArray("callsites", 132 [&] { DumpCallsiteSamples(CallsiteSamples); }); 133 }); 134 } 135 136 /// Dump all the function profiles found on stream \p OS in the JSON format. 137 void SampleProfileReader::dumpJson(raw_ostream &OS) { 138 std::vector<NameFunctionSamples> V; 139 sortFuncProfiles(Profiles, V); 140 json::OStream JOS(OS, 2); 141 JOS.arrayBegin(); 142 for (const auto &F : V) 143 dumpFunctionProfileJson(*F.second, JOS, true); 144 JOS.arrayEnd(); 145 146 // Emit a newline character at the end as json::OStream doesn't emit one. 147 OS << "\n"; 148 } 149 150 /// Parse \p Input as function head. 151 /// 152 /// Parse one line of \p Input, and update function name in \p FName, 153 /// function's total sample count in \p NumSamples, function's entry 154 /// count in \p NumHeadSamples. 155 /// 156 /// \returns true if parsing is successful. 157 static bool ParseHead(const StringRef &Input, StringRef &FName, 158 uint64_t &NumSamples, uint64_t &NumHeadSamples) { 159 if (Input[0] == ' ') 160 return false; 161 size_t n2 = Input.rfind(':'); 162 size_t n1 = Input.rfind(':', n2 - 1); 163 FName = Input.substr(0, n1); 164 if (Input.substr(n1 + 1, n2 - n1 - 1).getAsInteger(10, NumSamples)) 165 return false; 166 if (Input.substr(n2 + 1).getAsInteger(10, NumHeadSamples)) 167 return false; 168 return true; 169 } 170 171 /// Returns true if line offset \p L is legal (only has 16 bits). 172 static bool isOffsetLegal(unsigned L) { return (L & 0xffff) == L; } 173 174 /// Parse \p Input that contains metadata. 175 /// Possible metadata: 176 /// - CFG Checksum information: 177 /// !CFGChecksum: 12345 178 /// - CFG Checksum information: 179 /// !Attributes: 1 180 /// Stores the FunctionHash (a.k.a. CFG Checksum) into \p FunctionHash. 181 static bool parseMetadata(const StringRef &Input, uint64_t &FunctionHash, 182 uint32_t &Attributes) { 183 if (Input.startswith("!CFGChecksum:")) { 184 StringRef CFGInfo = Input.substr(strlen("!CFGChecksum:")).trim(); 185 return !CFGInfo.getAsInteger(10, FunctionHash); 186 } 187 188 if (Input.startswith("!Attributes:")) { 189 StringRef Attrib = Input.substr(strlen("!Attributes:")).trim(); 190 return !Attrib.getAsInteger(10, Attributes); 191 } 192 193 return false; 194 } 195 196 enum class LineType { 197 CallSiteProfile, 198 BodyProfile, 199 Metadata, 200 }; 201 202 /// Parse \p Input as line sample. 203 /// 204 /// \param Input input line. 205 /// \param LineTy Type of this line. 206 /// \param Depth the depth of the inline stack. 207 /// \param NumSamples total samples of the line/inlined callsite. 208 /// \param LineOffset line offset to the start of the function. 209 /// \param Discriminator discriminator of the line. 210 /// \param TargetCountMap map from indirect call target to count. 211 /// \param FunctionHash the function's CFG hash, used by pseudo probe. 212 /// 213 /// returns true if parsing is successful. 214 static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth, 215 uint64_t &NumSamples, uint32_t &LineOffset, 216 uint32_t &Discriminator, StringRef &CalleeName, 217 DenseMap<StringRef, uint64_t> &TargetCountMap, 218 uint64_t &FunctionHash, uint32_t &Attributes) { 219 for (Depth = 0; Input[Depth] == ' '; Depth++) 220 ; 221 if (Depth == 0) 222 return false; 223 224 if (Input[Depth] == '!') { 225 LineTy = LineType::Metadata; 226 return parseMetadata(Input.substr(Depth), FunctionHash, Attributes); 227 } 228 229 size_t n1 = Input.find(':'); 230 StringRef Loc = Input.substr(Depth, n1 - Depth); 231 size_t n2 = Loc.find('.'); 232 if (n2 == StringRef::npos) { 233 if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset)) 234 return false; 235 Discriminator = 0; 236 } else { 237 if (Loc.substr(0, n2).getAsInteger(10, LineOffset)) 238 return false; 239 if (Loc.substr(n2 + 1).getAsInteger(10, Discriminator)) 240 return false; 241 } 242 243 StringRef Rest = Input.substr(n1 + 2); 244 if (isDigit(Rest[0])) { 245 LineTy = LineType::BodyProfile; 246 size_t n3 = Rest.find(' '); 247 if (n3 == StringRef::npos) { 248 if (Rest.getAsInteger(10, NumSamples)) 249 return false; 250 } else { 251 if (Rest.substr(0, n3).getAsInteger(10, NumSamples)) 252 return false; 253 } 254 // Find call targets and their sample counts. 255 // Note: In some cases, there are symbols in the profile which are not 256 // mangled. To accommodate such cases, use colon + integer pairs as the 257 // anchor points. 258 // An example: 259 // _M_construct<char *>:1000 string_view<std::allocator<char> >:437 260 // ":1000" and ":437" are used as anchor points so the string above will 261 // be interpreted as 262 // target: _M_construct<char *> 263 // count: 1000 264 // target: string_view<std::allocator<char> > 265 // count: 437 266 while (n3 != StringRef::npos) { 267 n3 += Rest.substr(n3).find_first_not_of(' '); 268 Rest = Rest.substr(n3); 269 n3 = Rest.find_first_of(':'); 270 if (n3 == StringRef::npos || n3 == 0) 271 return false; 272 273 StringRef Target; 274 uint64_t count, n4; 275 while (true) { 276 // Get the segment after the current colon. 277 StringRef AfterColon = Rest.substr(n3 + 1); 278 // Get the target symbol before the current colon. 279 Target = Rest.substr(0, n3); 280 // Check if the word after the current colon is an integer. 281 n4 = AfterColon.find_first_of(' '); 282 n4 = (n4 != StringRef::npos) ? n3 + n4 + 1 : Rest.size(); 283 StringRef WordAfterColon = Rest.substr(n3 + 1, n4 - n3 - 1); 284 if (!WordAfterColon.getAsInteger(10, count)) 285 break; 286 287 // Try to find the next colon. 288 uint64_t n5 = AfterColon.find_first_of(':'); 289 if (n5 == StringRef::npos) 290 return false; 291 n3 += n5 + 1; 292 } 293 294 // An anchor point is found. Save the {target, count} pair 295 TargetCountMap[Target] = count; 296 if (n4 == Rest.size()) 297 break; 298 // Change n3 to the next blank space after colon + integer pair. 299 n3 = n4; 300 } 301 } else { 302 LineTy = LineType::CallSiteProfile; 303 size_t n3 = Rest.find_last_of(':'); 304 CalleeName = Rest.substr(0, n3); 305 if (Rest.substr(n3 + 1).getAsInteger(10, NumSamples)) 306 return false; 307 } 308 return true; 309 } 310 311 /// Load samples from a text file. 312 /// 313 /// See the documentation at the top of the file for an explanation of 314 /// the expected format. 315 /// 316 /// \returns true if the file was loaded successfully, false otherwise. 317 std::error_code SampleProfileReaderText::readImpl() { 318 line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#'); 319 sampleprof_error Result = sampleprof_error::success; 320 321 InlineCallStack InlineStack; 322 uint32_t TopLevelProbeProfileCount = 0; 323 324 // DepthMetadata tracks whether we have processed metadata for the current 325 // top-level or nested function profile. 326 uint32_t DepthMetadata = 0; 327 328 ProfileIsFS = ProfileIsFSDisciminator; 329 FunctionSamples::ProfileIsFS = ProfileIsFS; 330 for (; !LineIt.is_at_eof(); ++LineIt) { 331 size_t pos = LineIt->find_first_not_of(' '); 332 if (pos == LineIt->npos || (*LineIt)[pos] == '#') 333 continue; 334 // Read the header of each function. 335 // 336 // Note that for function identifiers we are actually expecting 337 // mangled names, but we may not always get them. This happens when 338 // the compiler decides not to emit the function (e.g., it was inlined 339 // and removed). In this case, the binary will not have the linkage 340 // name for the function, so the profiler will emit the function's 341 // unmangled name, which may contain characters like ':' and '>' in its 342 // name (member functions, templates, etc). 343 // 344 // The only requirement we place on the identifier, then, is that it 345 // should not begin with a number. 346 if ((*LineIt)[0] != ' ') { 347 uint64_t NumSamples, NumHeadSamples; 348 StringRef FName; 349 if (!ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) { 350 reportError(LineIt.line_number(), 351 "Expected 'mangled_name:NUM:NUM', found " + *LineIt); 352 return sampleprof_error::malformed; 353 } 354 DepthMetadata = 0; 355 SampleContext FContext(FName, CSNameTable); 356 if (FContext.hasContext()) 357 ++CSProfileCount; 358 Profiles[FContext] = FunctionSamples(); 359 FunctionSamples &FProfile = Profiles[FContext]; 360 FProfile.setContext(FContext); 361 MergeResult(Result, FProfile.addTotalSamples(NumSamples)); 362 MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples)); 363 InlineStack.clear(); 364 InlineStack.push_back(&FProfile); 365 } else { 366 uint64_t NumSamples; 367 StringRef FName; 368 DenseMap<StringRef, uint64_t> TargetCountMap; 369 uint32_t Depth, LineOffset, Discriminator; 370 LineType LineTy; 371 uint64_t FunctionHash = 0; 372 uint32_t Attributes = 0; 373 if (!ParseLine(*LineIt, LineTy, Depth, NumSamples, LineOffset, 374 Discriminator, FName, TargetCountMap, FunctionHash, 375 Attributes)) { 376 reportError(LineIt.line_number(), 377 "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " + 378 *LineIt); 379 return sampleprof_error::malformed; 380 } 381 if (LineTy != LineType::Metadata && Depth == DepthMetadata) { 382 // Metadata must be put at the end of a function profile. 383 reportError(LineIt.line_number(), 384 "Found non-metadata after metadata: " + *LineIt); 385 return sampleprof_error::malformed; 386 } 387 388 // Here we handle FS discriminators. 389 Discriminator &= getDiscriminatorMask(); 390 391 while (InlineStack.size() > Depth) { 392 InlineStack.pop_back(); 393 } 394 switch (LineTy) { 395 case LineType::CallSiteProfile: { 396 FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt( 397 LineLocation(LineOffset, Discriminator))[std::string(FName)]; 398 FSamples.setName(FName); 399 MergeResult(Result, FSamples.addTotalSamples(NumSamples)); 400 InlineStack.push_back(&FSamples); 401 DepthMetadata = 0; 402 break; 403 } 404 case LineType::BodyProfile: { 405 while (InlineStack.size() > Depth) { 406 InlineStack.pop_back(); 407 } 408 FunctionSamples &FProfile = *InlineStack.back(); 409 for (const auto &name_count : TargetCountMap) { 410 MergeResult(Result, FProfile.addCalledTargetSamples( 411 LineOffset, Discriminator, name_count.first, 412 name_count.second)); 413 } 414 MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator, 415 NumSamples)); 416 break; 417 } 418 case LineType::Metadata: { 419 FunctionSamples &FProfile = *InlineStack.back(); 420 if (FunctionHash) { 421 FProfile.setFunctionHash(FunctionHash); 422 if (Depth == 1) 423 ++TopLevelProbeProfileCount; 424 } 425 FProfile.getContext().setAllAttributes(Attributes); 426 if (Attributes & (uint32_t)ContextShouldBeInlined) 427 ProfileIsPreInlined = true; 428 DepthMetadata = Depth; 429 break; 430 } 431 } 432 } 433 } 434 435 assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) && 436 "Cannot have both context-sensitive and regular profile"); 437 ProfileIsCS = (CSProfileCount > 0); 438 assert((TopLevelProbeProfileCount == 0 || 439 TopLevelProbeProfileCount == Profiles.size()) && 440 "Cannot have both probe-based profiles and regular profiles"); 441 ProfileIsProbeBased = (TopLevelProbeProfileCount > 0); 442 FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased; 443 FunctionSamples::ProfileIsCS = ProfileIsCS; 444 FunctionSamples::ProfileIsPreInlined = ProfileIsPreInlined; 445 446 if (Result == sampleprof_error::success) 447 computeSummary(); 448 449 return Result; 450 } 451 452 bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) { 453 bool result = false; 454 455 // Check that the first non-comment line is a valid function header. 456 line_iterator LineIt(Buffer, /*SkipBlanks=*/true, '#'); 457 if (!LineIt.is_at_eof()) { 458 if ((*LineIt)[0] != ' ') { 459 uint64_t NumSamples, NumHeadSamples; 460 StringRef FName; 461 result = ParseHead(*LineIt, FName, NumSamples, NumHeadSamples); 462 } 463 } 464 465 return result; 466 } 467 468 template <typename T> ErrorOr<T> SampleProfileReaderBinary::readNumber() { 469 unsigned NumBytesRead = 0; 470 std::error_code EC; 471 uint64_t Val = decodeULEB128(Data, &NumBytesRead); 472 473 if (Val > std::numeric_limits<T>::max()) 474 EC = sampleprof_error::malformed; 475 else if (Data + NumBytesRead > End) 476 EC = sampleprof_error::truncated; 477 else 478 EC = sampleprof_error::success; 479 480 if (EC) { 481 reportError(0, EC.message()); 482 return EC; 483 } 484 485 Data += NumBytesRead; 486 return static_cast<T>(Val); 487 } 488 489 ErrorOr<StringRef> SampleProfileReaderBinary::readString() { 490 std::error_code EC; 491 StringRef Str(reinterpret_cast<const char *>(Data)); 492 if (Data + Str.size() + 1 > End) { 493 EC = sampleprof_error::truncated; 494 reportError(0, EC.message()); 495 return EC; 496 } 497 498 Data += Str.size() + 1; 499 return Str; 500 } 501 502 template <typename T> 503 ErrorOr<T> SampleProfileReaderBinary::readUnencodedNumber() { 504 std::error_code EC; 505 506 if (Data + sizeof(T) > End) { 507 EC = sampleprof_error::truncated; 508 reportError(0, EC.message()); 509 return EC; 510 } 511 512 using namespace support; 513 T Val = endian::readNext<T, little, unaligned>(Data); 514 return Val; 515 } 516 517 template <typename T> 518 inline ErrorOr<uint32_t> SampleProfileReaderBinary::readStringIndex(T &Table) { 519 std::error_code EC; 520 auto Idx = readNumber<uint32_t>(); 521 if (std::error_code EC = Idx.getError()) 522 return EC; 523 if (*Idx >= Table.size()) 524 return sampleprof_error::truncated_name_table; 525 return *Idx; 526 } 527 528 ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() { 529 auto Idx = readStringIndex(NameTable); 530 if (std::error_code EC = Idx.getError()) 531 return EC; 532 533 return NameTable[*Idx]; 534 } 535 536 ErrorOr<SampleContext> SampleProfileReaderBinary::readSampleContextFromTable() { 537 auto FName(readStringFromTable()); 538 if (std::error_code EC = FName.getError()) 539 return EC; 540 return SampleContext(*FName); 541 } 542 543 ErrorOr<StringRef> SampleProfileReaderExtBinaryBase::readStringFromTable() { 544 if (!FixedLengthMD5) 545 return SampleProfileReaderBinary::readStringFromTable(); 546 547 // read NameTable index. 548 auto Idx = readStringIndex(NameTable); 549 if (std::error_code EC = Idx.getError()) 550 return EC; 551 552 // Check whether the name to be accessed has been accessed before, 553 // if not, read it from memory directly. 554 StringRef &SR = NameTable[*Idx]; 555 if (SR.empty()) { 556 const uint8_t *SavedData = Data; 557 Data = MD5NameMemStart + ((*Idx) * sizeof(uint64_t)); 558 auto FID = readUnencodedNumber<uint64_t>(); 559 if (std::error_code EC = FID.getError()) 560 return EC; 561 // Save the string converted from uint64_t in MD5StringBuf. All the 562 // references to the name are all StringRefs refering to the string 563 // in MD5StringBuf. 564 MD5StringBuf->push_back(std::to_string(*FID)); 565 SR = MD5StringBuf->back(); 566 Data = SavedData; 567 } 568 return SR; 569 } 570 571 ErrorOr<StringRef> SampleProfileReaderCompactBinary::readStringFromTable() { 572 auto Idx = readStringIndex(NameTable); 573 if (std::error_code EC = Idx.getError()) 574 return EC; 575 576 return StringRef(NameTable[*Idx]); 577 } 578 579 std::error_code 580 SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { 581 auto NumSamples = readNumber<uint64_t>(); 582 if (std::error_code EC = NumSamples.getError()) 583 return EC; 584 FProfile.addTotalSamples(*NumSamples); 585 586 // Read the samples in the body. 587 auto NumRecords = readNumber<uint32_t>(); 588 if (std::error_code EC = NumRecords.getError()) 589 return EC; 590 591 for (uint32_t I = 0; I < *NumRecords; ++I) { 592 auto LineOffset = readNumber<uint64_t>(); 593 if (std::error_code EC = LineOffset.getError()) 594 return EC; 595 596 if (!isOffsetLegal(*LineOffset)) { 597 return std::error_code(); 598 } 599 600 auto Discriminator = readNumber<uint64_t>(); 601 if (std::error_code EC = Discriminator.getError()) 602 return EC; 603 604 auto NumSamples = readNumber<uint64_t>(); 605 if (std::error_code EC = NumSamples.getError()) 606 return EC; 607 608 auto NumCalls = readNumber<uint32_t>(); 609 if (std::error_code EC = NumCalls.getError()) 610 return EC; 611 612 // Here we handle FS discriminators: 613 uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask(); 614 615 for (uint32_t J = 0; J < *NumCalls; ++J) { 616 auto CalledFunction(readStringFromTable()); 617 if (std::error_code EC = CalledFunction.getError()) 618 return EC; 619 620 auto CalledFunctionSamples = readNumber<uint64_t>(); 621 if (std::error_code EC = CalledFunctionSamples.getError()) 622 return EC; 623 624 FProfile.addCalledTargetSamples(*LineOffset, DiscriminatorVal, 625 *CalledFunction, *CalledFunctionSamples); 626 } 627 628 FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples); 629 } 630 631 // Read all the samples for inlined function calls. 632 auto NumCallsites = readNumber<uint32_t>(); 633 if (std::error_code EC = NumCallsites.getError()) 634 return EC; 635 636 for (uint32_t J = 0; J < *NumCallsites; ++J) { 637 auto LineOffset = readNumber<uint64_t>(); 638 if (std::error_code EC = LineOffset.getError()) 639 return EC; 640 641 auto Discriminator = readNumber<uint64_t>(); 642 if (std::error_code EC = Discriminator.getError()) 643 return EC; 644 645 auto FName(readStringFromTable()); 646 if (std::error_code EC = FName.getError()) 647 return EC; 648 649 // Here we handle FS discriminators: 650 uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask(); 651 652 FunctionSamples &CalleeProfile = FProfile.functionSamplesAt( 653 LineLocation(*LineOffset, DiscriminatorVal))[std::string(*FName)]; 654 CalleeProfile.setName(*FName); 655 if (std::error_code EC = readProfile(CalleeProfile)) 656 return EC; 657 } 658 659 return sampleprof_error::success; 660 } 661 662 std::error_code 663 SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) { 664 Data = Start; 665 auto NumHeadSamples = readNumber<uint64_t>(); 666 if (std::error_code EC = NumHeadSamples.getError()) 667 return EC; 668 669 ErrorOr<SampleContext> FContext(readSampleContextFromTable()); 670 if (std::error_code EC = FContext.getError()) 671 return EC; 672 673 Profiles[*FContext] = FunctionSamples(); 674 FunctionSamples &FProfile = Profiles[*FContext]; 675 FProfile.setContext(*FContext); 676 FProfile.addHeadSamples(*NumHeadSamples); 677 678 if (FContext->hasContext()) 679 CSProfileCount++; 680 681 if (std::error_code EC = readProfile(FProfile)) 682 return EC; 683 return sampleprof_error::success; 684 } 685 686 std::error_code SampleProfileReaderBinary::readImpl() { 687 ProfileIsFS = ProfileIsFSDisciminator; 688 FunctionSamples::ProfileIsFS = ProfileIsFS; 689 while (!at_eof()) { 690 if (std::error_code EC = readFuncProfile(Data)) 691 return EC; 692 } 693 694 return sampleprof_error::success; 695 } 696 697 ErrorOr<SampleContextFrames> 698 SampleProfileReaderExtBinaryBase::readContextFromTable() { 699 auto ContextIdx = readNumber<uint32_t>(); 700 if (std::error_code EC = ContextIdx.getError()) 701 return EC; 702 if (*ContextIdx >= CSNameTable->size()) 703 return sampleprof_error::truncated_name_table; 704 return (*CSNameTable)[*ContextIdx]; 705 } 706 707 ErrorOr<SampleContext> 708 SampleProfileReaderExtBinaryBase::readSampleContextFromTable() { 709 if (ProfileIsCS) { 710 auto FContext(readContextFromTable()); 711 if (std::error_code EC = FContext.getError()) 712 return EC; 713 return SampleContext(*FContext); 714 } else { 715 auto FName(readStringFromTable()); 716 if (std::error_code EC = FName.getError()) 717 return EC; 718 return SampleContext(*FName); 719 } 720 } 721 722 std::error_code SampleProfileReaderExtBinaryBase::readOneSection( 723 const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry) { 724 Data = Start; 725 End = Start + Size; 726 switch (Entry.Type) { 727 case SecProfSummary: 728 if (std::error_code EC = readSummary()) 729 return EC; 730 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial)) 731 Summary->setPartialProfile(true); 732 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext)) 733 FunctionSamples::ProfileIsCS = ProfileIsCS = true; 734 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagIsPreInlined)) 735 FunctionSamples::ProfileIsPreInlined = ProfileIsPreInlined = true; 736 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator)) 737 FunctionSamples::ProfileIsFS = ProfileIsFS = true; 738 break; 739 case SecNameTable: { 740 FixedLengthMD5 = 741 hasSecFlag(Entry, SecNameTableFlags::SecFlagFixedLengthMD5); 742 bool UseMD5 = hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name); 743 assert((!FixedLengthMD5 || UseMD5) && 744 "If FixedLengthMD5 is true, UseMD5 has to be true"); 745 FunctionSamples::HasUniqSuffix = 746 hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix); 747 if (std::error_code EC = readNameTableSec(UseMD5)) 748 return EC; 749 break; 750 } 751 case SecCSNameTable: { 752 if (std::error_code EC = readCSNameTableSec()) 753 return EC; 754 break; 755 } 756 case SecLBRProfile: 757 if (std::error_code EC = readFuncProfiles()) 758 return EC; 759 break; 760 case SecFuncOffsetTable: 761 FuncOffsetsOrdered = hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagOrdered); 762 if (std::error_code EC = readFuncOffsetTable()) 763 return EC; 764 break; 765 case SecFuncMetadata: { 766 ProfileIsProbeBased = 767 hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagIsProbeBased); 768 FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased; 769 bool HasAttribute = 770 hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagHasAttribute); 771 if (std::error_code EC = readFuncMetadata(HasAttribute)) 772 return EC; 773 break; 774 } 775 case SecProfileSymbolList: 776 if (std::error_code EC = readProfileSymbolList()) 777 return EC; 778 break; 779 default: 780 if (std::error_code EC = readCustomSection(Entry)) 781 return EC; 782 break; 783 } 784 return sampleprof_error::success; 785 } 786 787 bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule() { 788 if (!M) 789 return false; 790 FuncsToUse.clear(); 791 for (auto &F : *M) 792 FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F)); 793 return true; 794 } 795 796 std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() { 797 // If there are more than one FuncOffsetTable, the profile read associated 798 // with previous FuncOffsetTable has to be done before next FuncOffsetTable 799 // is read. 800 FuncOffsetTable.clear(); 801 802 auto Size = readNumber<uint64_t>(); 803 if (std::error_code EC = Size.getError()) 804 return EC; 805 806 FuncOffsetTable.reserve(*Size); 807 808 if (FuncOffsetsOrdered) { 809 OrderedFuncOffsets = 810 std::make_unique<std::vector<std::pair<SampleContext, uint64_t>>>(); 811 OrderedFuncOffsets->reserve(*Size); 812 } 813 814 for (uint64_t I = 0; I < *Size; ++I) { 815 auto FContext(readSampleContextFromTable()); 816 if (std::error_code EC = FContext.getError()) 817 return EC; 818 819 auto Offset = readNumber<uint64_t>(); 820 if (std::error_code EC = Offset.getError()) 821 return EC; 822 823 FuncOffsetTable[*FContext] = *Offset; 824 if (FuncOffsetsOrdered) 825 OrderedFuncOffsets->emplace_back(*FContext, *Offset); 826 } 827 828 return sampleprof_error::success; 829 } 830 831 std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() { 832 // Collect functions used by current module if the Reader has been 833 // given a module. 834 // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName 835 // which will query FunctionSamples::HasUniqSuffix, so it has to be 836 // called after FunctionSamples::HasUniqSuffix is set, i.e. after 837 // NameTable section is read. 838 bool LoadFuncsToBeUsed = collectFuncsFromModule(); 839 840 // When LoadFuncsToBeUsed is false, load all the function profiles. 841 const uint8_t *Start = Data; 842 if (!LoadFuncsToBeUsed) { 843 while (Data < End) { 844 if (std::error_code EC = readFuncProfile(Data)) 845 return EC; 846 } 847 assert(Data == End && "More data is read than expected"); 848 } else { 849 // Load function profiles on demand. 850 if (Remapper) { 851 for (auto Name : FuncsToUse) { 852 Remapper->insert(Name); 853 } 854 } 855 856 if (ProfileIsCS) { 857 DenseSet<uint64_t> FuncGuidsToUse; 858 if (useMD5()) { 859 for (auto Name : FuncsToUse) 860 FuncGuidsToUse.insert(Function::getGUID(Name)); 861 } 862 863 // For each function in current module, load all context profiles for 864 // the function as well as their callee contexts which can help profile 865 // guided importing for ThinLTO. This can be achieved by walking 866 // through an ordered context container, where contexts are laid out 867 // as if they were walked in preorder of a context trie. While 868 // traversing the trie, a link to the highest common ancestor node is 869 // kept so that all of its decendants will be loaded. 870 assert(OrderedFuncOffsets.get() && 871 "func offset table should always be sorted in CS profile"); 872 const SampleContext *CommonContext = nullptr; 873 for (const auto &NameOffset : *OrderedFuncOffsets) { 874 const auto &FContext = NameOffset.first; 875 auto FName = FContext.getName(); 876 // For function in the current module, keep its farthest ancestor 877 // context. This can be used to load itself and its child and 878 // sibling contexts. 879 if ((useMD5() && FuncGuidsToUse.count(std::stoull(FName.data()))) || 880 (!useMD5() && (FuncsToUse.count(FName) || 881 (Remapper && Remapper->exist(FName))))) { 882 if (!CommonContext || !CommonContext->IsPrefixOf(FContext)) 883 CommonContext = &FContext; 884 } 885 886 if (CommonContext == &FContext || 887 (CommonContext && CommonContext->IsPrefixOf(FContext))) { 888 // Load profile for the current context which originated from 889 // the common ancestor. 890 const uint8_t *FuncProfileAddr = Start + NameOffset.second; 891 assert(FuncProfileAddr < End && "out of LBRProfile section"); 892 if (std::error_code EC = readFuncProfile(FuncProfileAddr)) 893 return EC; 894 } 895 } 896 } else { 897 if (useMD5()) { 898 for (auto Name : FuncsToUse) { 899 auto GUID = std::to_string(MD5Hash(Name)); 900 auto iter = FuncOffsetTable.find(StringRef(GUID)); 901 if (iter == FuncOffsetTable.end()) 902 continue; 903 const uint8_t *FuncProfileAddr = Start + iter->second; 904 assert(FuncProfileAddr < End && "out of LBRProfile section"); 905 if (std::error_code EC = readFuncProfile(FuncProfileAddr)) 906 return EC; 907 } 908 } else { 909 for (auto NameOffset : FuncOffsetTable) { 910 SampleContext FContext(NameOffset.first); 911 auto FuncName = FContext.getName(); 912 if (!FuncsToUse.count(FuncName) && 913 (!Remapper || !Remapper->exist(FuncName))) 914 continue; 915 const uint8_t *FuncProfileAddr = Start + NameOffset.second; 916 assert(FuncProfileAddr < End && "out of LBRProfile section"); 917 if (std::error_code EC = readFuncProfile(FuncProfileAddr)) 918 return EC; 919 } 920 } 921 } 922 Data = End; 923 } 924 assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) && 925 "Cannot have both context-sensitive and regular profile"); 926 assert((!CSProfileCount || ProfileIsCS) && 927 "Section flag should be consistent with actual profile"); 928 return sampleprof_error::success; 929 } 930 931 std::error_code SampleProfileReaderExtBinaryBase::readProfileSymbolList() { 932 if (!ProfSymList) 933 ProfSymList = std::make_unique<ProfileSymbolList>(); 934 935 if (std::error_code EC = ProfSymList->read(Data, End - Data)) 936 return EC; 937 938 Data = End; 939 return sampleprof_error::success; 940 } 941 942 std::error_code SampleProfileReaderExtBinaryBase::decompressSection( 943 const uint8_t *SecStart, const uint64_t SecSize, 944 const uint8_t *&DecompressBuf, uint64_t &DecompressBufSize) { 945 Data = SecStart; 946 End = SecStart + SecSize; 947 auto DecompressSize = readNumber<uint64_t>(); 948 if (std::error_code EC = DecompressSize.getError()) 949 return EC; 950 DecompressBufSize = *DecompressSize; 951 952 auto CompressSize = readNumber<uint64_t>(); 953 if (std::error_code EC = CompressSize.getError()) 954 return EC; 955 956 if (!llvm::compression::zlib::isAvailable()) 957 return sampleprof_error::zlib_unavailable; 958 959 uint8_t *Buffer = Allocator.Allocate<uint8_t>(DecompressBufSize); 960 size_t UCSize = DecompressBufSize; 961 llvm::Error E = compression::zlib::decompress(ArrayRef(Data, *CompressSize), 962 Buffer, UCSize); 963 if (E) 964 return sampleprof_error::uncompress_failed; 965 DecompressBuf = reinterpret_cast<const uint8_t *>(Buffer); 966 return sampleprof_error::success; 967 } 968 969 std::error_code SampleProfileReaderExtBinaryBase::readImpl() { 970 const uint8_t *BufStart = 971 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()); 972 973 for (auto &Entry : SecHdrTable) { 974 // Skip empty section. 975 if (!Entry.Size) 976 continue; 977 978 // Skip sections without context when SkipFlatProf is true. 979 if (SkipFlatProf && hasSecFlag(Entry, SecCommonFlags::SecFlagFlat)) 980 continue; 981 982 const uint8_t *SecStart = BufStart + Entry.Offset; 983 uint64_t SecSize = Entry.Size; 984 985 // If the section is compressed, decompress it into a buffer 986 // DecompressBuf before reading the actual data. The pointee of 987 // 'Data' will be changed to buffer hold by DecompressBuf 988 // temporarily when reading the actual data. 989 bool isCompressed = hasSecFlag(Entry, SecCommonFlags::SecFlagCompress); 990 if (isCompressed) { 991 const uint8_t *DecompressBuf; 992 uint64_t DecompressBufSize; 993 if (std::error_code EC = decompressSection( 994 SecStart, SecSize, DecompressBuf, DecompressBufSize)) 995 return EC; 996 SecStart = DecompressBuf; 997 SecSize = DecompressBufSize; 998 } 999 1000 if (std::error_code EC = readOneSection(SecStart, SecSize, Entry)) 1001 return EC; 1002 if (Data != SecStart + SecSize) 1003 return sampleprof_error::malformed; 1004 1005 // Change the pointee of 'Data' from DecompressBuf to original Buffer. 1006 if (isCompressed) { 1007 Data = BufStart + Entry.Offset; 1008 End = BufStart + Buffer->getBufferSize(); 1009 } 1010 } 1011 1012 return sampleprof_error::success; 1013 } 1014 1015 std::error_code SampleProfileReaderCompactBinary::readImpl() { 1016 // Collect functions used by current module if the Reader has been 1017 // given a module. 1018 bool LoadFuncsToBeUsed = collectFuncsFromModule(); 1019 ProfileIsFS = ProfileIsFSDisciminator; 1020 FunctionSamples::ProfileIsFS = ProfileIsFS; 1021 std::vector<uint64_t> OffsetsToUse; 1022 if (!LoadFuncsToBeUsed) { 1023 // load all the function profiles. 1024 for (auto FuncEntry : FuncOffsetTable) { 1025 OffsetsToUse.push_back(FuncEntry.second); 1026 } 1027 } else { 1028 // load function profiles on demand. 1029 for (auto Name : FuncsToUse) { 1030 auto GUID = std::to_string(MD5Hash(Name)); 1031 auto iter = FuncOffsetTable.find(StringRef(GUID)); 1032 if (iter == FuncOffsetTable.end()) 1033 continue; 1034 OffsetsToUse.push_back(iter->second); 1035 } 1036 } 1037 1038 for (auto Offset : OffsetsToUse) { 1039 const uint8_t *SavedData = Data; 1040 if (std::error_code EC = readFuncProfile( 1041 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) + 1042 Offset)) 1043 return EC; 1044 Data = SavedData; 1045 } 1046 return sampleprof_error::success; 1047 } 1048 1049 std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) { 1050 if (Magic == SPMagic()) 1051 return sampleprof_error::success; 1052 return sampleprof_error::bad_magic; 1053 } 1054 1055 std::error_code SampleProfileReaderExtBinary::verifySPMagic(uint64_t Magic) { 1056 if (Magic == SPMagic(SPF_Ext_Binary)) 1057 return sampleprof_error::success; 1058 return sampleprof_error::bad_magic; 1059 } 1060 1061 std::error_code 1062 SampleProfileReaderCompactBinary::verifySPMagic(uint64_t Magic) { 1063 if (Magic == SPMagic(SPF_Compact_Binary)) 1064 return sampleprof_error::success; 1065 return sampleprof_error::bad_magic; 1066 } 1067 1068 std::error_code SampleProfileReaderBinary::readNameTable() { 1069 auto Size = readNumber<uint32_t>(); 1070 if (std::error_code EC = Size.getError()) 1071 return EC; 1072 NameTable.reserve(*Size + NameTable.size()); 1073 for (uint32_t I = 0; I < *Size; ++I) { 1074 auto Name(readString()); 1075 if (std::error_code EC = Name.getError()) 1076 return EC; 1077 NameTable.push_back(*Name); 1078 } 1079 1080 return sampleprof_error::success; 1081 } 1082 1083 std::error_code SampleProfileReaderExtBinaryBase::readMD5NameTable() { 1084 auto Size = readNumber<uint64_t>(); 1085 if (std::error_code EC = Size.getError()) 1086 return EC; 1087 MD5StringBuf = std::make_unique<std::vector<std::string>>(); 1088 MD5StringBuf->reserve(*Size); 1089 if (FixedLengthMD5) { 1090 // Preallocate and initialize NameTable so we can check whether a name 1091 // index has been read before by checking whether the element in the 1092 // NameTable is empty, meanwhile readStringIndex can do the boundary 1093 // check using the size of NameTable. 1094 NameTable.resize(*Size + NameTable.size()); 1095 1096 MD5NameMemStart = Data; 1097 Data = Data + (*Size) * sizeof(uint64_t); 1098 return sampleprof_error::success; 1099 } 1100 NameTable.reserve(*Size); 1101 for (uint64_t I = 0; I < *Size; ++I) { 1102 auto FID = readNumber<uint64_t>(); 1103 if (std::error_code EC = FID.getError()) 1104 return EC; 1105 MD5StringBuf->push_back(std::to_string(*FID)); 1106 // NameTable is a vector of StringRef. Here it is pushing back a 1107 // StringRef initialized with the last string in MD5stringBuf. 1108 NameTable.push_back(MD5StringBuf->back()); 1109 } 1110 return sampleprof_error::success; 1111 } 1112 1113 std::error_code SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5) { 1114 if (IsMD5) 1115 return readMD5NameTable(); 1116 return SampleProfileReaderBinary::readNameTable(); 1117 } 1118 1119 // Read in the CS name table section, which basically contains a list of context 1120 // vectors. Each element of a context vector, aka a frame, refers to the 1121 // underlying raw function names that are stored in the name table, as well as 1122 // a callsite identifier that only makes sense for non-leaf frames. 1123 std::error_code SampleProfileReaderExtBinaryBase::readCSNameTableSec() { 1124 auto Size = readNumber<uint32_t>(); 1125 if (std::error_code EC = Size.getError()) 1126 return EC; 1127 1128 std::vector<SampleContextFrameVector> *PNameVec = 1129 new std::vector<SampleContextFrameVector>(); 1130 PNameVec->reserve(*Size); 1131 for (uint32_t I = 0; I < *Size; ++I) { 1132 PNameVec->emplace_back(SampleContextFrameVector()); 1133 auto ContextSize = readNumber<uint32_t>(); 1134 if (std::error_code EC = ContextSize.getError()) 1135 return EC; 1136 for (uint32_t J = 0; J < *ContextSize; ++J) { 1137 auto FName(readStringFromTable()); 1138 if (std::error_code EC = FName.getError()) 1139 return EC; 1140 auto LineOffset = readNumber<uint64_t>(); 1141 if (std::error_code EC = LineOffset.getError()) 1142 return EC; 1143 1144 if (!isOffsetLegal(*LineOffset)) 1145 return std::error_code(); 1146 1147 auto Discriminator = readNumber<uint64_t>(); 1148 if (std::error_code EC = Discriminator.getError()) 1149 return EC; 1150 1151 PNameVec->back().emplace_back( 1152 FName.get(), LineLocation(LineOffset.get(), Discriminator.get())); 1153 } 1154 } 1155 1156 // From this point the underlying object of CSNameTable should be immutable. 1157 CSNameTable.reset(PNameVec); 1158 return sampleprof_error::success; 1159 } 1160 1161 std::error_code 1162 1163 SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute, 1164 FunctionSamples *FProfile) { 1165 if (Data < End) { 1166 if (ProfileIsProbeBased) { 1167 auto Checksum = readNumber<uint64_t>(); 1168 if (std::error_code EC = Checksum.getError()) 1169 return EC; 1170 if (FProfile) 1171 FProfile->setFunctionHash(*Checksum); 1172 } 1173 1174 if (ProfileHasAttribute) { 1175 auto Attributes = readNumber<uint32_t>(); 1176 if (std::error_code EC = Attributes.getError()) 1177 return EC; 1178 if (FProfile) 1179 FProfile->getContext().setAllAttributes(*Attributes); 1180 } 1181 1182 if (!ProfileIsCS) { 1183 // Read all the attributes for inlined function calls. 1184 auto NumCallsites = readNumber<uint32_t>(); 1185 if (std::error_code EC = NumCallsites.getError()) 1186 return EC; 1187 1188 for (uint32_t J = 0; J < *NumCallsites; ++J) { 1189 auto LineOffset = readNumber<uint64_t>(); 1190 if (std::error_code EC = LineOffset.getError()) 1191 return EC; 1192 1193 auto Discriminator = readNumber<uint64_t>(); 1194 if (std::error_code EC = Discriminator.getError()) 1195 return EC; 1196 1197 auto FContext(readSampleContextFromTable()); 1198 if (std::error_code EC = FContext.getError()) 1199 return EC; 1200 1201 FunctionSamples *CalleeProfile = nullptr; 1202 if (FProfile) { 1203 CalleeProfile = const_cast<FunctionSamples *>( 1204 &FProfile->functionSamplesAt(LineLocation( 1205 *LineOffset, 1206 *Discriminator))[std::string(FContext.get().getName())]); 1207 } 1208 if (std::error_code EC = 1209 readFuncMetadata(ProfileHasAttribute, CalleeProfile)) 1210 return EC; 1211 } 1212 } 1213 } 1214 1215 return sampleprof_error::success; 1216 } 1217 1218 std::error_code 1219 SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute) { 1220 while (Data < End) { 1221 auto FContext(readSampleContextFromTable()); 1222 if (std::error_code EC = FContext.getError()) 1223 return EC; 1224 FunctionSamples *FProfile = nullptr; 1225 auto It = Profiles.find(*FContext); 1226 if (It != Profiles.end()) 1227 FProfile = &It->second; 1228 1229 if (std::error_code EC = readFuncMetadata(ProfileHasAttribute, FProfile)) 1230 return EC; 1231 } 1232 1233 assert(Data == End && "More data is read than expected"); 1234 return sampleprof_error::success; 1235 } 1236 1237 std::error_code SampleProfileReaderCompactBinary::readNameTable() { 1238 auto Size = readNumber<uint64_t>(); 1239 if (std::error_code EC = Size.getError()) 1240 return EC; 1241 NameTable.reserve(*Size); 1242 for (uint64_t I = 0; I < *Size; ++I) { 1243 auto FID = readNumber<uint64_t>(); 1244 if (std::error_code EC = FID.getError()) 1245 return EC; 1246 NameTable.push_back(std::to_string(*FID)); 1247 } 1248 return sampleprof_error::success; 1249 } 1250 1251 std::error_code 1252 SampleProfileReaderExtBinaryBase::readSecHdrTableEntry(uint32_t Idx) { 1253 SecHdrTableEntry Entry; 1254 auto Type = readUnencodedNumber<uint64_t>(); 1255 if (std::error_code EC = Type.getError()) 1256 return EC; 1257 Entry.Type = static_cast<SecType>(*Type); 1258 1259 auto Flags = readUnencodedNumber<uint64_t>(); 1260 if (std::error_code EC = Flags.getError()) 1261 return EC; 1262 Entry.Flags = *Flags; 1263 1264 auto Offset = readUnencodedNumber<uint64_t>(); 1265 if (std::error_code EC = Offset.getError()) 1266 return EC; 1267 Entry.Offset = *Offset; 1268 1269 auto Size = readUnencodedNumber<uint64_t>(); 1270 if (std::error_code EC = Size.getError()) 1271 return EC; 1272 Entry.Size = *Size; 1273 1274 Entry.LayoutIndex = Idx; 1275 SecHdrTable.push_back(std::move(Entry)); 1276 return sampleprof_error::success; 1277 } 1278 1279 std::error_code SampleProfileReaderExtBinaryBase::readSecHdrTable() { 1280 auto EntryNum = readUnencodedNumber<uint64_t>(); 1281 if (std::error_code EC = EntryNum.getError()) 1282 return EC; 1283 1284 for (uint64_t i = 0; i < (*EntryNum); i++) 1285 if (std::error_code EC = readSecHdrTableEntry(i)) 1286 return EC; 1287 1288 return sampleprof_error::success; 1289 } 1290 1291 std::error_code SampleProfileReaderExtBinaryBase::readHeader() { 1292 const uint8_t *BufStart = 1293 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()); 1294 Data = BufStart; 1295 End = BufStart + Buffer->getBufferSize(); 1296 1297 if (std::error_code EC = readMagicIdent()) 1298 return EC; 1299 1300 if (std::error_code EC = readSecHdrTable()) 1301 return EC; 1302 1303 return sampleprof_error::success; 1304 } 1305 1306 uint64_t SampleProfileReaderExtBinaryBase::getSectionSize(SecType Type) { 1307 uint64_t Size = 0; 1308 for (auto &Entry : SecHdrTable) { 1309 if (Entry.Type == Type) 1310 Size += Entry.Size; 1311 } 1312 return Size; 1313 } 1314 1315 uint64_t SampleProfileReaderExtBinaryBase::getFileSize() { 1316 // Sections in SecHdrTable is not necessarily in the same order as 1317 // sections in the profile because section like FuncOffsetTable needs 1318 // to be written after section LBRProfile but needs to be read before 1319 // section LBRProfile, so we cannot simply use the last entry in 1320 // SecHdrTable to calculate the file size. 1321 uint64_t FileSize = 0; 1322 for (auto &Entry : SecHdrTable) { 1323 FileSize = std::max(Entry.Offset + Entry.Size, FileSize); 1324 } 1325 return FileSize; 1326 } 1327 1328 static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) { 1329 std::string Flags; 1330 if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress)) 1331 Flags.append("{compressed,"); 1332 else 1333 Flags.append("{"); 1334 1335 if (hasSecFlag(Entry, SecCommonFlags::SecFlagFlat)) 1336 Flags.append("flat,"); 1337 1338 switch (Entry.Type) { 1339 case SecNameTable: 1340 if (hasSecFlag(Entry, SecNameTableFlags::SecFlagFixedLengthMD5)) 1341 Flags.append("fixlenmd5,"); 1342 else if (hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name)) 1343 Flags.append("md5,"); 1344 if (hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix)) 1345 Flags.append("uniq,"); 1346 break; 1347 case SecProfSummary: 1348 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial)) 1349 Flags.append("partial,"); 1350 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext)) 1351 Flags.append("context,"); 1352 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagIsPreInlined)) 1353 Flags.append("preInlined,"); 1354 if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator)) 1355 Flags.append("fs-discriminator,"); 1356 break; 1357 case SecFuncOffsetTable: 1358 if (hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagOrdered)) 1359 Flags.append("ordered,"); 1360 break; 1361 case SecFuncMetadata: 1362 if (hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagIsProbeBased)) 1363 Flags.append("probe,"); 1364 if (hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagHasAttribute)) 1365 Flags.append("attr,"); 1366 break; 1367 default: 1368 break; 1369 } 1370 char &last = Flags.back(); 1371 if (last == ',') 1372 last = '}'; 1373 else 1374 Flags.append("}"); 1375 return Flags; 1376 } 1377 1378 bool SampleProfileReaderExtBinaryBase::dumpSectionInfo(raw_ostream &OS) { 1379 uint64_t TotalSecsSize = 0; 1380 for (auto &Entry : SecHdrTable) { 1381 OS << getSecName(Entry.Type) << " - Offset: " << Entry.Offset 1382 << ", Size: " << Entry.Size << ", Flags: " << getSecFlagsStr(Entry) 1383 << "\n"; 1384 ; 1385 TotalSecsSize += Entry.Size; 1386 } 1387 uint64_t HeaderSize = SecHdrTable.front().Offset; 1388 assert(HeaderSize + TotalSecsSize == getFileSize() && 1389 "Size of 'header + sections' doesn't match the total size of profile"); 1390 1391 OS << "Header Size: " << HeaderSize << "\n"; 1392 OS << "Total Sections Size: " << TotalSecsSize << "\n"; 1393 OS << "File Size: " << getFileSize() << "\n"; 1394 return true; 1395 } 1396 1397 std::error_code SampleProfileReaderBinary::readMagicIdent() { 1398 // Read and check the magic identifier. 1399 auto Magic = readNumber<uint64_t>(); 1400 if (std::error_code EC = Magic.getError()) 1401 return EC; 1402 else if (std::error_code EC = verifySPMagic(*Magic)) 1403 return EC; 1404 1405 // Read the version number. 1406 auto Version = readNumber<uint64_t>(); 1407 if (std::error_code EC = Version.getError()) 1408 return EC; 1409 else if (*Version != SPVersion()) 1410 return sampleprof_error::unsupported_version; 1411 1412 return sampleprof_error::success; 1413 } 1414 1415 std::error_code SampleProfileReaderBinary::readHeader() { 1416 Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()); 1417 End = Data + Buffer->getBufferSize(); 1418 1419 if (std::error_code EC = readMagicIdent()) 1420 return EC; 1421 1422 if (std::error_code EC = readSummary()) 1423 return EC; 1424 1425 if (std::error_code EC = readNameTable()) 1426 return EC; 1427 return sampleprof_error::success; 1428 } 1429 1430 std::error_code SampleProfileReaderCompactBinary::readHeader() { 1431 SampleProfileReaderBinary::readHeader(); 1432 if (std::error_code EC = readFuncOffsetTable()) 1433 return EC; 1434 return sampleprof_error::success; 1435 } 1436 1437 std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() { 1438 auto TableOffset = readUnencodedNumber<uint64_t>(); 1439 if (std::error_code EC = TableOffset.getError()) 1440 return EC; 1441 1442 const uint8_t *SavedData = Data; 1443 const uint8_t *TableStart = 1444 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) + 1445 *TableOffset; 1446 Data = TableStart; 1447 1448 auto Size = readNumber<uint64_t>(); 1449 if (std::error_code EC = Size.getError()) 1450 return EC; 1451 1452 FuncOffsetTable.reserve(*Size); 1453 for (uint64_t I = 0; I < *Size; ++I) { 1454 auto FName(readStringFromTable()); 1455 if (std::error_code EC = FName.getError()) 1456 return EC; 1457 1458 auto Offset = readNumber<uint64_t>(); 1459 if (std::error_code EC = Offset.getError()) 1460 return EC; 1461 1462 FuncOffsetTable[*FName] = *Offset; 1463 } 1464 End = TableStart; 1465 Data = SavedData; 1466 return sampleprof_error::success; 1467 } 1468 1469 bool SampleProfileReaderCompactBinary::collectFuncsFromModule() { 1470 if (!M) 1471 return false; 1472 FuncsToUse.clear(); 1473 for (auto &F : *M) 1474 FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F)); 1475 return true; 1476 } 1477 1478 std::error_code SampleProfileReaderBinary::readSummaryEntry( 1479 std::vector<ProfileSummaryEntry> &Entries) { 1480 auto Cutoff = readNumber<uint64_t>(); 1481 if (std::error_code EC = Cutoff.getError()) 1482 return EC; 1483 1484 auto MinBlockCount = readNumber<uint64_t>(); 1485 if (std::error_code EC = MinBlockCount.getError()) 1486 return EC; 1487 1488 auto NumBlocks = readNumber<uint64_t>(); 1489 if (std::error_code EC = NumBlocks.getError()) 1490 return EC; 1491 1492 Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks); 1493 return sampleprof_error::success; 1494 } 1495 1496 std::error_code SampleProfileReaderBinary::readSummary() { 1497 auto TotalCount = readNumber<uint64_t>(); 1498 if (std::error_code EC = TotalCount.getError()) 1499 return EC; 1500 1501 auto MaxBlockCount = readNumber<uint64_t>(); 1502 if (std::error_code EC = MaxBlockCount.getError()) 1503 return EC; 1504 1505 auto MaxFunctionCount = readNumber<uint64_t>(); 1506 if (std::error_code EC = MaxFunctionCount.getError()) 1507 return EC; 1508 1509 auto NumBlocks = readNumber<uint64_t>(); 1510 if (std::error_code EC = NumBlocks.getError()) 1511 return EC; 1512 1513 auto NumFunctions = readNumber<uint64_t>(); 1514 if (std::error_code EC = NumFunctions.getError()) 1515 return EC; 1516 1517 auto NumSummaryEntries = readNumber<uint64_t>(); 1518 if (std::error_code EC = NumSummaryEntries.getError()) 1519 return EC; 1520 1521 std::vector<ProfileSummaryEntry> Entries; 1522 for (unsigned i = 0; i < *NumSummaryEntries; i++) { 1523 std::error_code EC = readSummaryEntry(Entries); 1524 if (EC != sampleprof_error::success) 1525 return EC; 1526 } 1527 Summary = std::make_unique<ProfileSummary>( 1528 ProfileSummary::PSK_Sample, Entries, *TotalCount, *MaxBlockCount, 0, 1529 *MaxFunctionCount, *NumBlocks, *NumFunctions); 1530 1531 return sampleprof_error::success; 1532 } 1533 1534 bool SampleProfileReaderRawBinary::hasFormat(const MemoryBuffer &Buffer) { 1535 const uint8_t *Data = 1536 reinterpret_cast<const uint8_t *>(Buffer.getBufferStart()); 1537 uint64_t Magic = decodeULEB128(Data); 1538 return Magic == SPMagic(); 1539 } 1540 1541 bool SampleProfileReaderExtBinary::hasFormat(const MemoryBuffer &Buffer) { 1542 const uint8_t *Data = 1543 reinterpret_cast<const uint8_t *>(Buffer.getBufferStart()); 1544 uint64_t Magic = decodeULEB128(Data); 1545 return Magic == SPMagic(SPF_Ext_Binary); 1546 } 1547 1548 bool SampleProfileReaderCompactBinary::hasFormat(const MemoryBuffer &Buffer) { 1549 const uint8_t *Data = 1550 reinterpret_cast<const uint8_t *>(Buffer.getBufferStart()); 1551 uint64_t Magic = decodeULEB128(Data); 1552 return Magic == SPMagic(SPF_Compact_Binary); 1553 } 1554 1555 std::error_code SampleProfileReaderGCC::skipNextWord() { 1556 uint32_t dummy; 1557 if (!GcovBuffer.readInt(dummy)) 1558 return sampleprof_error::truncated; 1559 return sampleprof_error::success; 1560 } 1561 1562 template <typename T> ErrorOr<T> SampleProfileReaderGCC::readNumber() { 1563 if (sizeof(T) <= sizeof(uint32_t)) { 1564 uint32_t Val; 1565 if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max()) 1566 return static_cast<T>(Val); 1567 } else if (sizeof(T) <= sizeof(uint64_t)) { 1568 uint64_t Val; 1569 if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max()) 1570 return static_cast<T>(Val); 1571 } 1572 1573 std::error_code EC = sampleprof_error::malformed; 1574 reportError(0, EC.message()); 1575 return EC; 1576 } 1577 1578 ErrorOr<StringRef> SampleProfileReaderGCC::readString() { 1579 StringRef Str; 1580 if (!GcovBuffer.readString(Str)) 1581 return sampleprof_error::truncated; 1582 return Str; 1583 } 1584 1585 std::error_code SampleProfileReaderGCC::readHeader() { 1586 // Read the magic identifier. 1587 if (!GcovBuffer.readGCDAFormat()) 1588 return sampleprof_error::unrecognized_format; 1589 1590 // Read the version number. Note - the GCC reader does not validate this 1591 // version, but the profile creator generates v704. 1592 GCOV::GCOVVersion version; 1593 if (!GcovBuffer.readGCOVVersion(version)) 1594 return sampleprof_error::unrecognized_format; 1595 1596 if (version != GCOV::V407) 1597 return sampleprof_error::unsupported_version; 1598 1599 // Skip the empty integer. 1600 if (std::error_code EC = skipNextWord()) 1601 return EC; 1602 1603 return sampleprof_error::success; 1604 } 1605 1606 std::error_code SampleProfileReaderGCC::readSectionTag(uint32_t Expected) { 1607 uint32_t Tag; 1608 if (!GcovBuffer.readInt(Tag)) 1609 return sampleprof_error::truncated; 1610 1611 if (Tag != Expected) 1612 return sampleprof_error::malformed; 1613 1614 if (std::error_code EC = skipNextWord()) 1615 return EC; 1616 1617 return sampleprof_error::success; 1618 } 1619 1620 std::error_code SampleProfileReaderGCC::readNameTable() { 1621 if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames)) 1622 return EC; 1623 1624 uint32_t Size; 1625 if (!GcovBuffer.readInt(Size)) 1626 return sampleprof_error::truncated; 1627 1628 for (uint32_t I = 0; I < Size; ++I) { 1629 StringRef Str; 1630 if (!GcovBuffer.readString(Str)) 1631 return sampleprof_error::truncated; 1632 Names.push_back(std::string(Str)); 1633 } 1634 1635 return sampleprof_error::success; 1636 } 1637 1638 std::error_code SampleProfileReaderGCC::readFunctionProfiles() { 1639 if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction)) 1640 return EC; 1641 1642 uint32_t NumFunctions; 1643 if (!GcovBuffer.readInt(NumFunctions)) 1644 return sampleprof_error::truncated; 1645 1646 InlineCallStack Stack; 1647 for (uint32_t I = 0; I < NumFunctions; ++I) 1648 if (std::error_code EC = readOneFunctionProfile(Stack, true, 0)) 1649 return EC; 1650 1651 computeSummary(); 1652 return sampleprof_error::success; 1653 } 1654 1655 std::error_code SampleProfileReaderGCC::readOneFunctionProfile( 1656 const InlineCallStack &InlineStack, bool Update, uint32_t Offset) { 1657 uint64_t HeadCount = 0; 1658 if (InlineStack.size() == 0) 1659 if (!GcovBuffer.readInt64(HeadCount)) 1660 return sampleprof_error::truncated; 1661 1662 uint32_t NameIdx; 1663 if (!GcovBuffer.readInt(NameIdx)) 1664 return sampleprof_error::truncated; 1665 1666 StringRef Name(Names[NameIdx]); 1667 1668 uint32_t NumPosCounts; 1669 if (!GcovBuffer.readInt(NumPosCounts)) 1670 return sampleprof_error::truncated; 1671 1672 uint32_t NumCallsites; 1673 if (!GcovBuffer.readInt(NumCallsites)) 1674 return sampleprof_error::truncated; 1675 1676 FunctionSamples *FProfile = nullptr; 1677 if (InlineStack.size() == 0) { 1678 // If this is a top function that we have already processed, do not 1679 // update its profile again. This happens in the presence of 1680 // function aliases. Since these aliases share the same function 1681 // body, there will be identical replicated profiles for the 1682 // original function. In this case, we simply not bother updating 1683 // the profile of the original function. 1684 FProfile = &Profiles[Name]; 1685 FProfile->addHeadSamples(HeadCount); 1686 if (FProfile->getTotalSamples() > 0) 1687 Update = false; 1688 } else { 1689 // Otherwise, we are reading an inlined instance. The top of the 1690 // inline stack contains the profile of the caller. Insert this 1691 // callee in the caller's CallsiteMap. 1692 FunctionSamples *CallerProfile = InlineStack.front(); 1693 uint32_t LineOffset = Offset >> 16; 1694 uint32_t Discriminator = Offset & 0xffff; 1695 FProfile = &CallerProfile->functionSamplesAt( 1696 LineLocation(LineOffset, Discriminator))[std::string(Name)]; 1697 } 1698 FProfile->setName(Name); 1699 1700 for (uint32_t I = 0; I < NumPosCounts; ++I) { 1701 uint32_t Offset; 1702 if (!GcovBuffer.readInt(Offset)) 1703 return sampleprof_error::truncated; 1704 1705 uint32_t NumTargets; 1706 if (!GcovBuffer.readInt(NumTargets)) 1707 return sampleprof_error::truncated; 1708 1709 uint64_t Count; 1710 if (!GcovBuffer.readInt64(Count)) 1711 return sampleprof_error::truncated; 1712 1713 // The line location is encoded in the offset as: 1714 // high 16 bits: line offset to the start of the function. 1715 // low 16 bits: discriminator. 1716 uint32_t LineOffset = Offset >> 16; 1717 uint32_t Discriminator = Offset & 0xffff; 1718 1719 InlineCallStack NewStack; 1720 NewStack.push_back(FProfile); 1721 llvm::append_range(NewStack, InlineStack); 1722 if (Update) { 1723 // Walk up the inline stack, adding the samples on this line to 1724 // the total sample count of the callers in the chain. 1725 for (auto *CallerProfile : NewStack) 1726 CallerProfile->addTotalSamples(Count); 1727 1728 // Update the body samples for the current profile. 1729 FProfile->addBodySamples(LineOffset, Discriminator, Count); 1730 } 1731 1732 // Process the list of functions called at an indirect call site. 1733 // These are all the targets that a function pointer (or virtual 1734 // function) resolved at runtime. 1735 for (uint32_t J = 0; J < NumTargets; J++) { 1736 uint32_t HistVal; 1737 if (!GcovBuffer.readInt(HistVal)) 1738 return sampleprof_error::truncated; 1739 1740 if (HistVal != HIST_TYPE_INDIR_CALL_TOPN) 1741 return sampleprof_error::malformed; 1742 1743 uint64_t TargetIdx; 1744 if (!GcovBuffer.readInt64(TargetIdx)) 1745 return sampleprof_error::truncated; 1746 StringRef TargetName(Names[TargetIdx]); 1747 1748 uint64_t TargetCount; 1749 if (!GcovBuffer.readInt64(TargetCount)) 1750 return sampleprof_error::truncated; 1751 1752 if (Update) 1753 FProfile->addCalledTargetSamples(LineOffset, Discriminator, 1754 TargetName, TargetCount); 1755 } 1756 } 1757 1758 // Process all the inlined callers into the current function. These 1759 // are all the callsites that were inlined into this function. 1760 for (uint32_t I = 0; I < NumCallsites; I++) { 1761 // The offset is encoded as: 1762 // high 16 bits: line offset to the start of the function. 1763 // low 16 bits: discriminator. 1764 uint32_t Offset; 1765 if (!GcovBuffer.readInt(Offset)) 1766 return sampleprof_error::truncated; 1767 InlineCallStack NewStack; 1768 NewStack.push_back(FProfile); 1769 llvm::append_range(NewStack, InlineStack); 1770 if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset)) 1771 return EC; 1772 } 1773 1774 return sampleprof_error::success; 1775 } 1776 1777 /// Read a GCC AutoFDO profile. 1778 /// 1779 /// This format is generated by the Linux Perf conversion tool at 1780 /// https://github.com/google/autofdo. 1781 std::error_code SampleProfileReaderGCC::readImpl() { 1782 assert(!ProfileIsFSDisciminator && "Gcc profiles not support FSDisciminator"); 1783 // Read the string table. 1784 if (std::error_code EC = readNameTable()) 1785 return EC; 1786 1787 // Read the source profile. 1788 if (std::error_code EC = readFunctionProfiles()) 1789 return EC; 1790 1791 return sampleprof_error::success; 1792 } 1793 1794 bool SampleProfileReaderGCC::hasFormat(const MemoryBuffer &Buffer) { 1795 StringRef Magic(reinterpret_cast<const char *>(Buffer.getBufferStart())); 1796 return Magic == "adcg*704"; 1797 } 1798 1799 void SampleProfileReaderItaniumRemapper::applyRemapping(LLVMContext &Ctx) { 1800 // If the reader uses MD5 to represent string, we can't remap it because 1801 // we don't know what the original function names were. 1802 if (Reader.useMD5()) { 1803 Ctx.diagnose(DiagnosticInfoSampleProfile( 1804 Reader.getBuffer()->getBufferIdentifier(), 1805 "Profile data remapping cannot be applied to profile data " 1806 "in compact format (original mangled names are not available).", 1807 DS_Warning)); 1808 return; 1809 } 1810 1811 // CSSPGO-TODO: Remapper is not yet supported. 1812 // We will need to remap the entire context string. 1813 assert(Remappings && "should be initialized while creating remapper"); 1814 for (auto &Sample : Reader.getProfiles()) { 1815 DenseSet<StringRef> NamesInSample; 1816 Sample.second.findAllNames(NamesInSample); 1817 for (auto &Name : NamesInSample) 1818 if (auto Key = Remappings->insert(Name)) 1819 NameMap.insert({Key, Name}); 1820 } 1821 1822 RemappingApplied = true; 1823 } 1824 1825 std::optional<StringRef> 1826 SampleProfileReaderItaniumRemapper::lookUpNameInProfile(StringRef Fname) { 1827 if (auto Key = Remappings->lookup(Fname)) 1828 return NameMap.lookup(Key); 1829 return std::nullopt; 1830 } 1831 1832 /// Prepare a memory buffer for the contents of \p Filename. 1833 /// 1834 /// \returns an error code indicating the status of the buffer. 1835 static ErrorOr<std::unique_ptr<MemoryBuffer>> 1836 setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) { 1837 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN() 1838 : FS.getBufferForFile(Filename); 1839 if (std::error_code EC = BufferOrErr.getError()) 1840 return EC; 1841 auto Buffer = std::move(BufferOrErr.get()); 1842 1843 return std::move(Buffer); 1844 } 1845 1846 /// Create a sample profile reader based on the format of the input file. 1847 /// 1848 /// \param Filename The file to open. 1849 /// 1850 /// \param C The LLVM context to use to emit diagnostics. 1851 /// 1852 /// \param P The FSDiscriminatorPass. 1853 /// 1854 /// \param RemapFilename The file used for profile remapping. 1855 /// 1856 /// \returns an error code indicating the status of the created reader. 1857 ErrorOr<std::unique_ptr<SampleProfileReader>> 1858 SampleProfileReader::create(const std::string Filename, LLVMContext &C, 1859 vfs::FileSystem &FS, FSDiscriminatorPass P, 1860 const std::string RemapFilename) { 1861 auto BufferOrError = setupMemoryBuffer(Filename, FS); 1862 if (std::error_code EC = BufferOrError.getError()) 1863 return EC; 1864 return create(BufferOrError.get(), C, FS, P, RemapFilename); 1865 } 1866 1867 /// Create a sample profile remapper from the given input, to remap the 1868 /// function names in the given profile data. 1869 /// 1870 /// \param Filename The file to open. 1871 /// 1872 /// \param Reader The profile reader the remapper is going to be applied to. 1873 /// 1874 /// \param C The LLVM context to use to emit diagnostics. 1875 /// 1876 /// \returns an error code indicating the status of the created reader. 1877 ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>> 1878 SampleProfileReaderItaniumRemapper::create(const std::string Filename, 1879 vfs::FileSystem &FS, 1880 SampleProfileReader &Reader, 1881 LLVMContext &C) { 1882 auto BufferOrError = setupMemoryBuffer(Filename, FS); 1883 if (std::error_code EC = BufferOrError.getError()) 1884 return EC; 1885 return create(BufferOrError.get(), Reader, C); 1886 } 1887 1888 /// Create a sample profile remapper from the given input, to remap the 1889 /// function names in the given profile data. 1890 /// 1891 /// \param B The memory buffer to create the reader from (assumes ownership). 1892 /// 1893 /// \param C The LLVM context to use to emit diagnostics. 1894 /// 1895 /// \param Reader The profile reader the remapper is going to be applied to. 1896 /// 1897 /// \returns an error code indicating the status of the created reader. 1898 ErrorOr<std::unique_ptr<SampleProfileReaderItaniumRemapper>> 1899 SampleProfileReaderItaniumRemapper::create(std::unique_ptr<MemoryBuffer> &B, 1900 SampleProfileReader &Reader, 1901 LLVMContext &C) { 1902 auto Remappings = std::make_unique<SymbolRemappingReader>(); 1903 if (Error E = Remappings->read(*B)) { 1904 handleAllErrors( 1905 std::move(E), [&](const SymbolRemappingParseError &ParseError) { 1906 C.diagnose(DiagnosticInfoSampleProfile(B->getBufferIdentifier(), 1907 ParseError.getLineNum(), 1908 ParseError.getMessage())); 1909 }); 1910 return sampleprof_error::malformed; 1911 } 1912 1913 return std::make_unique<SampleProfileReaderItaniumRemapper>( 1914 std::move(B), std::move(Remappings), Reader); 1915 } 1916 1917 /// Create a sample profile reader based on the format of the input data. 1918 /// 1919 /// \param B The memory buffer to create the reader from (assumes ownership). 1920 /// 1921 /// \param C The LLVM context to use to emit diagnostics. 1922 /// 1923 /// \param P The FSDiscriminatorPass. 1924 /// 1925 /// \param RemapFilename The file used for profile remapping. 1926 /// 1927 /// \returns an error code indicating the status of the created reader. 1928 ErrorOr<std::unique_ptr<SampleProfileReader>> 1929 SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C, 1930 vfs::FileSystem &FS, FSDiscriminatorPass P, 1931 const std::string RemapFilename) { 1932 std::unique_ptr<SampleProfileReader> Reader; 1933 if (SampleProfileReaderRawBinary::hasFormat(*B)) 1934 Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C)); 1935 else if (SampleProfileReaderExtBinary::hasFormat(*B)) 1936 Reader.reset(new SampleProfileReaderExtBinary(std::move(B), C)); 1937 else if (SampleProfileReaderCompactBinary::hasFormat(*B)) 1938 Reader.reset(new SampleProfileReaderCompactBinary(std::move(B), C)); 1939 else if (SampleProfileReaderGCC::hasFormat(*B)) 1940 Reader.reset(new SampleProfileReaderGCC(std::move(B), C)); 1941 else if (SampleProfileReaderText::hasFormat(*B)) 1942 Reader.reset(new SampleProfileReaderText(std::move(B), C)); 1943 else 1944 return sampleprof_error::unrecognized_format; 1945 1946 if (!RemapFilename.empty()) { 1947 auto ReaderOrErr = SampleProfileReaderItaniumRemapper::create( 1948 RemapFilename, FS, *Reader, C); 1949 if (std::error_code EC = ReaderOrErr.getError()) { 1950 std::string Msg = "Could not create remapper: " + EC.message(); 1951 C.diagnose(DiagnosticInfoSampleProfile(RemapFilename, Msg)); 1952 return EC; 1953 } 1954 Reader->Remapper = std::move(ReaderOrErr.get()); 1955 } 1956 1957 if (std::error_code EC = Reader->readHeader()) { 1958 return EC; 1959 } 1960 1961 Reader->setDiscriminatorMaskedBitFrom(P); 1962 1963 return std::move(Reader); 1964 } 1965 1966 // For text and GCC file formats, we compute the summary after reading the 1967 // profile. Binary format has the profile summary in its header. 1968 void SampleProfileReader::computeSummary() { 1969 SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); 1970 Summary = Builder.computeSummaryForProfiles(Profiles); 1971 } 1972