LLVM 24.0.0git
SampleProfReader.cpp
Go to the documentation of this file.
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
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallSet.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/IR/Module.h"
34#include "llvm/Support/JSON.h"
35#include "llvm/Support/LEB128.h"
37#include "llvm/Support/MD5.h"
42#include <algorithm>
43#include <cstddef>
44#include <cstdint>
45#include <cstring>
46#include <limits>
47#include <memory>
48#include <system_error>
49#include <vector>
50
51using namespace llvm;
52using namespace sampleprof;
53
54#define DEBUG_TYPE "samplepgo-reader"
55
56// This internal option specifies if the profile uses FS discriminators.
57// It only applies to text, and binary format profiles.
58// For ext-binary format profiles, the flag is set in the summary.
60 "profile-isfs", cl::Hidden, cl::init(false),
61 cl::desc("Profile uses flow sensitive discriminators"));
62
63static cl::opt<bool>
64 LazyLoadNameTable("sample-profile-lazy-load-name-table", cl::init(true),
66 cl::desc("Lazy load the name table from the profile."));
67
68/// Dump the function profile for \p FName.
69///
70/// \param FContext Name + context of the function to print.
71/// \param OS Stream to emit the output to.
73 raw_ostream &OS) {
74 OS << "Function: " << FS.getContext().toString() << ": " << FS;
75}
76
77/// Dump all the function profiles found on stream \p OS.
79 std::vector<NameFunctionSamples> V;
81 for (const auto &I : V)
82 dumpFunctionProfile(*I.second, OS);
83}
84
86 json::OStream &JOS, bool TopLevel = false) {
87 auto DumpBody = [&](const BodySampleMap &BodySamples) {
88 for (const auto &I : BodySamples) {
89 const LineLocation &Loc = I.first;
90 const SampleRecord &Sample = I.second;
91 JOS.object([&] {
92 JOS.attribute("line", Loc.LineOffset);
93 if (Loc.Discriminator)
94 JOS.attribute("discriminator", Loc.Discriminator);
95 JOS.attribute("samples", Sample.getSamples());
96
97 auto CallTargets = Sample.getSortedCallTargets();
98 if (!CallTargets.empty()) {
99 JOS.attributeArray("calls", [&] {
100 for (const auto &J : CallTargets) {
101 JOS.object([&] {
102 JOS.attribute("function", J.first.str());
103 JOS.attribute("samples", J.second);
104 });
105 }
106 });
107 }
108 });
109 }
110 };
111
112 auto DumpCallsiteSamples = [&](const CallsiteSampleMap &CallsiteSamples) {
113 for (const auto &I : CallsiteSamples)
114 for (const auto &FS : I.second) {
115 const LineLocation &Loc = I.first;
116 const FunctionSamples &CalleeSamples = FS.second;
117 JOS.object([&] {
118 JOS.attribute("line", Loc.LineOffset);
119 if (Loc.Discriminator)
120 JOS.attribute("discriminator", Loc.Discriminator);
121 JOS.attributeArray(
122 "samples", [&] { dumpFunctionProfileJson(CalleeSamples, JOS); });
123 });
124 }
125 };
126
127 JOS.object([&] {
128 JOS.attribute("name", S.getFunction().str());
129 JOS.attribute("total", S.getTotalSamples());
130 if (TopLevel)
131 JOS.attribute("head", S.getHeadSamples());
132
133 const auto &BodySamples = S.getBodySamples();
134 if (!BodySamples.empty())
135 JOS.attributeArray("body", [&] { DumpBody(BodySamples); });
136
137 const auto &CallsiteSamples = S.getCallsiteSamples();
138 if (!CallsiteSamples.empty())
139 JOS.attributeArray("callsites",
140 [&] { DumpCallsiteSamples(CallsiteSamples); });
141 });
142}
143
144/// Dump all the function profiles found on stream \p OS in the JSON format.
146 std::vector<NameFunctionSamples> V;
148 json::OStream JOS(OS, 2);
149 JOS.arrayBegin();
150 for (const auto &F : V)
151 dumpFunctionProfileJson(*F.second, JOS, true);
152 JOS.arrayEnd();
153
154 // Emit a newline character at the end as json::OStream doesn't emit one.
155 OS << "\n";
156}
157
158/// Parse \p Input as function head.
159///
160/// Parse one line of \p Input, and update function name in \p FName,
161/// function's total sample count in \p NumSamples, function's entry
162/// count in \p NumHeadSamples.
163///
164/// \returns true if parsing is successful.
165static bool ParseHead(const StringRef &Input, StringRef &FName,
166 uint64_t &NumSamples, uint64_t &NumHeadSamples) {
167 if (Input[0] == ' ')
168 return false;
169 size_t n2 = Input.rfind(':');
170 size_t n1 = Input.rfind(':', n2 - 1);
171 FName = Input.substr(0, n1);
172 if (Input.substr(n1 + 1, n2 - n1 - 1).getAsInteger(10, NumSamples))
173 return false;
174 if (Input.substr(n2 + 1).getAsInteger(10, NumHeadSamples))
175 return false;
176 return true;
177}
178
179/// Returns true if line offset \p L is legal (only has 16 bits).
180static bool isOffsetLegal(unsigned L) { return (L & 0xffff) == L; }
181
182/// Parse \p Input that contains metadata.
183/// Possible metadata:
184/// - CFG Checksum information:
185/// !CFGChecksum: 12345
186/// - CFG Checksum information:
187/// !Attributes: 1
188/// Stores the FunctionHash (a.k.a. CFG Checksum) into \p FunctionHash.
189static bool parseMetadata(const StringRef &Input, uint64_t &FunctionHash,
190 uint32_t &Attributes) {
191 if (Input.starts_with("!CFGChecksum:")) {
192 StringRef CFGInfo = Input.substr(strlen("!CFGChecksum:")).trim();
193 return !CFGInfo.getAsInteger(10, FunctionHash);
194 }
195
196 if (Input.starts_with("!Attributes:")) {
197 StringRef Attrib = Input.substr(strlen("!Attributes:")).trim();
198 return !Attrib.getAsInteger(10, Attributes);
199 }
200
201 return false;
202}
203
210
211// Parse `Input` as a white-space separated list of `vtable:count` pairs. An
212// example input line is `_ZTVbar:1471 _ZTVfoo:630`.
215 for (size_t Index = Input.find_first_not_of(' '); Index != StringRef::npos;) {
216 size_t ColonIndex = Input.find(':', Index);
217 if (ColonIndex == StringRef::npos)
218 return false; // No colon found, invalid format.
219 StringRef TypeName = Input.substr(Index, ColonIndex - Index);
220 // CountIndex is the start index of count.
221 size_t CountStartIndex = ColonIndex + 1;
222 // NextIndex is the start index after the 'target:count' pair.
223 size_t NextIndex = Input.find_first_of(' ', CountStartIndex);
225 if (Input.substr(CountStartIndex, NextIndex - CountStartIndex)
226 .getAsInteger(10, Count))
227 return false; // Invalid count.
228 // Error on duplicated type names in one line of input.
229 auto [Iter, Inserted] = TypeCountMap.insert({TypeName, Count});
230 if (!Inserted)
231 return false;
232 Index = (NextIndex == StringRef::npos)
234 : Input.find_first_not_of(' ', NextIndex);
235 }
236 return true;
237}
238
239/// Parse \p Input as line sample.
240///
241/// \param Input input line.
242/// \param LineTy Type of this line.
243/// \param Depth the depth of the inline stack.
244/// \param NumSamples total samples of the line/inlined callsite.
245/// \param LineOffset line offset to the start of the function.
246/// \param Discriminator discriminator of the line.
247/// \param TargetCountMap map from indirect call target to count.
248/// \param FunctionHash the function's CFG hash, used by pseudo probe.
249///
250/// returns true if parsing is successful.
251static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth,
252 uint64_t &NumSamples, uint32_t &LineOffset,
253 uint32_t &Discriminator, StringRef &CalleeName,
254 DenseMap<StringRef, uint64_t> &TargetCountMap,
256 uint64_t &FunctionHash, uint32_t &Attributes,
257 bool &IsFlat) {
258 for (Depth = 0; Input[Depth] == ' '; Depth++)
259 ;
260 if (Depth == 0)
261 return false;
262
263 if (Input[Depth] == '!') {
264 LineTy = LineType::Metadata;
265 // This metadata is only for manual inspection only. We already created a
266 // FunctionSamples and put it in the profile map, so there is no point
267 // to skip profiles even they have no use for ThinLTO.
268 if (Input == StringRef(" !Flat")) {
269 IsFlat = true;
270 return true;
271 }
272 return parseMetadata(Input.substr(Depth), FunctionHash, Attributes);
273 }
274
275 size_t n1 = Input.find(':');
276 StringRef Loc = Input.substr(Depth, n1 - Depth);
277 size_t n2 = Loc.find('.');
278 if (n2 == StringRef::npos) {
279 if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset))
280 return false;
281 Discriminator = 0;
282 } else {
283 if (Loc.substr(0, n2).getAsInteger(10, LineOffset))
284 return false;
285 if (Loc.substr(n2 + 1).getAsInteger(10, Discriminator))
286 return false;
287 }
288
289 StringRef Rest = Input.substr(n1 + 2);
290 if (isDigit(Rest[0])) {
291 LineTy = LineType::BodyProfile;
292 size_t n3 = Rest.find(' ');
293 if (n3 == StringRef::npos) {
294 if (Rest.getAsInteger(10, NumSamples))
295 return false;
296 } else {
297 if (Rest.substr(0, n3).getAsInteger(10, NumSamples))
298 return false;
299 }
300 // Find call targets and their sample counts.
301 // Note: In some cases, there are symbols in the profile which are not
302 // mangled. To accommodate such cases, use colon + integer pairs as the
303 // anchor points.
304 // An example:
305 // _M_construct<char *>:1000 string_view<std::allocator<char> >:437
306 // ":1000" and ":437" are used as anchor points so the string above will
307 // be interpreted as
308 // target: _M_construct<char *>
309 // count: 1000
310 // target: string_view<std::allocator<char> >
311 // count: 437
312 while (n3 != StringRef::npos) {
313 n3 += Rest.substr(n3).find_first_not_of(' ');
314 Rest = Rest.substr(n3);
315 n3 = Rest.find_first_of(':');
316 if (n3 == StringRef::npos || n3 == 0)
317 return false;
318
320 uint64_t count, n4;
321 while (true) {
322 // Get the segment after the current colon.
323 StringRef AfterColon = Rest.substr(n3 + 1);
324 // Get the target symbol before the current colon.
325 Target = Rest.substr(0, n3);
326 // Check if the word after the current colon is an integer.
327 n4 = AfterColon.find_first_of(' ');
328 n4 = (n4 != StringRef::npos) ? n3 + n4 + 1 : Rest.size();
329 StringRef WordAfterColon = Rest.substr(n3 + 1, n4 - n3 - 1);
330 if (!WordAfterColon.getAsInteger(10, count))
331 break;
332
333 // Try to find the next colon.
334 uint64_t n5 = AfterColon.find_first_of(':');
335 if (n5 == StringRef::npos)
336 return false;
337 n3 += n5 + 1;
338 }
339
340 // An anchor point is found. Save the {target, count} pair
341 TargetCountMap[Target] = count;
342 if (n4 == Rest.size())
343 break;
344 // Change n3 to the next blank space after colon + integer pair.
345 n3 = n4;
346 }
347 } else if (Rest.starts_with(kVTableProfPrefix)) {
349 return parseTypeCountMap(Rest.substr(strlen(kVTableProfPrefix)),
351 } else {
353 size_t n3 = Rest.find_last_of(':');
354 CalleeName = Rest.substr(0, n3);
355 if (Rest.substr(n3 + 1).getAsInteger(10, NumSamples))
356 return false;
357 }
358 return true;
359}
360
361/// Load samples from a text file.
362///
363/// See the documentation at the top of the file for an explanation of
364/// the expected format.
365///
366/// \returns true if the file was loaded successfully, false otherwise.
368 line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
370
371 InlineCallStack InlineStack;
372 uint32_t TopLevelProbeProfileCount = 0;
373
374 // DepthMetadata tracks whether we have processed metadata for the current
375 // top-level or nested function profile.
376 uint32_t DepthMetadata = 0;
377
378 std::vector<SampleContext *> FlatSamples;
379
382 for (; !LineIt.is_at_eof(); ++LineIt) {
383 size_t pos = LineIt->find_first_not_of(' ');
384 if (pos == LineIt->npos || (*LineIt)[pos] == '#')
385 continue;
386 // Read the header of each function.
387 //
388 // Note that for function identifiers we are actually expecting
389 // mangled names, but we may not always get them. This happens when
390 // the compiler decides not to emit the function (e.g., it was inlined
391 // and removed). In this case, the binary will not have the linkage
392 // name for the function, so the profiler will emit the function's
393 // unmangled name, which may contain characters like ':' and '>' in its
394 // name (member functions, templates, etc).
395 //
396 // The only requirement we place on the identifier, then, is that it
397 // should not begin with a number.
398 if ((*LineIt)[0] != ' ') {
399 uint64_t NumSamples, NumHeadSamples;
400 StringRef FName;
401 if (!ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) {
402 reportError(LineIt.line_number(),
403 "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
405 }
406 DepthMetadata = 0;
407 SampleContext FContext(FName, CSNameTable);
408 if (FContext.hasContext())
410 FunctionSamples &FProfile = Profiles.create(FContext);
411 mergeSampleProfErrors(Result, FProfile.addTotalSamples(NumSamples));
412 mergeSampleProfErrors(Result, FProfile.addHeadSamples(NumHeadSamples));
413 InlineStack.clear();
414 InlineStack.push_back(&FProfile);
415 } else {
416 uint64_t NumSamples;
417 StringRef FName;
418 DenseMap<StringRef, uint64_t> TargetCountMap;
420 uint32_t Depth, LineOffset, Discriminator;
422 uint64_t FunctionHash = 0;
423 uint32_t Attributes = 0;
424 bool IsFlat = false;
425 // TODO: Update ParseLine to return an error code instead of a bool and
426 // report it.
427 if (!ParseLine(*LineIt, LineTy, Depth, NumSamples, LineOffset,
428 Discriminator, FName, TargetCountMap, TypeCountMap,
429 FunctionHash, Attributes, IsFlat)) {
430 switch (LineTy) {
432 reportError(LineIt.line_number(),
433 "Cannot parse metadata: " + *LineIt);
434 break;
436 reportError(LineIt.line_number(),
437 "Expected 'vtables [mangled_vtable:NUM]+', found " +
438 *LineIt);
439 break;
440 default:
441 reportError(LineIt.line_number(),
442 "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
443 *LineIt);
444 }
446 }
447 if (LineTy != LineType::Metadata && Depth == DepthMetadata) {
448 // Metadata must be put at the end of a function profile.
449 reportError(LineIt.line_number(),
450 "Found non-metadata after metadata: " + *LineIt);
452 }
453
454 // Here we handle FS discriminators.
455 Discriminator &= getDiscriminatorMask();
456
457 while (InlineStack.size() > Depth) {
458 InlineStack.pop_back();
459 }
460 switch (LineTy) {
462 FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
463 LineLocation(LineOffset, Discriminator))[FunctionId(FName)];
464 FSamples.setFunction(FunctionId(FName));
465 mergeSampleProfErrors(Result, FSamples.addTotalSamples(NumSamples));
466 InlineStack.push_back(&FSamples);
467 DepthMetadata = 0;
468 break;
469 }
470
473 Result, InlineStack.back()->addCallsiteVTableTypeProfAt(
474 LineLocation(LineOffset, Discriminator), TypeCountMap));
475 break;
476 }
477
479 FunctionSamples &FProfile = *InlineStack.back();
480 for (const auto &name_count : TargetCountMap) {
482 LineOffset, Discriminator,
483 FunctionId(name_count.first),
484 name_count.second));
485 }
487 Result,
488 FProfile.addBodySamples(LineOffset, Discriminator, NumSamples));
489 break;
490 }
491 case LineType::Metadata: {
492 FunctionSamples &FProfile = *InlineStack.back();
493 if (FunctionHash) {
494 FProfile.setFunctionHash(FunctionHash);
495 if (Depth == 1)
496 ++TopLevelProbeProfileCount;
497 }
498 FProfile.getContext().setAllAttributes(Attributes);
499 if (Attributes & (uint32_t)ContextShouldBeInlined)
500 ProfileIsPreInlined = true;
501 DepthMetadata = Depth;
502 if (IsFlat) {
503 if (Depth == 1)
504 FlatSamples.push_back(&FProfile.getContext());
505 else
507 Buffer->getBufferIdentifier(), LineIt.line_number(),
508 "!Flat may only be used at top level function.", DS_Warning));
509 }
510 break;
511 }
512 }
513 }
514 }
515
516 // Honor the option to skip flat functions. Since they are already added to
517 // the profile map, remove them all here.
518 if (SkipFlatProf)
519 for (SampleContext *FlatSample : FlatSamples)
520 Profiles.erase(*FlatSample);
521
522 assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
523 "Cannot have both context-sensitive and regular profile");
525 assert((TopLevelProbeProfileCount == 0 ||
526 TopLevelProbeProfileCount == Profiles.size()) &&
527 "Cannot have both probe-based profiles and regular profiles");
528 ProfileIsProbeBased = (TopLevelProbeProfileCount > 0);
532
533 if (Result == sampleprof_error::success)
535
536 return Result;
537}
538
540 bool result = false;
541
542 // Check that the first non-comment line is a valid function header.
543 line_iterator LineIt(Buffer, /*SkipBlanks=*/true, '#');
544 if (!LineIt.is_at_eof()) {
545 if ((*LineIt)[0] != ' ') {
546 uint64_t NumSamples, NumHeadSamples;
547 StringRef FName;
548 result = ParseHead(*LineIt, FName, NumSamples, NumHeadSamples);
549 }
550 }
551
552 return result;
553}
554
555/// Emit a reader diagnostic for \p ProfError and return its error code.
556static std::error_code diagnoseReaderError(const SampleProfileReader &Reader,
557 sampleprof_error ProfError) {
558 std::error_code EC = ProfError;
559 Reader.reportError(0, EC.message());
560 return EC;
561}
562
564 if (Data >= End)
566
567 unsigned NumBytesRead = 0;
569 uint64_t Val = decodeULEB128(Data, &NumBytesRead, End, nullptr, &DecodeError);
570
571 // Preserve the distinction between incomplete input and an invalid value.
572 switch (DecodeError) {
574 break;
579 }
580
581 if (Val > std::numeric_limits<T>::max())
583
584 Data += NumBytesRead;
585 return static_cast<T>(Val);
586}
587
589 if (Data >= End)
591
592 const auto *Terminator = static_cast<const uint8_t *>(
593 std::memchr(Data, 0, static_cast<size_t>(End - Data)));
594 if (!Terminator)
596
597 StringRef Str(reinterpret_cast<const char *>(Data), Terminator - Data);
598 Data = Terminator + 1;
599 return Str;
600}
601
602template <typename T>
604 if (Data > End || static_cast<size_t>(End - Data) < sizeof(T))
606
607 using namespace support;
609 return Val;
610}
611
612template <typename T>
614 auto Idx = readNumber<size_t>();
615 if (std::error_code EC = Idx.getError())
616 return EC;
617 if (*Idx >= Table.size())
619 return *Idx;
620}
621
624 if (!NameTable)
626 auto Idx = readStringIndex(*NameTable);
627 if (std::error_code EC = Idx.getError())
628 return EC;
629 if (RetIdx)
630 *RetIdx = *Idx;
631 return (*NameTable)[*Idx];
632}
633
636 auto ContextIdx = readNumber<size_t>();
637 if (std::error_code EC = ContextIdx.getError())
638 return EC;
639 if (*ContextIdx >= CSNameTable.size())
641 if (RetIdx)
642 *RetIdx = *ContextIdx;
643 return CSNameTable[*ContextIdx];
644}
645
648 SampleContext Context;
649 size_t Idx;
650 if (ProfileIsCS) {
651 auto FContext(readContextFromTable(&Idx));
652 if (std::error_code EC = FContext.getError())
653 return EC;
654 Context = SampleContext(*FContext);
655 } else {
656 auto FName(readStringFromTable(&Idx));
657 if (std::error_code EC = FName.getError())
658 return EC;
659 Context = SampleContext(*FName);
660 }
661 // Since MD5SampleContextStart may point to the profile's file data, need to
662 // make sure it is reading the same value on big endian CPU.
664 // Lazy computing of hash value, write back to the table to cache it. Only
665 // compute the context's hash value if it is being referenced for the first
666 // time.
667 if (Hash == 0) {
669 Hash = Context.getHashCode();
671 }
672 return std::make_pair(Context, Hash);
673}
674
675std::error_code
677 auto NumVTableTypes = readNumber<uint32_t>();
678 if (std::error_code EC = NumVTableTypes.getError())
679 return EC;
680 M.reserve(*NumVTableTypes);
681
682 for (uint32_t I = 0; I < *NumVTableTypes; ++I) {
683 auto VTableType(readStringFromTable());
684 if (std::error_code EC = VTableType.getError())
685 return EC;
686
687 auto VTableSamples = readNumber<uint64_t>();
688 if (std::error_code EC = VTableSamples.getError())
689 return EC;
690 // The source profile should not have duplicate vtable records at the same
691 // location. In case duplicate vtables are found, reader can emit a warning
692 // but continue processing the profile.
693 if (!M.insert(std::make_pair(*VTableType, *VTableSamples)).second) {
695 Buffer->getBufferIdentifier(), 0,
696 "Duplicate vtable type " + VTableType->str() +
697 " at the same location. Additional counters will be ignored.",
698 DS_Warning));
699 continue;
700 }
701 }
703}
704
705std::error_code
708 "Cannot read vtable profiles if ReadVTableProf is false");
709
710 // Read the vtable type profile for the callsite.
711 auto NumCallsites = readNumber<uint32_t>();
712 if (std::error_code EC = NumCallsites.getError())
713 return EC;
714 FProfile.reserveCallsiteTypeCounts(*NumCallsites);
715
716 for (uint32_t I = 0; I < *NumCallsites; ++I) {
717 auto LineOffset = readNumber<uint64_t>();
718 if (std::error_code EC = LineOffset.getError())
719 return EC;
720
721 if (!isOffsetLegal(*LineOffset))
723
724 auto Discriminator = readNumber<uint64_t>();
725 if (std::error_code EC = Discriminator.getError())
726 return EC;
727
728 // Here we handle FS discriminators:
729 const uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
730
731 if (std::error_code EC = readVTableTypeCountMap(FProfile.getTypeSamplesAt(
732 LineLocation(*LineOffset, DiscriminatorVal))))
733 return EC;
734 }
736}
737
738std::error_code
740 bool IsNested) {
741 if (ProfileSecRange.IsComposite && !IsNested) {
742 auto NumHeadSamples = readNumber<uint64_t>();
743 if (std::error_code EC = NumHeadSamples.getError())
744 return EC;
745 FProfile.addHeadSamples(*NumHeadSamples);
746 }
747 auto NumSamples = readNumber<uint64_t>();
748 if (std::error_code EC = NumSamples.getError())
749 return EC;
750 FProfile.addTotalSamples(*NumSamples);
751
752 // Read the samples in the body.
753 auto NumRecords = readNumber<uint32_t>();
754 if (std::error_code EC = NumRecords.getError())
755 return EC;
756 FProfile.reserveBodySamples(*NumRecords);
757
758 for (uint32_t I = 0; I < *NumRecords; ++I) {
759 auto LineOffset = readNumber<uint64_t>();
760 if (std::error_code EC = LineOffset.getError())
761 return EC;
762
763 if (!isOffsetLegal(*LineOffset)) {
765 }
766
767 auto Discriminator = readNumber<uint64_t>();
768 if (std::error_code EC = Discriminator.getError())
769 return EC;
770
771 auto NumSamples = readNumber<uint64_t>();
772 if (std::error_code EC = NumSamples.getError())
773 return EC;
774
775 auto NumCalls = readNumber<uint32_t>();
776 if (std::error_code EC = NumCalls.getError())
777 return EC;
778
779 // Here we handle FS discriminators:
780 uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
781
782 for (uint32_t J = 0; J < *NumCalls; ++J) {
783 auto CalledFunction(readStringFromTable());
784 if (std::error_code EC = CalledFunction.getError())
785 return EC;
786
787 auto CalledFunctionSamples = readNumber<uint64_t>();
788 if (std::error_code EC = CalledFunctionSamples.getError())
789 return EC;
790
791 FProfile.addCalledTargetSamples(*LineOffset, DiscriminatorVal,
792 *CalledFunction, *CalledFunctionSamples);
793 }
794
795 FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
796 }
797
799}
800
801std::error_code
803 bool IsNested) {
804 // Read the number of profile types.
805 auto ProfNum = readNumber<uint64_t>();
806 if (std::error_code EC = ProfNum.getError())
807 return EC;
809 *ProfileTypeInfoOS << (IsNested ? "Nested function: " : "Function: ")
810 << FProfile.getContext().toString()
811 << "\n Profile blocks: " << *ProfNum << "\n";
812
813 // Each type identifies one logical payload for the function. Decoding the
814 // same type twice would merge absolute counters from malformed input.
815 SmallSet<uint64_t, 4> SeenTypes;
816
817 // Read the specified number of composite profiles.
818 for (uint64_t I = 0; I < *ProfNum; ++I) {
819 auto Type = readNumber<uint64_t>();
820 if (std::error_code EC = Type.getError())
821 return EC;
822 // Report the conflicting ID so malformed profiles can be diagnosed
823 // without inspecting their binary encoding.
824 if (!SeenTypes.insert(*Type).second) {
825 reportError(0, "Duplicate profile type ID: " + Twine(*Type));
827 }
828 auto Size = readNumber<uint64_t>();
829 if (std::error_code EC = Size.getError())
830 return EC;
832 *ProfileTypeInfoOS << " Type: " << *Type << " ("
834 << "), Payload size: " << *Size << "\n";
835 const uint64_t RemainingSize = End - Data;
836 // Diagnose a size that would let the payload cross its containing section.
837 if (*Size > RemainingSize) {
838 reportError(0, "Profile type ID " + Twine(*Type) +
839 " declares payload size " + Twine(*Size) +
840 ", but only " + Twine(RemainingSize) +
841 " bytes remain");
843 }
844
845 const uint8_t *PayloadEnd = Data + *Size;
846 std::error_code EC = sampleprof_error::success;
847 // Restrict field readers to the current payload so they reject fields that
848 // extend into the following payload.
849 SaveAndRestore<const uint8_t *> RestoreEnd(End, PayloadEnd);
850 switch (*Type) {
851 case ProfTypeLBR:
852 EC = readLBRProfile(FProfile, IsNested);
853 break;
854 default:
855 // Skip unknown profile types for forward compatibility.
857 Data = PayloadEnd;
858 break;
859 }
860
861 if (EC)
862 return EC;
863 // Reject trailing bytes because every known decoder must consume exactly
864 // the payload declared for its type.
865 if (Data != PayloadEnd) {
866 reportError(0,
867 "Profile type ID " + Twine(*Type) +
868 " did not consume its complete payload; unread bytes: " +
869 Twine(PayloadEnd - Data));
871 }
872 }
873
875}
876
877std::error_code
879 bool IsNested) {
880 if (ProfileSecRange.IsComposite) {
881 if (std::error_code EC = readCompositeProfile(FProfile, IsNested))
882 return EC;
883 } else {
884 if (std::error_code EC = readLBRProfile(FProfile, IsNested))
885 return EC;
886 }
887
888 // Read all the samples for inlined function calls.
889 auto NumCallsites = readNumber<uint32_t>();
890 if (std::error_code EC = NumCallsites.getError())
891 return EC;
892
893 for (uint32_t J = 0; J < *NumCallsites; ++J) {
894 auto LineOffset = readNumber<uint64_t>();
895 if (std::error_code EC = LineOffset.getError())
896 return EC;
897
898 auto Discriminator = readNumber<uint64_t>();
899 if (std::error_code EC = Discriminator.getError())
900 return EC;
901
902 auto FName(readStringFromTable());
903 if (std::error_code EC = FName.getError())
904 return EC;
905
906 // Here we handle FS discriminators:
907 uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
908
909 FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
910 LineLocation(*LineOffset, DiscriminatorVal))[*FName];
911 CalleeProfile.setFunction(*FName);
912 if (std::error_code EC = readProfile(CalleeProfile, /*IsNested=*/true))
913 return EC;
914 }
915
916 if (ReadVTableProf)
917 return readCallsiteVTableProf(FProfile);
918
920}
921
922std::error_code
925 Data = Start;
926 ErrorOr<uint64_t> NumHeadSamples = 0;
927 if (!ProfileSecRange.IsComposite) {
928 NumHeadSamples = readNumber<uint64_t>();
929 if (std::error_code EC = NumHeadSamples.getError())
930 return EC;
931 }
932 auto FContextHash(readSampleContextFromTable());
933 if (std::error_code EC = FContextHash.getError())
934 return EC;
935
936 auto &[FContext, Hash] = *FContextHash;
937 // Use the cached hash value for insertion instead of recalculating it.
938 auto Res = Profiles.try_emplace(Hash, FContext, FunctionSamples());
939 FunctionSamples &FProfile = Res.first->second;
940 FProfile.setContext(FContext);
941 if (!ProfileSecRange.IsComposite)
942 FProfile.addHeadSamples(*NumHeadSamples);
943
944 if (FContext.hasContext())
946
947 if (std::error_code EC = readProfile(FProfile, /*IsNested=*/false))
948 return EC;
950}
951
952std::error_code
956
960 while (Data < End) {
961 if (std::error_code EC = readFuncProfile(Data))
962 return EC;
963 }
964
966}
967
969 const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry) {
970 Data = Start;
971 End = Start + Size;
972 switch (Entry.Type) {
973 case SecProfSummary:
974 if (std::error_code EC = readSummary())
975 return EC;
977 Summary->setPartialProfile(true);
985 ReadVTableProf = true;
986 break;
987 case SecNameTable: {
988 bool FixedLengthMD5 =
990 bool UseMD5 = hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name);
991 // UseMD5 means if THIS section uses MD5, ProfileIsMD5 means if the entire
992 // profile uses MD5 for function name matching in IPO passes.
993 ProfileIsMD5 = ProfileIsMD5 || UseMD5;
996 bool IsEytzinger = hasSecFlag(Entry, SecNameTableFlags::SecFlagEytzinger);
997 if (std::error_code EC =
998 readNameTableSec(UseMD5, FixedLengthMD5, IsEytzinger))
999 return EC;
1000 break;
1001 }
1002 case SecCSNameTable: {
1003 if (std::error_code EC = readCSNameTableSec())
1004 return EC;
1005 break;
1006 }
1007 case SecLBRProfile:
1009 // Retain the section and its encoding for subsequent on-demand reads.
1010 ProfileSecRange = {Data, End, Entry.Type == SecCompositeProfile};
1011 if (std::error_code EC = readFuncProfiles())
1012 return EC;
1013 break;
1014 case SecFuncOffsetTable:
1016 // If module is absent, we are using LLVM tools, and need to read all
1017 // profiles, so skip reading the function offset table.
1018 if (!M) {
1019 Data = End;
1020 } else {
1021 bool IsEytzinger =
1023 bool IsFlat = hasSecFlag(Entry, SecCommonFlags::SecFlagFlat);
1024 // An unflagged function offset table inherently indexes the primary
1025 // Nested symbol span.
1026 bool IsNested = !IsFlat;
1027 assert((!ProfileIsCS ||
1029 IsEytzinger) &&
1030 "func offset table should always be sorted or in Eytzinger BFS "
1031 "order in CS profile");
1032 if (std::error_code EC = readFuncOffsetTable(IsEytzinger, IsNested))
1033 return EC;
1034 }
1035 break;
1036 case SecFuncMetadata: {
1042 if (std::error_code EC = readFuncMetadata())
1043 return EC;
1044 break;
1045 }
1047 if (std::error_code EC = readProfileSymbolList(
1049 return EC;
1050 break;
1051 default:
1052 if (std::error_code EC = readCustomSection(Entry))
1053 return EC;
1054 break;
1055 }
1057}
1058
1060 // If profile is CS, the function offset section is expected to consist of
1061 // sequences of contexts in pre-order layout
1062 // (e.g. [A, A:1 @ B, A:1 @ B:2.3 @ C] [D, D:1 @ E]), so that when a matched
1063 // context in the module is found, the profiles of all its callees are
1064 // recursively loaded. A list is needed since the order of profiles matters.
1065 if (ProfileIsCS)
1066 return true;
1067
1068 // If the profile is MD5, use the map container to lookup functions in
1069 // the module. A remapper has no use on MD5 names.
1070 if (useMD5())
1071 return false;
1072
1073 // Profile is not MD5 and if a remapper is present, the remapped name of
1074 // every function needed to be matched against the module, so use the list
1075 // container since each entry is accessed.
1076 if (Remapper)
1077 return true;
1078
1079 // Otherwise use the map container for faster lookup.
1080 // TODO: If the cardinality of the function offset section is much smaller
1081 // than the number of functions in the module, using the list container can
1082 // be always faster, but we need to figure out the constant factor to
1083 // determine the cutoff.
1084 return false;
1085}
1086
1087std::error_code
1089 SampleProfileMap &Profiles) {
1090 if (FuncsToUse.empty())
1092
1095 if (std::error_code EC = readFuncProfiles(FuncsToUse, Profiles))
1096 return EC;
1097 End = Data;
1098 DenseSet<FunctionSamples *> ProfilesToReadMetadata;
1099 for (auto FName : FuncsToUse) {
1100 auto I = Profiles.find(FName);
1101 if (I != Profiles.end())
1102 ProfilesToReadMetadata.insert(&I->second);
1103 }
1104
1105 if (std::error_code EC = readFuncMetadata(ProfilesToReadMetadata))
1106 return EC;
1108}
1109
1111 if (!M)
1112 return false;
1113 FuncsToUse.clear();
1114 for (auto &F : *M)
1116 return true;
1117}
1118
1119std::error_code
1121 bool IsNested) {
1122 if (IsEytzinger)
1123 return readEytzingerFuncOffsetTable(IsNested);
1125}
1126
1127std::error_code
1129 // If there are more than one function offset section, the profile associated
1130 // with the previous section has to be done reading before next one is read.
1131 FuncOffsetTable.reset();
1132
1133 size_t Size = End - Data;
1134 size_t SpanSize = NameTable->getEytzingerSpan(IsNested).size();
1135 if (Size != SpanSize * sizeof(uint32_t))
1137
1138 auto *Array = reinterpret_cast<const support::ulittle32_t *>(Data);
1139 ArrayRef<support::ulittle32_t> Offsets(Array, SpanSize);
1140
1141 FuncOffsetTable.emplace(EytzingerMode, NameTable->getEytzingerSpan(IsNested),
1142 Offsets);
1143
1144 Data = End;
1146}
1147
1149 // If there are more than one function offset section, the profile associated
1150 // with the previous section has to be done reading before next one is read.
1151 FuncOffsetTable.reset();
1152 FuncOffsetList.clear();
1153
1154 auto Size = readNumber<uint64_t>();
1155 if (std::error_code EC = Size.getError())
1156 return EC;
1157
1158 bool UseFuncOffsetList = useFuncOffsetList();
1159 if (UseFuncOffsetList)
1160 FuncOffsetList.reserve(*Size);
1161 else
1163
1164 for (uint64_t I = 0; I < *Size; ++I) {
1165 auto FContextHash(readSampleContextFromTable());
1166 if (std::error_code EC = FContextHash.getError())
1167 return EC;
1168
1169 auto &[FContext, Hash] = *FContextHash;
1171 if (std::error_code EC = Offset.getError())
1172 return EC;
1173
1174 if (UseFuncOffsetList)
1175 FuncOffsetList.emplace_back(FContext, *Offset);
1176 else
1177 // Because Porfiles replace existing value with new value if collision
1178 // happens, we also use the latest offset so that they are consistent.
1179 FuncOffsetTable->insert(Hash, *Offset);
1180 }
1181
1183}
1184
1187 const uint8_t *Start = Data;
1188
1189 if (Remapper) {
1190 for (auto Name : FuncsToUse) {
1191 Remapper->insert(Name);
1192 }
1193 }
1194
1195 if (FuncOffsetTable && FuncOffsetTable->isEytzinger() &&
1197 ArrayRef<support::ulittle32_t> Offsets = FuncOffsetTable->getFuncOffsets();
1198 if (Offsets.size() != FuncOffsetTable->getExpectedSize())
1200 for (const auto &[LocalIdx, RelOffset] : llvm::enumerate(Offsets)) {
1201 if (RelOffset == UINT32_MAX)
1202 continue;
1203 const uint8_t *FuncProfileAddr = Start + RelOffset;
1204 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1205 return EC;
1206 }
1208 }
1209
1210 if (ProfileIsCS) {
1212 DenseSet<uint64_t> FuncGuidsToUse;
1213 if (useMD5()) {
1214 for (auto Name : FuncsToUse)
1216 }
1217
1218 // For each function in current module, load all context profiles for
1219 // the function as well as their callee contexts which can help profile
1220 // guided importing for ThinLTO. This can be achieved by walking
1221 // through an ordered context container, where contexts are laid out
1222 // as if they were walked in preorder of a context trie. While
1223 // traversing the trie, a link to the highest common ancestor node is
1224 // kept so that all of its decendants will be loaded.
1225 const SampleContext *CommonContext = nullptr;
1226 for (const auto &NameOffset : FuncOffsetList) {
1227 const auto &FContext = NameOffset.first;
1228 FunctionId FName = FContext.getFunction();
1229 StringRef FNameString;
1230 if (!useMD5())
1231 FNameString = FName.stringRef();
1232
1233 // For function in the current module, keep its farthest ancestor
1234 // context. This can be used to load itself and its child and
1235 // sibling contexts.
1236 if ((useMD5() && FuncGuidsToUse.count(FName.getHashCode())) ||
1237 (!useMD5() && (FuncsToUse.count(FNameString) ||
1238 (Remapper && Remapper->exist(FNameString))))) {
1239 if (!CommonContext || !CommonContext->isPrefixOf(FContext))
1240 CommonContext = &FContext;
1241 }
1242
1243 if (CommonContext == &FContext ||
1244 (CommonContext && CommonContext->isPrefixOf(FContext))) {
1245 // Load profile for the current context which originated from
1246 // the common ancestor.
1247 const uint8_t *FuncProfileAddr = Start + NameOffset.second;
1248 if (std::error_code EC = readFuncProfile(FuncProfileAddr))
1249 return EC;
1250 }
1251 }
1252 } else if (useMD5()) {
1254 for (auto Name : FuncsToUse) {
1255 auto GUID = MD5Hash(Name);
1256 if (auto Offset = FuncOffsetTable->lookup(GUID)) {
1257 const uint8_t *FuncProfileAddr = Start + *Offset;
1258 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1259 return EC;
1260 }
1261 }
1262 } else if (Remapper) {
1264 for (auto NameOffset : FuncOffsetList) {
1265 SampleContext FContext(NameOffset.first);
1266 auto FuncName = FContext.getFunction();
1267 StringRef FuncNameStr = FuncName.stringRef();
1268 if (!FuncsToUse.count(FuncNameStr) && !Remapper->exist(FuncNameStr))
1269 continue;
1270 const uint8_t *FuncProfileAddr = Start + NameOffset.second;
1271 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1272 return EC;
1273 }
1274 } else {
1276 for (auto Name : FuncsToUse) {
1277 if (auto Offset = FuncOffsetTable->lookup(MD5Hash(Name))) {
1278 const uint8_t *FuncProfileAddr = Start + *Offset;
1279 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1280 return EC;
1281 }
1282 }
1283 }
1284
1286}
1287
1289 // Collect functions used by current module if the Reader has been
1290 // given a module.
1291 // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName
1292 // which will query FunctionSamples::HasUniqSuffix, so it has to be
1293 // called after FunctionSamples::HasUniqSuffix is set, i.e. after
1294 // NameTable section is read.
1295 bool LoadFuncsToBeUsed = collectFuncsFromModule();
1296
1297 // When LoadFuncsToBeUsed is false, we are using LLVM tool, need to read all
1298 // profiles.
1299 if (!LoadFuncsToBeUsed) {
1300 while (Data < End) {
1301 if (std::error_code EC = readFuncProfile(Data))
1302 return EC;
1303 }
1304 assert(Data == End && "More data is read than expected");
1305 } else {
1306 // Load function profiles on demand.
1307 if (std::error_code EC = readFuncProfiles(FuncsToUse, Profiles))
1308 return EC;
1309 Data = End;
1310 }
1311 assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
1312 "Cannot have both context-sensitive and regular profile");
1314 "Section flag should be consistent with actual profile");
1316}
1317
1318std::error_code
1324
1326 size_t Size = End - Data;
1327 if (Size % sizeof(uint64_t) != 0)
1329 const auto *Table = reinterpret_cast<const support::ulittle64_t *>(Data);
1330 size_t NumEntries = Size / sizeof(uint64_t);
1331 if (!ProfSymList)
1332 ProfSymList = std::make_unique<ProfileSymbolList>();
1333 ProfSymList->setColdGUIDTable(
1335 Data = End;
1337}
1338
1339std::error_code
1341 if (!ProfSymList)
1342 ProfSymList = std::make_unique<ProfileSymbolList>();
1343
1344 if (std::error_code EC = ProfSymList->read(Data, End - Data))
1345 return EC;
1346
1347 Data = End;
1349}
1350
1351std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
1352 const uint8_t *SecStart, const uint64_t SecSize,
1353 const uint8_t *&DecompressBuf, uint64_t &DecompressBufSize) {
1354 Data = SecStart;
1355 End = SecStart + SecSize;
1356 auto DecompressSize = readNumber<uint64_t>();
1357 if (std::error_code EC = DecompressSize.getError())
1358 return EC;
1359 DecompressBufSize = *DecompressSize;
1360
1361 auto CompressSize = readNumber<uint64_t>();
1362 if (std::error_code EC = CompressSize.getError())
1363 return EC;
1364
1367
1368 uint8_t *Buffer = Allocator.Allocate<uint8_t>(DecompressBufSize);
1369 size_t UCSize = DecompressBufSize;
1371 Buffer, UCSize);
1372 if (E)
1374 DecompressBuf = reinterpret_cast<const uint8_t *>(Buffer);
1376}
1377
1379 const uint8_t *BufStart =
1380 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
1381
1382 for (auto &Entry : SecHdrTable) {
1383 // Skip empty section.
1384 if (!Entry.Size)
1385 continue;
1386
1387 // Skip sections without inlined functions when SkipFlatProf is true.
1389 continue;
1390
1391 const uint8_t *SecStart = BufStart + Entry.Offset;
1392 uint64_t SecSize = Entry.Size;
1393
1394 // If the section is compressed, decompress it into a buffer
1395 // DecompressBuf before reading the actual data. The pointee of
1396 // 'Data' will be changed to buffer hold by DecompressBuf
1397 // temporarily when reading the actual data.
1398 bool isCompressed = hasSecFlag(Entry, SecCommonFlags::SecFlagCompress);
1399 if (isCompressed) {
1400 const uint8_t *DecompressBuf;
1401 uint64_t DecompressBufSize;
1402 if (std::error_code EC = decompressSection(
1403 SecStart, SecSize, DecompressBuf, DecompressBufSize))
1404 return EC;
1405 SecStart = DecompressBuf;
1406 SecSize = DecompressBufSize;
1407 }
1408
1409 if (std::error_code EC = readOneSection(SecStart, SecSize, Entry))
1410 return EC;
1411 if (Data != SecStart + SecSize)
1413
1414 // Change the pointee of 'Data' from DecompressBuf to original Buffer.
1415 if (isCompressed) {
1416 Data = BufStart + Entry.Offset;
1417 End = BufStart + Buffer->getBufferSize();
1418 }
1419 }
1420
1422}
1423
1424std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
1425 if (Magic == SPMagic())
1428}
1429
1430std::error_code SampleProfileReaderExtBinary::verifySPMagic(uint64_t Magic) {
1431 if (Magic == SPMagic(SPF_Ext_Binary))
1434}
1435
1437 auto Size = readNumber<size_t>();
1438 if (std::error_code EC = Size.getError())
1439 return EC;
1440
1441 // Normally if useMD5 is true, the name table should have MD5 values, not
1442 // strings, however in the case that ExtBinary profile has multiple name
1443 // tables mixing string and MD5, all of them have to be normalized to use MD5,
1444 // because optimization passes can only handle either type.
1445 bool UseMD5 = useMD5();
1446
1447 std::vector<FunctionId> TableVec;
1448 TableVec.reserve(*Size);
1449 if (!ProfileIsCS) {
1450 MD5SampleContextTable.clear();
1451 if (UseMD5)
1452 MD5SampleContextTable.reserve(*Size);
1453 else
1454 // If we are using strings, delay MD5 computation since only a portion of
1455 // names are used by top level functions. Use 0 to indicate MD5 value is
1456 // to be calculated as no known string has a MD5 value of 0.
1457 MD5SampleContextTable.resize(*Size);
1458 }
1459 for (size_t I = 0; I < *Size; ++I) {
1460 auto Name(readString());
1461 if (std::error_code EC = Name.getError())
1462 return EC;
1463 if (UseMD5) {
1464 FunctionId FID(*Name);
1465 if (!ProfileIsCS)
1466 MD5SampleContextTable.emplace_back(FID.getHashCode());
1467 TableVec.emplace_back(FID);
1468 } else
1469 TableVec.push_back(FunctionId(*Name));
1470 }
1471 if (!ProfileIsCS)
1473 if (UseMD5)
1474 NameTable =
1475 std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
1476 else
1477 NameTable =
1478 std::make_unique<StringSampleProfileNameTable>(std::move(TableVec));
1480}
1481
1483 bool IsMD5, bool FixedLengthMD5, bool IsEytzinger) {
1484 if (IsEytzinger)
1485 return readNameTableSecEytzinger(IsMD5, FixedLengthMD5);
1486 return readNameTableSecLegacy(IsMD5, FixedLengthMD5);
1487}
1488
1489// Read the Eytzinger layout for SecNameTable from an ExtBinary MD5 profile.
1490//
1491// The section consists of three sequential ULEB128 symbol counts (Nested, Flat,
1492// and Inlinees) followed by their corresponding arrays of 64-bit MD5 hash keys
1493// laid out in Eytzinger order.
1495 bool IsMD5, bool FixedLengthMD5) {
1496 assert(IsMD5 && "Eytzinger name tables require MD5 representation");
1497 if (!IsMD5)
1499
1500 // Read the table sizes for Nested, flat, and inlinee symbols.
1501 std::array<uint64_t, static_cast<size_t>(EytzingerSpan::NumSpans)> Counts;
1502 for (uint64_t &Count : Counts) {
1503 auto ValOrErr = readNumber<uint64_t>();
1504 if (std::error_code EC = ValOrErr.getError())
1505 return EC;
1506 Count = *ValOrErr;
1507 }
1508 auto [NumNested, NumFlat, NumInlinees] = Counts;
1509
1510 // Guard against unsigned overflow in total entry computation.
1511 if (NumNested > std::numeric_limits<uint32_t>::max() ||
1512 NumFlat > std::numeric_limits<uint32_t>::max() ||
1513 NumInlinees > std::numeric_limits<uint32_t>::max())
1515
1516 uint64_t TotalEntries = NumNested + NumFlat + NumInlinees;
1517 if (static_cast<size_t>(End - Data) < TotalEntries * sizeof(uint64_t))
1519
1520 NameTable = std::make_unique<EytzingerSampleProfileNameTable>(
1521 reinterpret_cast<const support::ulittle64_t *>(Data), NumNested, NumFlat,
1522 NumInlinees);
1523
1524 if (!ProfileIsCS)
1525 MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
1526 Data = Data + TotalEntries * sizeof(uint64_t);
1528}
1529
1530std::error_code
1532 bool FixedLengthMD5) {
1533 if (FixedLengthMD5) {
1534 if (!IsMD5)
1535 errs() << "If FixedLengthMD5 is true, UseMD5 has to be true";
1536 auto Size = readNumber<size_t>();
1537 if (std::error_code EC = Size.getError())
1538 return EC;
1539
1540 assert(Data + (*Size) * sizeof(uint64_t) == End &&
1541 "Fixed length MD5 name table does not contain specified number of "
1542 "entries");
1543 if (Data + (*Size) * sizeof(uint64_t) > End)
1545
1546 if (LazyLoadNameTable) {
1547 NameTable = std::make_unique<LazySampleProfileNameTable>(Data, *Size);
1548 } else {
1549 std::vector<FunctionId> TableVec;
1550 TableVec.reserve(*Size);
1551 for (size_t I = 0; I < *Size; ++I) {
1552 using namespace support;
1553 uint64_t FID = endian::read<uint64_t, unaligned>(
1554 Data + I * sizeof(uint64_t), endianness::little);
1555 TableVec.emplace_back(FunctionId(FID));
1556 }
1557 NameTable =
1558 std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
1559 }
1560 if (!ProfileIsCS)
1561 MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
1562 Data = Data + (*Size) * sizeof(uint64_t);
1564 }
1565
1566 if (IsMD5) {
1567 assert(!FixedLengthMD5 && "FixedLengthMD5 should be unreachable here");
1568 auto Size = readNumber<size_t>();
1569 if (std::error_code EC = Size.getError())
1570 return EC;
1571
1572 std::vector<FunctionId> TableVec;
1573 TableVec.reserve(*Size);
1574 if (!ProfileIsCS)
1575 MD5SampleContextTable.resize(*Size);
1576 for (size_t I = 0; I < *Size; ++I) {
1577 auto FID = readNumber<uint64_t>();
1578 if (std::error_code EC = FID.getError())
1579 return EC;
1580 if (!ProfileIsCS)
1582 TableVec.emplace_back(FunctionId(*FID));
1583 }
1584 if (!ProfileIsCS)
1586 NameTable =
1587 std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
1589 }
1590
1592}
1593
1594// Read in the CS name table section, which basically contains a list of context
1595// vectors. Each element of a context vector, aka a frame, refers to the
1596// underlying raw function names that are stored in the name table, as well as
1597// a callsite identifier that only makes sense for non-leaf frames.
1599 auto Size = readNumber<size_t>();
1600 if (std::error_code EC = Size.getError())
1601 return EC;
1602
1603 CSNameTable.clear();
1604 CSNameTable.reserve(*Size);
1605 if (ProfileIsCS) {
1606 // Delay MD5 computation of CS context until they are needed. Use 0 to
1607 // indicate MD5 value is to be calculated as no known string has a MD5
1608 // value of 0.
1609 MD5SampleContextTable.clear();
1610 MD5SampleContextTable.resize(*Size);
1612 }
1613 for (size_t I = 0; I < *Size; ++I) {
1614 CSNameTable.emplace_back(SampleContextFrameVector());
1615 auto ContextSize = readNumber<uint32_t>();
1616 if (std::error_code EC = ContextSize.getError())
1617 return EC;
1618 for (uint32_t J = 0; J < *ContextSize; ++J) {
1619 auto FName(readStringFromTable());
1620 if (std::error_code EC = FName.getError())
1621 return EC;
1622 auto LineOffset = readNumber<uint64_t>();
1623 if (std::error_code EC = LineOffset.getError())
1624 return EC;
1625
1626 if (!isOffsetLegal(*LineOffset))
1628
1629 auto Discriminator = readNumber<uint64_t>();
1630 if (std::error_code EC = Discriminator.getError())
1631 return EC;
1632
1633 CSNameTable.back().emplace_back(
1634 FName.get(), LineLocation(LineOffset.get(), Discriminator.get()));
1635 }
1636 }
1637
1639}
1640
1641std::error_code
1643 if (Data < End) {
1644 if (ProfileIsProbeBased) {
1645 auto Checksum = readNumber<uint64_t>();
1646 if (std::error_code EC = Checksum.getError())
1647 return EC;
1648 if (FProfile)
1649 FProfile->setFunctionHash(*Checksum);
1650 }
1651
1652 if (ProfileHasAttribute) {
1653 auto Attributes = readNumber<uint32_t>();
1654 if (std::error_code EC = Attributes.getError())
1655 return EC;
1656 if (FProfile)
1657 FProfile->getContext().setAllAttributes(*Attributes);
1658 }
1659
1660 if (!ProfileIsCS) {
1661 // Read all the attributes for inlined function calls.
1662 auto NumCallsites = readNumber<uint32_t>();
1663 if (std::error_code EC = NumCallsites.getError())
1664 return EC;
1665
1666 for (uint32_t J = 0; J < *NumCallsites; ++J) {
1667 auto LineOffset = readNumber<uint64_t>();
1668 if (std::error_code EC = LineOffset.getError())
1669 return EC;
1670
1671 auto Discriminator = readNumber<uint64_t>();
1672 if (std::error_code EC = Discriminator.getError())
1673 return EC;
1674
1675 auto FContextHash(readSampleContextFromTable());
1676 if (std::error_code EC = FContextHash.getError())
1677 return EC;
1678
1679 auto &[FContext, Hash] = *FContextHash;
1680 FunctionSamples *CalleeProfile = nullptr;
1681 if (FProfile) {
1682 CalleeProfile = const_cast<FunctionSamples *>(
1684 *LineOffset, *Discriminator))[FContext.getFunction()]);
1685 }
1686 if (std::error_code EC = readFuncMetadata(CalleeProfile))
1687 return EC;
1688 }
1689 }
1690 }
1691
1693}
1694
1697 if (FuncMetadataIndex.empty())
1699
1700 for (auto *FProfile : Profiles) {
1701 auto R = FuncMetadataIndex.find(FProfile->getContext().getHashCode());
1702 if (R == FuncMetadataIndex.end())
1703 continue;
1704
1705 Data = R->second.first;
1706 End = R->second.second;
1707 if (std::error_code EC = readFuncMetadata(FProfile))
1708 return EC;
1709 assert(Data == End && "More data is read than expected");
1710 }
1712}
1713
1715 while (Data < End) {
1716 auto FContextHash(readSampleContextFromTable());
1717 if (std::error_code EC = FContextHash.getError())
1718 return EC;
1719 auto &[FContext, Hash] = *FContextHash;
1720 FunctionSamples *FProfile = nullptr;
1721 auto It = Profiles.find(FContext);
1722 if (It != Profiles.end())
1723 FProfile = &It->second;
1724
1725 const uint8_t *Start = Data;
1726 if (std::error_code EC = readFuncMetadata(FProfile))
1727 return EC;
1728
1729 FuncMetadataIndex[FContext.getHashCode()] = {Start, Data};
1730 }
1731
1732 assert(Data == End && "More data is read than expected");
1734}
1735
1736std::error_code
1738 SecHdrTableEntry Entry;
1740 if (std::error_code EC = Type.getError())
1741 return EC;
1742 Entry.Type = static_cast<SecType>(*Type);
1743
1744 // Reject a section whose encoding is newer than the declared file version.
1745 if ((Entry.Type == SecCompositeProfile ||
1746 Entry.Type == SecCompositeFuncOffsetTable) &&
1749
1750 auto Flags = readUnencodedNumber<uint64_t>();
1751 if (std::error_code EC = Flags.getError())
1752 return EC;
1753 Entry.Flags = *Flags;
1754
1756 if (std::error_code EC = Offset.getError())
1757 return EC;
1758 Entry.Offset = *Offset;
1759
1761 if (std::error_code EC = Size.getError())
1762 return EC;
1763 Entry.Size = *Size;
1764
1765 Entry.LayoutIndex = Idx;
1766 SecHdrTable.push_back(std::move(Entry));
1768}
1769
1771 auto EntryNum = readUnencodedNumber<uint64_t>();
1772 if (std::error_code EC = EntryNum.getError())
1773 return EC;
1774
1775 for (uint64_t i = 0; i < (*EntryNum); i++)
1776 if (std::error_code EC = readSecHdrTableEntry(i))
1777 return EC;
1778
1780}
1781
1783 const uint8_t *BufStart =
1784 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
1785 Data = BufStart;
1786 End = BufStart + Buffer->getBufferSize();
1787
1788 if (std::error_code EC = readMagicIdent())
1789 return EC;
1790
1791 if (std::error_code EC = readSecHdrTable())
1792 return EC;
1793
1795}
1796
1798 uint64_t Size = 0;
1799 for (auto &Entry : SecHdrTable) {
1800 if (Entry.Type == Type)
1801 Size += Entry.Size;
1802 }
1803 return Size;
1804}
1805
1807 // Sections in SecHdrTable is not necessarily in the same order as
1808 // sections in the profile because section like FuncOffsetTable needs
1809 // to be written after section LBRProfile but needs to be read before
1810 // section LBRProfile, so we cannot simply use the last entry in
1811 // SecHdrTable to calculate the file size.
1812 uint64_t FileSize = 0;
1813 for (auto &Entry : SecHdrTable) {
1814 FileSize = std::max(Entry.Offset + Entry.Size, FileSize);
1815 }
1816 return FileSize;
1817}
1818
1819static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) {
1820 std::string Flags;
1822 Flags.append("{compressed,");
1823 else
1824 Flags.append("{");
1825
1827 Flags.append("flat,");
1828
1829 switch (Entry.Type) {
1830 case SecNameTable:
1832 Flags.append("eytzinger,");
1834 Flags.append("fixlenmd5,");
1836 Flags.append("md5,");
1838 Flags.append("uniq,");
1839 break;
1840 case SecProfSummary:
1842 Flags.append("partial,");
1844 Flags.append("context,");
1846 Flags.append("preInlined,");
1848 Flags.append("fs-discriminator,");
1849 break;
1850 case SecFuncOffsetTable:
1853 Flags.append("ordered,");
1855 Flags.append("eytzinger,");
1856 break;
1857 case SecFuncMetadata:
1859 Flags.append("probe,");
1861 Flags.append("attr,");
1862 break;
1865 Flags.append("md5,");
1866 break;
1867 default:
1868 break;
1869 }
1870 char &last = Flags.back();
1871 if (last == ',')
1872 last = '}';
1873 else
1874 Flags.append("}");
1875 return Flags;
1876}
1877
1879 uint64_t TotalSecsSize = 0;
1880 for (auto &Entry : SecHdrTable) {
1881 OS << getSecName(Entry.Type) << " - Offset: " << Entry.Offset
1882 << ", Size: " << Entry.Size << ", Flags: " << getSecFlagsStr(Entry)
1883 << "\n";
1884 ;
1885 TotalSecsSize += Entry.Size;
1886 }
1887 uint64_t HeaderSize = SecHdrTable.front().Offset;
1888 assert(HeaderSize + TotalSecsSize == getFileSize() &&
1889 "Size of 'header + sections' doesn't match the total size of profile");
1890
1891 OS << "Header Size: " << HeaderSize << "\n";
1892 OS << "Total Sections Size: " << TotalSecsSize << "\n";
1893 OS << "File Size: " << getFileSize() << "\n";
1894 return true;
1895}
1896
1898 // Read and check the magic identifier.
1899 auto Magic = readNumber<uint64_t>();
1900 if (std::error_code EC = Magic.getError())
1901 return EC;
1902 else if (std::error_code EC = verifySPMagic(*Magic))
1903 return EC;
1904
1905 // Read the version number.
1907 if (std::error_code EC = Version.getError())
1908 return EC;
1912
1914}
1915
1917 Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
1918 End = Data + Buffer->getBufferSize();
1919
1920 if (std::error_code EC = readMagicIdent())
1921 return EC;
1922
1923 if (std::error_code EC = readSummary())
1924 return EC;
1925
1926 if (std::error_code EC = readNameTable())
1927 return EC;
1929}
1930
1931std::error_code SampleProfileReaderBinary::readSummaryEntry(
1932 std::vector<ProfileSummaryEntry> &Entries) {
1933 auto Cutoff = readNumber<uint64_t>();
1934 if (std::error_code EC = Cutoff.getError())
1935 return EC;
1936
1937 auto MinBlockCount = readNumber<uint64_t>();
1938 if (std::error_code EC = MinBlockCount.getError())
1939 return EC;
1940
1941 auto NumBlocks = readNumber<uint64_t>();
1942 if (std::error_code EC = NumBlocks.getError())
1943 return EC;
1944
1945 Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
1947}
1948
1950 auto TotalCount = readNumber<uint64_t>();
1951 if (std::error_code EC = TotalCount.getError())
1952 return EC;
1953
1954 auto MaxBlockCount = readNumber<uint64_t>();
1955 if (std::error_code EC = MaxBlockCount.getError())
1956 return EC;
1957
1958 auto MaxFunctionCount = readNumber<uint64_t>();
1959 if (std::error_code EC = MaxFunctionCount.getError())
1960 return EC;
1961
1962 auto NumBlocks = readNumber<uint64_t>();
1963 if (std::error_code EC = NumBlocks.getError())
1964 return EC;
1965
1966 auto NumFunctions = readNumber<uint64_t>();
1967 if (std::error_code EC = NumFunctions.getError())
1968 return EC;
1969
1970 auto NumSummaryEntries = readNumber<uint64_t>();
1971 if (std::error_code EC = NumSummaryEntries.getError())
1972 return EC;
1973
1974 std::vector<ProfileSummaryEntry> Entries;
1975 for (unsigned i = 0; i < *NumSummaryEntries; i++) {
1976 std::error_code EC = readSummaryEntry(Entries);
1977 if (EC != sampleprof_error::success)
1978 return EC;
1979 }
1980 Summary = std::make_unique<ProfileSummary>(
1981 ProfileSummary::PSK_Sample, Entries, *TotalCount, *MaxBlockCount, 0,
1982 *MaxFunctionCount, *NumBlocks, *NumFunctions);
1983
1985}
1986
1987/// Return whether Buffer starts with ExpectedMagic without reading beyond it.
1988static bool hasBinaryFormat(const MemoryBuffer &Buffer,
1989 uint64_t ExpectedMagic) {
1990 const uint8_t *Data =
1991 reinterpret_cast<const uint8_t *>(Buffer.getBufferStart());
1992 const uint8_t *End = reinterpret_cast<const uint8_t *>(Buffer.getBufferEnd());
1994 uint64_t Magic = decodeULEB128(Data, nullptr, End, nullptr, &DecodeError);
1995 return DecodeError == ULEB128DecodeError::None && Magic == ExpectedMagic;
1996}
1997
2001
2005
2007 uint32_t dummy;
2008 if (!GcovBuffer.readInt(dummy))
2011}
2012
2014 if (sizeof(T) <= sizeof(uint32_t)) {
2015 uint32_t Val;
2016 if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
2017 return static_cast<T>(Val);
2018 } else if (sizeof(T) <= sizeof(uint64_t)) {
2019 uint64_t Val;
2020 if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max())
2021 return static_cast<T>(Val);
2022 }
2023
2024 std::error_code EC = sampleprof_error::malformed;
2025 reportError(0, EC.message());
2026 return EC;
2027}
2028
2030 StringRef Str;
2031 if (!GcovBuffer.readString(Str))
2033 return Str;
2034}
2035
2037 // Read the magic identifier.
2038 if (!GcovBuffer.readGCDAFormat())
2040
2041 // Read the version number. Note - the GCC reader does not validate this
2042 // version, but the profile creator generates v704.
2043 GCOV::GCOVVersion version;
2044 if (!GcovBuffer.readGCOVVersion(version))
2046
2047 if (version != GCOV::V407)
2049
2050 // Skip the empty integer.
2051 if (std::error_code EC = skipNextWord())
2052 return EC;
2053
2055}
2056
2058 uint32_t Tag;
2059 if (!GcovBuffer.readInt(Tag))
2061
2062 if (Tag != Expected)
2064
2065 if (std::error_code EC = skipNextWord())
2066 return EC;
2067
2069}
2070
2072 if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
2073 return EC;
2074
2075 uint32_t Size;
2076 if (!GcovBuffer.readInt(Size))
2078
2079 for (uint32_t I = 0; I < Size; ++I) {
2080 StringRef Str;
2081 if (!GcovBuffer.readString(Str))
2083 Names.push_back(std::string(Str));
2084 }
2085
2087}
2088
2090 if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
2091 return EC;
2092
2093 uint32_t NumFunctions;
2094 if (!GcovBuffer.readInt(NumFunctions))
2096
2097 InlineCallStack Stack;
2098 for (uint32_t I = 0; I < NumFunctions; ++I)
2099 if (std::error_code EC = readOneFunctionProfile(Stack, true, 0))
2100 return EC;
2101
2104}
2105
2107 const InlineCallStack &InlineStack, bool Update, uint32_t Offset) {
2108 uint64_t HeadCount = 0;
2109 if (InlineStack.size() == 0)
2110 if (!GcovBuffer.readInt64(HeadCount))
2112
2113 uint32_t NameIdx;
2114 if (!GcovBuffer.readInt(NameIdx))
2116
2117 StringRef Name(Names[NameIdx]);
2118
2119 uint32_t NumPosCounts;
2120 if (!GcovBuffer.readInt(NumPosCounts))
2122
2123 uint32_t NumCallsites;
2124 if (!GcovBuffer.readInt(NumCallsites))
2126
2127 FunctionSamples *FProfile = nullptr;
2128 if (InlineStack.size() == 0) {
2129 // If this is a top function that we have already processed, do not
2130 // update its profile again. This happens in the presence of
2131 // function aliases. Since these aliases share the same function
2132 // body, there will be identical replicated profiles for the
2133 // original function. In this case, we simply not bother updating
2134 // the profile of the original function.
2135 FProfile = &Profiles[FunctionId(Name)];
2136 FProfile->addHeadSamples(HeadCount);
2137 if (FProfile->getTotalSamples() > 0)
2138 Update = false;
2139 } else {
2140 // Otherwise, we are reading an inlined instance. The top of the
2141 // inline stack contains the profile of the caller. Insert this
2142 // callee in the caller's CallsiteMap.
2143 FunctionSamples *CallerProfile = InlineStack.front();
2144 uint32_t LineOffset = Offset >> 16;
2145 uint32_t Discriminator = Offset & 0xffff;
2146 FProfile = &CallerProfile->functionSamplesAt(
2147 LineLocation(LineOffset, Discriminator))[FunctionId(Name)];
2148 }
2149 FProfile->setFunction(FunctionId(Name));
2150 FProfile->reserveBodySamples(NumPosCounts);
2151
2152 for (uint32_t I = 0; I < NumPosCounts; ++I) {
2154 if (!GcovBuffer.readInt(Offset))
2156
2157 uint32_t NumTargets;
2158 if (!GcovBuffer.readInt(NumTargets))
2160
2161 uint64_t Count;
2162 if (!GcovBuffer.readInt64(Count))
2164
2165 // The line location is encoded in the offset as:
2166 // high 16 bits: line offset to the start of the function.
2167 // low 16 bits: discriminator.
2168 uint32_t LineOffset = Offset >> 16;
2169 uint32_t Discriminator = Offset & 0xffff;
2170
2171 InlineCallStack NewStack;
2172 NewStack.push_back(FProfile);
2173 llvm::append_range(NewStack, InlineStack);
2174 if (Update) {
2175 // Walk up the inline stack, adding the samples on this line to
2176 // the total sample count of the callers in the chain.
2177 for (auto *CallerProfile : NewStack)
2178 CallerProfile->addTotalSamples(Count);
2179
2180 // Update the body samples for the current profile.
2181 FProfile->addBodySamples(LineOffset, Discriminator, Count);
2182 }
2183
2184 // Process the list of functions called at an indirect call site.
2185 // These are all the targets that a function pointer (or virtual
2186 // function) resolved at runtime.
2187 for (uint32_t J = 0; J < NumTargets; J++) {
2188 uint32_t HistVal;
2189 if (!GcovBuffer.readInt(HistVal))
2191
2192 if (HistVal != HIST_TYPE_INDIR_CALL_TOPN)
2194
2195 uint64_t TargetIdx;
2196 if (!GcovBuffer.readInt64(TargetIdx))
2198 StringRef TargetName(Names[TargetIdx]);
2199
2200 uint64_t TargetCount;
2201 if (!GcovBuffer.readInt64(TargetCount))
2203
2204 if (Update)
2205 FProfile->addCalledTargetSamples(LineOffset, Discriminator,
2206 FunctionId(TargetName), TargetCount);
2207 }
2208 }
2209
2210 // Process all the inlined callers into the current function. These
2211 // are all the callsites that were inlined into this function.
2212 for (uint32_t I = 0; I < NumCallsites; I++) {
2213 // The offset is encoded as:
2214 // high 16 bits: line offset to the start of the function.
2215 // low 16 bits: discriminator.
2217 if (!GcovBuffer.readInt(Offset))
2219 InlineCallStack NewStack;
2220 NewStack.push_back(FProfile);
2221 llvm::append_range(NewStack, InlineStack);
2222 if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
2223 return EC;
2224 }
2225
2227}
2228
2229/// Read a GCC AutoFDO profile.
2230///
2231/// This format is generated by the Linux Perf conversion tool at
2232/// https://github.com/google/autofdo.
2234 assert(!ProfileIsFSDisciminator && "Gcc profiles not support FSDisciminator");
2235 // Read the string table.
2236 if (std::error_code EC = readNameTable())
2237 return EC;
2238
2239 // Read the source profile.
2240 if (std::error_code EC = readFunctionProfiles())
2241 return EC;
2242
2244}
2245
2247 StringRef Contents = Buffer.getBuffer();
2248 // Preserve exact magic matching, including a magic-only eight-byte buffer.
2249 return Contents.starts_with("adcg*704") &&
2250 (Contents.size() == 8 || Contents[8] == '\0');
2251}
2252
2254 // If the reader uses MD5 to represent string, we can't remap it because
2255 // we don't know what the original function names were.
2256 if (Reader.useMD5()) {
2257 Ctx.diagnose(DiagnosticInfoSampleProfile(
2258 Reader.getBuffer()->getBufferIdentifier(),
2259 "Profile data remapping cannot be applied to profile data "
2260 "using MD5 names (original mangled names are not available).",
2261 DS_Warning));
2262 return;
2263 }
2264
2265 // CSSPGO-TODO: Remapper is not yet supported.
2266 // We will need to remap the entire context string.
2267 assert(Remappings && "should be initialized while creating remapper");
2268 for (auto &Sample : Reader.getProfiles()) {
2269 DenseSet<FunctionId> NamesInSample;
2270 Sample.second.findAllNames(NamesInSample);
2271 for (auto &Name : NamesInSample) {
2272 StringRef NameStr = Name.stringRef();
2273 if (auto Key = Remappings->insert(NameStr))
2274 NameMap.insert({Key, NameStr});
2275 }
2276 }
2277
2278 RemappingApplied = true;
2279}
2280
2281std::optional<StringRef>
2283 if (auto Key = Remappings->lookup(Fname)) {
2284 StringRef Result = NameMap.lookup(Key);
2285 if (!Result.empty())
2286 return Result;
2287 }
2288 return std::nullopt;
2289}
2290
2291/// Prepare a memory buffer for the contents of \p Filename.
2292///
2293/// \returns an error code indicating the status of the buffer.
2296 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
2297 : FS.getBufferForFile(Filename);
2298 if (std::error_code EC = BufferOrErr.getError())
2299 return EC;
2300 auto Buffer = std::move(BufferOrErr.get());
2301
2302 return std::move(Buffer);
2303}
2304
2305/// Create a sample profile reader based on the format of the input file.
2306///
2307/// \param Filename The file to open.
2308///
2309/// \param C The LLVM context to use to emit diagnostics.
2310///
2311/// \param P The FSDiscriminatorPass.
2312///
2313/// \param RemapFilename The file used for profile remapping.
2314///
2315/// \returns an error code indicating the status of the created reader.
2316ErrorOr<std::unique_ptr<SampleProfileReader>>
2319 StringRef RemapFilename) {
2320 auto BufferOrError = setupMemoryBuffer(Filename, FS);
2321 if (std::error_code EC = BufferOrError.getError())
2322 return EC;
2323 return create(BufferOrError.get(), C, FS, P, RemapFilename);
2324}
2325
2326/// Create a sample profile remapper from the given input, to remap the
2327/// function names in the given profile data.
2328///
2329/// \param Filename The file to open.
2330///
2331/// \param Reader The profile reader the remapper is going to be applied to.
2332///
2333/// \param C The LLVM context to use to emit diagnostics.
2334///
2335/// \returns an error code indicating the status of the created reader.
2338 vfs::FileSystem &FS,
2339 SampleProfileReader &Reader,
2340 LLVMContext &C) {
2341 auto BufferOrError = setupMemoryBuffer(Filename, FS);
2342 if (std::error_code EC = BufferOrError.getError())
2343 return EC;
2344 return create(BufferOrError.get(), Reader, C);
2345}
2346
2347/// Create a sample profile remapper from the given input, to remap the
2348/// function names in the given profile data.
2349///
2350/// \param B The memory buffer to create the reader from (assumes ownership).
2351///
2352/// \param C The LLVM context to use to emit diagnostics.
2353///
2354/// \param Reader The profile reader the remapper is going to be applied to.
2355///
2356/// \returns an error code indicating the status of the created reader.
2358SampleProfileReaderItaniumRemapper::create(std::unique_ptr<MemoryBuffer> &B,
2359 SampleProfileReader &Reader,
2360 LLVMContext &C) {
2361 auto Remappings = std::make_unique<SymbolRemappingReader>();
2362 if (Error E = Remappings->read(*B)) {
2364 std::move(E), [&](const SymbolRemappingParseError &ParseError) {
2365 C.diagnose(DiagnosticInfoSampleProfile(B->getBufferIdentifier(),
2366 ParseError.getLineNum(),
2367 ParseError.getMessage()));
2368 });
2370 }
2371
2372 return std::make_unique<SampleProfileReaderItaniumRemapper>(
2373 std::move(B), std::move(Remappings), Reader);
2374}
2375
2376/// Create a sample profile reader based on the format of the input data.
2377///
2378/// \param B The memory buffer to create the reader from (assumes ownership).
2379///
2380/// \param C The LLVM context to use to emit diagnostics.
2381///
2382/// \param P The FSDiscriminatorPass.
2383///
2384/// \param RemapFilename The file used for profile remapping.
2385///
2386/// \returns an error code indicating the status of the created reader.
2388SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
2390 StringRef RemapFilename) {
2391 std::unique_ptr<SampleProfileReader> Reader;
2393 Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C));
2395 Reader.reset(new SampleProfileReaderExtBinary(std::move(B), C));
2397 Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
2399 Reader.reset(new SampleProfileReaderText(std::move(B), C));
2400 else
2402
2403 if (!RemapFilename.empty()) {
2405 RemapFilename, FS, *Reader, C);
2406 if (std::error_code EC = ReaderOrErr.getError()) {
2407 std::string Msg = "Could not create remapper: " + EC.message();
2408 C.diagnose(DiagnosticInfoSampleProfile(RemapFilename, Msg));
2409 return EC;
2410 }
2411 Reader->Remapper = std::move(ReaderOrErr.get());
2412 }
2413
2414 if (std::error_code EC = Reader->readHeader()) {
2415 return EC;
2416 }
2417
2418 Reader->setDiscriminatorMaskedBitFrom(P);
2419
2420 return std::move(Reader);
2421}
2422
2423// For text and GCC file formats, we compute the summary after reading the
2424// profile. Binary format has the profile summary in its header.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
Provides ErrorOr<T> smart pointer.
Module.h This file contains the declarations for the Module class.
This file supports working with JSON data.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
static constexpr StringLiteral Filename
#define P(N)
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool ParseHead(const StringRef &Input, StringRef &FName, uint64_t &NumSamples, uint64_t &NumHeadSamples)
Parse Input as function head.
static void dumpFunctionProfileJson(const FunctionSamples &S, json::OStream &JOS, bool TopLevel=false)
static bool isOffsetLegal(unsigned L)
Returns true if line offset L is legal (only has 16 bits).
static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth, uint64_t &NumSamples, uint32_t &LineOffset, uint32_t &Discriminator, StringRef &CalleeName, DenseMap< StringRef, uint64_t > &TargetCountMap, DenseMap< StringRef, uint64_t > &TypeCountMap, uint64_t &FunctionHash, uint32_t &Attributes, bool &IsFlat)
Parse Input as line sample.
static cl::opt< bool > LazyLoadNameTable("sample-profile-lazy-load-name-table", cl::init(true), cl::Hidden, cl::desc("Lazy load the name table from the profile."))
static cl::opt< bool > ProfileIsFSDisciminator("profile-isfs", cl::Hidden, cl::init(false), cl::desc("Profile uses flow sensitive discriminators"))
static std::string getSecFlagsStr(const SecHdrTableEntry &Entry)
static std::error_code diagnoseReaderError(const SampleProfileReader &Reader, sampleprof_error ProfError)
Emit a reader diagnostic for ProfError and return its error code.
static bool hasBinaryFormat(const MemoryBuffer &Buffer, uint64_t ExpectedMagic)
Return whether Buffer starts with ExpectedMagic without reading beyond it.
static bool parseTypeCountMap(StringRef Input, DenseMap< StringRef, uint64_t > &TypeCountMap)
static bool parseMetadata(const StringRef &Input, uint64_t &FunctionHash, uint32_t &Attributes)
Parse Input that contains metadata.
This file provides utility classes that use RAII to save and restore values.
This file defines the SmallSet class.
Defines the virtual file system interface vfs::FileSystem.
The Input class is used to parse a yaml document into in-memory structs and vectors.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Diagnostic information for the sample profiler.
Represents either an error or a value T.
Definition ErrorOr.h:56
std::error_code getError() const
Definition ErrorOr.h:152
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
Non-owning view of a buffer formatted as a complete binary search tree in Eytzinger (breadth-first) o...
Definition Eytzinger.h:30
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
Definition Globals.cpp:80
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
This interface provides simple read-only access to a block of memory, and provides simple methods for...
const char * getBufferEnd() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
Root of the metadata hierarchy.
Definition Metadata.h:64
static LLVM_ABI const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static constexpr size_t npos
Definition StringRef.h:58
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
size_t find_last_of(char C, size_t From=npos) const
Find the last character in the string that is C, or npos if not found.
Definition StringRef.h:421
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition StringRef.h:396
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:290
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
Definition JSON.h:983
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
Definition JSON.h:1013
void attribute(llvm::StringRef Key, const Value &Contents)
Emit an attribute whose value is self-contained (number, vector<int> etc).
Definition JSON.h:1038
LLVM_ABI void arrayBegin()
Definition JSON.cpp:845
void attributeArray(llvm::StringRef Key, Block Contents)
Emit an attribute whose value is an array with elements from the Block.
Definition JSON.h:1042
LLVM_ABI void arrayEnd()
Definition JSON.cpp:853
A forward iterator which reads text lines from a buffer.
int64_t line_number() const
Return the current line number. May return any number at EOF.
bool is_at_eof() const
Return true if we've reached EOF or are an "end" iterator.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
StringRef stringRef() const
Convert to StringRef.
Definition FunctionId.h:108
uint64_t getHashCode() const
Get hash code of this object.
Definition FunctionId.h:123
std::string str() const
Convert to a string, usually for output purpose.
Definition FunctionId.h:97
Representation of the samples collected for a function.
Definition SampleProf.h:853
static LLVM_ABI std::atomic< bool > ProfileIsFS
If this profile uses flow sensitive discriminators.
static LLVM_ABI std::atomic< bool > ProfileIsPreInlined
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:860
uint64_t getHeadSamples() const
For top-level functions, return the total number of branch samples that have the function as the bran...
void setFunction(FunctionId NewFunctionID)
Set the name of the function.
const CallsiteSampleMap & getCallsiteSamples() const LLVM_LIFETIME_BOUND
Return all the callsite samples collected in the body of the function.
FunctionId getFunction() const
Return the function name.
SampleContext & getContext() const LLVM_LIFETIME_BOUND
FunctionSamplesMap & functionSamplesAt(const LineLocation &Loc) LLVM_LIFETIME_BOUND
Return the function samples at the given callsite location.
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:879
void reserveBodySamples(size_t NumEntries)
Definition SampleProf.h:907
TypeCountMap & getTypeSamplesAt(const LineLocation &Loc) LLVM_LIFETIME_BOUND
Returns the vtable access samples for the C++ types for Loc.
sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, FunctionId Func, uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:893
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:887
static LLVM_ABI std::atomic< bool > HasUniqSuffix
Whether the profile contains any ".__uniq." suffix in a name.
void setFunctionHash(uint64_t Hash)
static LLVM_ABI std::atomic< bool > ProfileIsProbeBased
const BodySampleMap & getBodySamples() const LLVM_LIFETIME_BOUND
Return all the samples collected in the body of the function.
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
void setContext(const SampleContext &FContext)
static LLVM_ABI std::atomic< bool > ProfileIsCS
void reserveCallsiteTypeCounts(size_t NumEntries)
Definition SampleProf.h:911
void setAllAttributes(uint32_t A)
Definition SampleProf.h:719
FunctionId getFunction() const
Definition SampleProf.h:725
std::string toString() const
Definition SampleProf.h:741
bool isPrefixOf(const SampleContext &That) const
Definition SampleProf.h:804
This class provides operator overloads to the map container using MD5 as the key type,...
iterator find(const SampleContext &Ctx)
std::error_code readNameTable()
Read the whole name table.
const uint8_t * Data
Points to the current location in the buffer.
std::error_code readCompositeProfile(FunctionSamples &FProfile, bool IsNested)
std::error_code readLBRProfile(FunctionSamples &FProfile, bool IsNested)
Read specific profile types.
ErrorOr< StringRef > readString()
Read a string from the profile.
std::unique_ptr< SampleProfileNameTable > NameTable
Function name table.
ErrorOr< T > readNumber()
Read a numeric value of type T from the profile.
ErrorOr< SampleContextFrames > readContextFromTable(size_t *RetIdx=nullptr)
Read a context indirectly via the CSNameTable.
ErrorOr< std::pair< SampleContext, uint64_t > > readSampleContextFromTable()
Read a context indirectly via the CSNameTable if the profile has context, otherwise same as readStrin...
std::error_code readHeader() override
Read and validate the file header.
const uint64_t * MD5SampleContextStart
The starting address of the table of MD5 values of sample contexts.
std::vector< SampleContextFrameVector > CSNameTable
CSNameTable is used to save full context vectors.
std::error_code readImpl() override
Read sample profiles from the associated file.
ErrorOr< FunctionId > readStringFromTable(size_t *RetIdx=nullptr)
Read a string indirectly via the name table. Optionally return the index.
std::vector< uint64_t > MD5SampleContextTable
Table to cache MD5 values of sample contexts corresponding to readSampleContextFromTable(),...
std::error_code readCallsiteVTableProf(FunctionSamples &FProfile)
Read all virtual functions' vtable access counts for FProfile.
ErrorOr< size_t > readStringIndex(T &Table)
Read the string index and check whether it overflows the table.
const uint8_t * End
Points to the end of the buffer.
std::error_code readProfile(FunctionSamples &FProfile, bool IsNested)
Read the contents of the given profile instance.
ErrorOr< T > readUnencodedNumber()
Read a numeric value of type T from the profile.
std::error_code readFuncProfile(const uint8_t *Start)
Read the next function profile instance.
std::error_code readVTableTypeCountMap(TypeCountMap &M)
Read bytes from the input buffer pointed by Data and decode them into M.
std::error_code readSummary()
Read profile summary.
std::error_code readMagicIdent()
Read the contents of Magic number and Version number.
std::error_code readNameTableSecEytzinger(bool IsMD5, bool FixedLengthMD5)
bool collectFuncsFromModule() override
Collect functions with definitions in Module M.
uint64_t getSectionSize(SecType Type)
Get the total size of all Type sections.
std::error_code readEytzingerFuncOffsetTable(bool IsNested)
virtual std::error_code readCustomSection(const SecHdrTableEntry &Entry)=0
std::vector< std::pair< SampleContext, uint64_t > > FuncOffsetList
The list version of FuncOffsetTable.
DenseSet< StringRef > FuncsToUse
The set containing the functions to use when compiling a module.
std::unique_ptr< ProfileSymbolList > ProfSymList
std::optional< SampleProfileFuncOffsetTable > FuncOffsetTable
The table mapping from a function context's MD5 to the offset of its FunctionSample towards file star...
std::error_code readNameTableSec(bool IsMD5, bool FixedLengthMD5, bool IsEytzinger=false)
bool useFuncOffsetList() const
Determine which container readFuncOffsetTable() should populate, the list FuncOffsetList or the map F...
std::error_code readImpl() override
Read sample profiles in extensible format from the associated file.
virtual std::error_code readOneSection(const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry)
bool dumpSectionInfo(raw_ostream &OS=dbgs()) override
std::error_code readFuncOffsetTable(bool IsEytzinger, bool IsNested)
std::error_code readNameTableSecLegacy(bool IsMD5, bool FixedLengthMD5)
std::error_code readHeader() override
Read and validate the file header.
uint64_t getFileSize()
Get the total size of header and all sections.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
GCOVBuffer GcovBuffer
GCOV buffer containing the profile.
std::vector< std::string > Names
Function names in this profile.
std::error_code readImpl() override
Read sample profiles from the associated file.
std::error_code readHeader() override
Read and validate the file header.
std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack, bool Update, uint32_t Offset)
static const uint32_t GCOVTagAFDOFileNames
GCOV tags used to separate sections in the profile file.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
std::error_code readSectionTag(uint32_t Expected)
Read the section tag and check that it's the same as Expected.
static LLVM_ABI ErrorOr< std::unique_ptr< SampleProfileReaderItaniumRemapper > > create(StringRef Filename, vfs::FileSystem &FS, SampleProfileReader &Reader, LLVMContext &C)
Create a remapper from the given remapping file.
LLVM_ABI void applyRemapping(LLVMContext &Ctx)
Apply remappings to the profile read by Reader.
LLVM_ABI std::optional< StringRef > lookUpNameInProfile(StringRef FunctionName)
Return the equivalent name in the profile for FunctionName if it exists.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
std::error_code readImpl() override
Read sample profiles from the associated file.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
bool ReadVTableProf
If true, the profile has vtable profiles and reader should decode them to parse profiles correctly.
bool ProfileIsPreInlined
Whether function profile contains ShouldBeInlined contexts.
DenseMap< uint64_t, std::pair< const uint8_t *, const uint8_t * > > FuncMetadataIndex
uint32_t CSProfileCount
Number of context-sensitive profiles.
static LLVM_ABI ErrorOr< std::unique_ptr< SampleProfileReader > > create(StringRef Filename, LLVMContext &C, vfs::FileSystem &FS, FSDiscriminatorPass P=FSDiscriminatorPass::Base, StringRef RemapFilename="")
Create a sample profile reader appropriate to the file format.
LLVM_ABI void dump(raw_ostream &OS=dbgs())
Print all the profiles on stream OS.
bool useMD5() const
Return whether names in the profile are all MD5 numbers.
const Module * M
The current module being compiled if SampleProfileReader is used by compiler.
std::unique_ptr< MemoryBuffer > Buffer
Memory buffer holding the profile file.
std::unique_ptr< SampleProfileReaderItaniumRemapper > Remapper
bool ProfileHasAttribute
Whether the profile has attribute metadata.
bool SkipFlatProf
If SkipFlatProf is true, skip functions marked with !Flat in text mode or sections with SecFlagFlat f...
std::error_code read()
The interface to read sample profiles from the associated file.
ProfileSectionRange ProfileSecRange
Profile section most recently selected for on-demand loading.
bool ProfileIsCS
Whether function profiles are context-sensitive flat profiles.
bool ProfileIsMD5
Whether the profile uses MD5 for Sample Contexts and function names.
std::unique_ptr< ProfileSummary > Summary
Profile summary information.
LLVM_ABI void computeSummary()
Compute summary for this profile.
uint32_t getDiscriminatorMask() const
Get the bitmask the discriminators: For FS profiles, return the bit mask for this pass.
bool HasUnknownProfileTypes
Whether reading skipped at least one unknown composite profile block.
bool ProfileIsFS
Whether the function profiles use FS discriminators.
LLVM_ABI void dumpJson(raw_ostream &OS=dbgs())
Print all the profiles on stream OS in the JSON format.
SampleProfileMap Profiles
Map every function to its associated profile.
uint64_t FormatVersion
Format version of the profile.
LLVM_ABI void dumpFunctionProfile(const FunctionSamples &FS, raw_ostream &OS=dbgs())
Print the profile for FunctionSamples on stream OS.
bool ProfileIsProbeBased
Whether samples are collected based on pseudo probes.
void reportError(int64_t LineNumber, const Twine &Msg) const
Report a parse error message.
raw_ostream * ProfileTypeInfoOS
Optional stream for composite block structure; null disables the output.
LLVMContext & Ctx
LLVM context used to emit diagnostics.
Representation of a single sample record.
Definition SampleProf.h:422
SortedCallTargetSet getSortedCallTargets() const
Definition SampleProf.h:496
The virtual file system interface.
GCOVVersion
Definition GCOV.h:43
@ V407
Definition GCOV.h:43
initializer< Ty > init(const Ty &Val)
LLVM_ABI Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)
LLVM_ABI bool isAvailable()
LLVM_ABI void sortFuncProfiles(const SampleProfileMap &ProfileMap, std::vector< NameFunctionSamples > &SortedProfiles)
static uint64_t SPMagic(SampleProfileFormat Format=SPF_Binary)
Definition SampleProf.h:114
static bool formatVersionIsSupported(uint64_t Version)
Definition SampleProf.h:136
std::map< LineLocation, FunctionSamplesMap > CallsiteSampleMap
Definition SampleProf.h:844
static bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:335
SortedVectorMap< LineLocation, SampleRecord, 0 > BodySampleMap
Definition SampleProf.h:840
uint64_t MD5Hash(const FunctionId &Obj)
Definition FunctionId.h:167
constexpr EytzingerModeT EytzingerMode
@ SecFlagIsPreInlined
SecFlagIsPreInlined means this profile contains ShouldBeInlined contexts thus this is CS preinliner c...
Definition SampleProf.h:263
@ SecFlagHasVTableTypeProf
SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
Definition SampleProf.h:266
@ SecFlagPartial
SecFlagPartial means the profile is for common/shared code.
Definition SampleProf.h:254
@ SecFlagFSDiscriminator
SecFlagFSDiscriminator means this profile uses flow-sensitive discriminators.
Definition SampleProf.h:260
@ SecFlagFullContext
SecFlagContext means this is context-sensitive flat profile for CSSPGO.
Definition SampleProf.h:257
static StringRef getProfTypeName(uint64_t Type)
Definition SampleProf.h:196
SmallVector< SampleContextFrame, 1 > SampleContextFrameVector
Definition SampleProf.h:613
static std::string getSecName(SecType Type)
Definition SampleProf.h:164
constexpr InMemoryModeT InMemoryMode
static constexpr uint64_t CompositeProfileVersion
Definition SampleProf.h:130
constexpr char kVTableProfPrefix[]
Definition SampleProf.h:97
SmallVector< FunctionSamples *, 10 > InlineCallStack
SortedVectorMap< FunctionId, uint64_t, 0 > TypeCountMap
Key represents type of a C++ polymorphic class type by its vtable and value represents its counter.
Definition SampleProf.h:402
uint64_t read64le(const void *P)
Definition Endian.h:415
void write64le(void *P, uint64_t V)
Definition Endian.h:458
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition Endian.h:53
value_type readNext(const CharT *&memory, endianness endian)
Read a value of a particular endianness from a buffer, and increment the buffer past that value.
Definition Endian.h:67
detail::packed_endian_specific_integral< uint64_t, llvm::endianness::little, unaligned > ulittle64_t
Definition Endian.h:273
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
Definition Endian.h:270
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition Error.h:1013
ULEB128DecodeError
Identifies why ULEB128 decoding failed.
Definition LEB128.h:127
@ UnexpectedEnd
The encoding requires bytes beyond the supplied buffer.
Definition LEB128.h:131
@ None
No decoding error has been reported.
Definition LEB128.h:129
@ TooBig
The encoded value does not fit in uint64_t.
Definition LEB128.h:133
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
sampleprof_error mergeSampleProfErrors(sampleprof_error &Accumulator, sampleprof_error Result)
Definition SampleProf.h:75
sampleprof_error
Definition SampleProf.h:52
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2028
ArrayRef(const T &OneElt) -> ArrayRef< T >
uint64_t decodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end, const char **error, ULEB128DecodeError *errorCode)
Utility function to decode a ULEB128 value and report a typed error.
Definition LEB128.h:145
A utility class that uses RAII to save and restore the value of a variable.
Represents the relative location of an instruction.
Definition SampleProf.h:351
const uint8_t * Start
First byte of the retained section.
const uint8_t * End
One-past-the-end byte of the retained section.