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 // With FS discriminators, M may already hold the types of another raw
681 // location that maps to the same masked location (see below), so reserve
682 // for both the existing and the incoming vtables.
683 M.reserve(M.size() + *NumVTableTypes);
684
685 for (uint32_t I = 0; I < *NumVTableTypes; ++I) {
686 auto VTableType(readStringFromTable());
687 if (std::error_code EC = VTableType.getError())
688 return EC;
689
690 auto VTableSamples = readNumber<uint64_t>();
691 if (std::error_code EC = VTableSamples.getError())
692 return EC;
693
694 auto [It, Inserted] = M.try_emplace(*VTableType, *VTableSamples);
695 if (Inserted)
696 continue;
697
698 // Without FS discriminators, the source profile should not have duplicate
699 // vtable records at the same location. Emit a warning about duplicate
700 // vtables and continue processing the profile.
701 if (!ProfileIsFS) {
703 Buffer->getBufferIdentifier(), 0,
704 "Duplicate vtable type " + VTableType->str() +
705 " at the same location. Additional counters will be ignored.",
706 DS_Warning));
707 continue;
708 }
709
710 // With flow-sensitive discriminators enabled in the profiled binary,
711 // several raw locations of the profiled instruction may map to the same
712 // masked location. Accumulate vtable counts for the same masked location,
713 // like body and callsite samples are accumulated.
714 It->second = SaturatingAdd(It->second, *VTableSamples);
715 }
717}
718
719std::error_code
722 "Cannot read vtable profiles if ReadVTableProf is false");
723
724 // Read the vtable type profile for the callsite.
725 auto NumCallsites = readNumber<uint32_t>();
726 if (std::error_code EC = NumCallsites.getError())
727 return EC;
728 FProfile.reserveCallsiteTypeCounts(*NumCallsites);
729
730 for (uint32_t I = 0; I < *NumCallsites; ++I) {
731 auto LineOffset = readNumber<uint64_t>();
732 if (std::error_code EC = LineOffset.getError())
733 return EC;
734
735 if (!isOffsetLegal(*LineOffset))
737
738 auto Discriminator = readNumber<uint64_t>();
739 if (std::error_code EC = Discriminator.getError())
740 return EC;
741
742 // Here we handle FS discriminators:
743 const uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
744
745 if (std::error_code EC = readVTableTypeCountMap(FProfile.getTypeSamplesAt(
746 LineLocation(*LineOffset, DiscriminatorVal))))
747 return EC;
748 }
750}
751
752std::error_code
754 bool IsNested) {
755 if (ProfileSecRange.IsComposite && !IsNested) {
756 auto NumHeadSamples = readNumber<uint64_t>();
757 if (std::error_code EC = NumHeadSamples.getError())
758 return EC;
759 FProfile.addHeadSamples(*NumHeadSamples);
760 }
761 auto NumSamples = readNumber<uint64_t>();
762 if (std::error_code EC = NumSamples.getError())
763 return EC;
764 FProfile.addTotalSamples(*NumSamples);
765
766 // Read the samples in the body.
767 auto NumRecords = readNumber<uint32_t>();
768 if (std::error_code EC = NumRecords.getError())
769 return EC;
770 FProfile.reserveBodySamples(*NumRecords);
771
772 for (uint32_t I = 0; I < *NumRecords; ++I) {
773 auto LineOffset = readNumber<uint64_t>();
774 if (std::error_code EC = LineOffset.getError())
775 return EC;
776
777 if (!isOffsetLegal(*LineOffset)) {
779 }
780
781 auto Discriminator = readNumber<uint64_t>();
782 if (std::error_code EC = Discriminator.getError())
783 return EC;
784
785 auto NumSamples = readNumber<uint64_t>();
786 if (std::error_code EC = NumSamples.getError())
787 return EC;
788
789 auto NumCalls = readNumber<uint32_t>();
790 if (std::error_code EC = NumCalls.getError())
791 return EC;
792
793 // Here we handle FS discriminators:
794 uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
795
796 for (uint32_t J = 0; J < *NumCalls; ++J) {
797 auto CalledFunction(readStringFromTable());
798 if (std::error_code EC = CalledFunction.getError())
799 return EC;
800
801 auto CalledFunctionSamples = readNumber<uint64_t>();
802 if (std::error_code EC = CalledFunctionSamples.getError())
803 return EC;
804
805 FProfile.addCalledTargetSamples(*LineOffset, DiscriminatorVal,
806 *CalledFunction, *CalledFunctionSamples);
807 }
808
809 FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
810 }
811
813}
814
815std::error_code
817 bool IsNested) {
818 // Read the number of profile types.
819 auto ProfNum = readNumber<uint64_t>();
820 if (std::error_code EC = ProfNum.getError())
821 return EC;
823 *ProfileTypeInfoOS << (IsNested ? "Nested function: " : "Function: ")
824 << FProfile.getContext().toString()
825 << "\n Profile blocks: " << *ProfNum << "\n";
826
827 // Each type identifies one logical payload for the function. Decoding the
828 // same type twice would merge absolute counters from malformed input.
829 SmallSet<uint64_t, 4> SeenTypes;
830
831 // Read the specified number of composite profiles.
832 for (uint64_t I = 0; I < *ProfNum; ++I) {
833 auto Type = readNumber<uint64_t>();
834 if (std::error_code EC = Type.getError())
835 return EC;
836 // Report the conflicting ID so malformed profiles can be diagnosed
837 // without inspecting their binary encoding.
838 if (!SeenTypes.insert(*Type).second) {
839 reportError(0, "Duplicate profile type ID: " + Twine(*Type));
841 }
842 auto Size = readNumber<uint64_t>();
843 if (std::error_code EC = Size.getError())
844 return EC;
846 *ProfileTypeInfoOS << " Type: " << *Type << " ("
848 << "), Payload size: " << *Size << "\n";
849 const uint64_t RemainingSize = End - Data;
850 // Diagnose a size that would let the payload cross its containing section.
851 if (*Size > RemainingSize) {
852 reportError(0, "Profile type ID " + Twine(*Type) +
853 " declares payload size " + Twine(*Size) +
854 ", but only " + Twine(RemainingSize) +
855 " bytes remain");
857 }
858
859 const uint8_t *PayloadEnd = Data + *Size;
860 std::error_code EC = sampleprof_error::success;
861 // Restrict field readers to the current payload so they reject fields that
862 // extend into the following payload.
863 SaveAndRestore<const uint8_t *> RestoreEnd(End, PayloadEnd);
864 switch (*Type) {
865 case ProfTypeLBR:
866 EC = readLBRProfile(FProfile, IsNested);
867 break;
868 default:
869 // Skip unknown profile types for forward compatibility.
871 Data = PayloadEnd;
872 break;
873 }
874
875 if (EC)
876 return EC;
877 // Reject trailing bytes because every known decoder must consume exactly
878 // the payload declared for its type.
879 if (Data != PayloadEnd) {
880 reportError(0,
881 "Profile type ID " + Twine(*Type) +
882 " did not consume its complete payload; unread bytes: " +
883 Twine(PayloadEnd - Data));
885 }
886 }
887
889}
890
891std::error_code
893 bool IsNested) {
894 if (ProfileSecRange.IsComposite) {
895 if (std::error_code EC = readCompositeProfile(FProfile, IsNested))
896 return EC;
897 } else {
898 if (std::error_code EC = readLBRProfile(FProfile, IsNested))
899 return EC;
900 }
901
902 // Read all the samples for inlined function calls.
903 auto NumCallsites = readNumber<uint32_t>();
904 if (std::error_code EC = NumCallsites.getError())
905 return EC;
906
907 for (uint32_t J = 0; J < *NumCallsites; ++J) {
908 auto LineOffset = readNumber<uint64_t>();
909 if (std::error_code EC = LineOffset.getError())
910 return EC;
911
912 auto Discriminator = readNumber<uint64_t>();
913 if (std::error_code EC = Discriminator.getError())
914 return EC;
915
916 auto FName(readStringFromTable());
917 if (std::error_code EC = FName.getError())
918 return EC;
919
920 // Here we handle FS discriminators:
921 uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
922
923 FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
924 LineLocation(*LineOffset, DiscriminatorVal))[*FName];
925 CalleeProfile.setFunction(*FName);
926 if (std::error_code EC = readProfile(CalleeProfile, /*IsNested=*/true))
927 return EC;
928 }
929
930 if (ReadVTableProf)
931 return readCallsiteVTableProf(FProfile);
932
934}
935
936std::error_code
939 Data = Start;
940 ErrorOr<uint64_t> NumHeadSamples = 0;
941 if (!ProfileSecRange.IsComposite) {
942 NumHeadSamples = readNumber<uint64_t>();
943 if (std::error_code EC = NumHeadSamples.getError())
944 return EC;
945 }
946 auto FContextHash(readSampleContextFromTable());
947 if (std::error_code EC = FContextHash.getError())
948 return EC;
949
950 auto &[FContext, Hash] = *FContextHash;
951 // Use the cached hash value for insertion instead of recalculating it.
952 auto Res = Profiles.try_emplace(Hash, FContext, FunctionSamples());
953 FunctionSamples &FProfile = Res.first->second;
954 FProfile.setContext(FContext);
955 if (!ProfileSecRange.IsComposite)
956 FProfile.addHeadSamples(*NumHeadSamples);
957
958 if (FContext.hasContext())
960
961 if (std::error_code EC = readProfile(FProfile, /*IsNested=*/false))
962 return EC;
964}
965
966std::error_code
970
974 while (Data < End) {
975 if (std::error_code EC = readFuncProfile(Data))
976 return EC;
977 }
978
980}
981
983 const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry) {
984 Data = Start;
985 End = Start + Size;
986 switch (Entry.Type) {
987 case SecProfSummary:
988 if (std::error_code EC = readSummary())
989 return EC;
991 Summary->setPartialProfile(true);
999 ReadVTableProf = true;
1000 break;
1001 case SecNameTable: {
1002 bool FixedLengthMD5 =
1004 bool UseMD5 = hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name);
1005 // UseMD5 means if THIS section uses MD5, ProfileIsMD5 means if the entire
1006 // profile uses MD5 for function name matching in IPO passes.
1007 ProfileIsMD5 = ProfileIsMD5 || UseMD5;
1010 bool IsEytzinger = hasSecFlag(Entry, SecNameTableFlags::SecFlagEytzinger);
1011 if (std::error_code EC =
1012 readNameTableSec(UseMD5, FixedLengthMD5, IsEytzinger))
1013 return EC;
1014 break;
1015 }
1016 case SecCSNameTable: {
1017 if (std::error_code EC = readCSNameTableSec())
1018 return EC;
1019 break;
1020 }
1021 case SecLBRProfile:
1023 // Retain the section and its encoding for subsequent on-demand reads.
1024 ProfileSecRange = {Data, End, Entry.Type == SecCompositeProfile};
1025 if (std::error_code EC = readFuncProfiles())
1026 return EC;
1027 break;
1028 case SecFuncOffsetTable:
1030 // If module is absent, we are using LLVM tools, and need to read all
1031 // profiles, so skip reading the function offset table.
1032 if (!M) {
1033 Data = End;
1034 } else {
1035 bool IsEytzinger =
1037 bool IsFlat = hasSecFlag(Entry, SecCommonFlags::SecFlagFlat);
1038 // An unflagged function offset table inherently indexes the primary
1039 // Nested symbol span.
1040 bool IsNested = !IsFlat;
1041 assert((!ProfileIsCS ||
1043 IsEytzinger) &&
1044 "func offset table should always be sorted or in Eytzinger BFS "
1045 "order in CS profile");
1046 if (std::error_code EC = readFuncOffsetTable(IsEytzinger, IsNested))
1047 return EC;
1048 }
1049 break;
1050 case SecFuncMetadata: {
1056 if (std::error_code EC = readFuncMetadata())
1057 return EC;
1058 break;
1059 }
1061 if (std::error_code EC = readProfileSymbolList(
1063 return EC;
1064 break;
1065 default:
1066 if (std::error_code EC = readCustomSection(Entry))
1067 return EC;
1068 break;
1069 }
1071}
1072
1074 // If profile is CS, the function offset section is expected to consist of
1075 // sequences of contexts in pre-order layout
1076 // (e.g. [A, A:1 @ B, A:1 @ B:2.3 @ C] [D, D:1 @ E]), so that when a matched
1077 // context in the module is found, the profiles of all its callees are
1078 // recursively loaded. A list is needed since the order of profiles matters.
1079 if (ProfileIsCS)
1080 return true;
1081
1082 // If the profile is MD5, use the map container to lookup functions in
1083 // the module. A remapper has no use on MD5 names.
1084 if (useMD5())
1085 return false;
1086
1087 // Profile is not MD5 and if a remapper is present, the remapped name of
1088 // every function needed to be matched against the module, so use the list
1089 // container since each entry is accessed.
1090 if (Remapper)
1091 return true;
1092
1093 // Otherwise use the map container for faster lookup.
1094 // TODO: If the cardinality of the function offset section is much smaller
1095 // than the number of functions in the module, using the list container can
1096 // be always faster, but we need to figure out the constant factor to
1097 // determine the cutoff.
1098 return false;
1099}
1100
1101std::error_code
1103 SampleProfileMap &Profiles) {
1104 if (FuncsToUse.empty())
1106
1109 if (std::error_code EC = readFuncProfiles(FuncsToUse, Profiles))
1110 return EC;
1111 End = Data;
1112 DenseSet<FunctionSamples *> ProfilesToReadMetadata;
1113 for (auto FName : FuncsToUse) {
1114 auto I = Profiles.find(FName);
1115 if (I != Profiles.end())
1116 ProfilesToReadMetadata.insert(&I->second);
1117 }
1118
1119 if (std::error_code EC = readFuncMetadata(ProfilesToReadMetadata))
1120 return EC;
1122}
1123
1125 if (!M)
1126 return false;
1127 FuncsToUse.clear();
1128 for (auto &F : *M)
1130 return true;
1131}
1132
1133std::error_code
1135 bool IsNested) {
1136 if (IsEytzinger)
1137 return readEytzingerFuncOffsetTable(IsNested);
1139}
1140
1141std::error_code
1143 // If there are more than one function offset section, the profile associated
1144 // with the previous section has to be done reading before next one is read.
1145 FuncOffsetTable.reset();
1146
1147 size_t Size = End - Data;
1148 size_t SpanSize = NameTable->getEytzingerSpan(IsNested).size();
1149 if (Size != SpanSize * sizeof(uint32_t))
1151
1152 auto *Array = reinterpret_cast<const support::ulittle32_t *>(Data);
1153 ArrayRef<support::ulittle32_t> Offsets(Array, SpanSize);
1154
1155 FuncOffsetTable.emplace(EytzingerMode, NameTable->getEytzingerSpan(IsNested),
1156 Offsets);
1157
1158 Data = End;
1160}
1161
1163 // If there are more than one function offset section, the profile associated
1164 // with the previous section has to be done reading before next one is read.
1165 FuncOffsetTable.reset();
1166 FuncOffsetList.clear();
1167
1168 auto Size = readNumber<uint64_t>();
1169 if (std::error_code EC = Size.getError())
1170 return EC;
1171
1172 bool UseFuncOffsetList = useFuncOffsetList();
1173 if (UseFuncOffsetList)
1174 FuncOffsetList.reserve(*Size);
1175 else
1177
1178 for (uint64_t I = 0; I < *Size; ++I) {
1179 auto FContextHash(readSampleContextFromTable());
1180 if (std::error_code EC = FContextHash.getError())
1181 return EC;
1182
1183 auto &[FContext, Hash] = *FContextHash;
1185 if (std::error_code EC = Offset.getError())
1186 return EC;
1187
1188 if (UseFuncOffsetList)
1189 FuncOffsetList.emplace_back(FContext, *Offset);
1190 else
1191 // Because Porfiles replace existing value with new value if collision
1192 // happens, we also use the latest offset so that they are consistent.
1193 FuncOffsetTable->insert(Hash, *Offset);
1194 }
1195
1197}
1198
1201 const uint8_t *Start = Data;
1202
1203 if (Remapper) {
1204 for (auto Name : FuncsToUse) {
1205 Remapper->insert(Name);
1206 }
1207 }
1208
1209 if (FuncOffsetTable && FuncOffsetTable->isEytzinger() &&
1211 ArrayRef<support::ulittle32_t> Offsets = FuncOffsetTable->getFuncOffsets();
1212 if (Offsets.size() != FuncOffsetTable->getExpectedSize())
1214 for (const auto &[LocalIdx, RelOffset] : llvm::enumerate(Offsets)) {
1215 if (RelOffset == UINT32_MAX)
1216 continue;
1217 const uint8_t *FuncProfileAddr = Start + RelOffset;
1218 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1219 return EC;
1220 }
1222 }
1223
1224 if (ProfileIsCS) {
1226 DenseSet<uint64_t> FuncGuidsToUse;
1227 if (useMD5()) {
1228 for (auto Name : FuncsToUse)
1230 }
1231
1232 // For each function in current module, load all context profiles for
1233 // the function as well as their callee contexts which can help profile
1234 // guided importing for ThinLTO. This can be achieved by walking
1235 // through an ordered context container, where contexts are laid out
1236 // as if they were walked in preorder of a context trie. While
1237 // traversing the trie, a link to the highest common ancestor node is
1238 // kept so that all of its decendants will be loaded.
1239 const SampleContext *CommonContext = nullptr;
1240 for (const auto &NameOffset : FuncOffsetList) {
1241 const auto &FContext = NameOffset.first;
1242 FunctionId FName = FContext.getFunction();
1243 StringRef FNameString;
1244 if (!useMD5())
1245 FNameString = FName.stringRef();
1246
1247 // For function in the current module, keep its farthest ancestor
1248 // context. This can be used to load itself and its child and
1249 // sibling contexts.
1250 if ((useMD5() && FuncGuidsToUse.count(FName.getHashCode())) ||
1251 (!useMD5() && (FuncsToUse.count(FNameString) ||
1252 (Remapper && Remapper->exist(FNameString))))) {
1253 if (!CommonContext || !CommonContext->isPrefixOf(FContext))
1254 CommonContext = &FContext;
1255 }
1256
1257 if (CommonContext == &FContext ||
1258 (CommonContext && CommonContext->isPrefixOf(FContext))) {
1259 // Load profile for the current context which originated from
1260 // the common ancestor.
1261 const uint8_t *FuncProfileAddr = Start + NameOffset.second;
1262 if (std::error_code EC = readFuncProfile(FuncProfileAddr))
1263 return EC;
1264 }
1265 }
1266 } else if (useMD5()) {
1268 for (auto Name : FuncsToUse) {
1269 auto GUID = MD5Hash(Name);
1270 if (auto Offset = FuncOffsetTable->lookup(GUID)) {
1271 const uint8_t *FuncProfileAddr = Start + *Offset;
1272 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1273 return EC;
1274 }
1275 }
1276 } else if (Remapper) {
1278 for (auto NameOffset : FuncOffsetList) {
1279 SampleContext FContext(NameOffset.first);
1280 auto FuncName = FContext.getFunction();
1281 StringRef FuncNameStr = FuncName.stringRef();
1282 if (!FuncsToUse.count(FuncNameStr) && !Remapper->exist(FuncNameStr))
1283 continue;
1284 const uint8_t *FuncProfileAddr = Start + NameOffset.second;
1285 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1286 return EC;
1287 }
1288 } else {
1290 for (auto Name : FuncsToUse) {
1291 if (auto Offset = FuncOffsetTable->lookup(MD5Hash(Name))) {
1292 const uint8_t *FuncProfileAddr = Start + *Offset;
1293 if (std::error_code EC = readFuncProfile(FuncProfileAddr, Profiles))
1294 return EC;
1295 }
1296 }
1297 }
1298
1300}
1301
1303 // Collect functions used by current module if the Reader has been
1304 // given a module.
1305 // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName
1306 // which will query FunctionSamples::HasUniqSuffix, so it has to be
1307 // called after FunctionSamples::HasUniqSuffix is set, i.e. after
1308 // NameTable section is read.
1309 bool LoadFuncsToBeUsed = collectFuncsFromModule();
1310
1311 // When LoadFuncsToBeUsed is false, we are using LLVM tool, need to read all
1312 // profiles.
1313 if (!LoadFuncsToBeUsed) {
1314 while (Data < End) {
1315 if (std::error_code EC = readFuncProfile(Data))
1316 return EC;
1317 }
1318 assert(Data == End && "More data is read than expected");
1319 } else {
1320 // Load function profiles on demand.
1321 if (std::error_code EC = readFuncProfiles(FuncsToUse, Profiles))
1322 return EC;
1323 Data = End;
1324 }
1325 assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
1326 "Cannot have both context-sensitive and regular profile");
1328 "Section flag should be consistent with actual profile");
1330}
1331
1332std::error_code
1338
1340 size_t Size = End - Data;
1341 if (Size % sizeof(uint64_t) != 0)
1343 const auto *Table = reinterpret_cast<const support::ulittle64_t *>(Data);
1344 size_t NumEntries = Size / sizeof(uint64_t);
1345 if (!ProfSymList)
1346 ProfSymList = std::make_unique<ProfileSymbolList>();
1347 ProfSymList->setColdGUIDTable(
1349 Data = End;
1351}
1352
1353std::error_code
1355 if (!ProfSymList)
1356 ProfSymList = std::make_unique<ProfileSymbolList>();
1357
1358 if (std::error_code EC = ProfSymList->read(Data, End - Data))
1359 return EC;
1360
1361 Data = End;
1363}
1364
1365std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
1366 const uint8_t *SecStart, const uint64_t SecSize,
1367 const uint8_t *&DecompressBuf, uint64_t &DecompressBufSize) {
1368 Data = SecStart;
1369 End = SecStart + SecSize;
1370 auto DecompressSize = readNumber<uint64_t>();
1371 if (std::error_code EC = DecompressSize.getError())
1372 return EC;
1373 DecompressBufSize = *DecompressSize;
1374
1375 auto CompressSize = readNumber<uint64_t>();
1376 if (std::error_code EC = CompressSize.getError())
1377 return EC;
1378
1381
1382 uint8_t *Buffer = Allocator.Allocate<uint8_t>(DecompressBufSize);
1383 size_t UCSize = DecompressBufSize;
1385 Buffer, UCSize);
1386 if (E)
1388 DecompressBuf = reinterpret_cast<const uint8_t *>(Buffer);
1390}
1391
1393 const uint8_t *BufStart =
1394 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
1395
1396 for (auto &Entry : SecHdrTable) {
1397 // Skip empty section.
1398 if (!Entry.Size)
1399 continue;
1400
1401 // Skip sections without inlined functions when SkipFlatProf is true.
1403 continue;
1404
1405 const uint8_t *SecStart = BufStart + Entry.Offset;
1406 uint64_t SecSize = Entry.Size;
1407
1408 // If the section is compressed, decompress it into a buffer
1409 // DecompressBuf before reading the actual data. The pointee of
1410 // 'Data' will be changed to buffer hold by DecompressBuf
1411 // temporarily when reading the actual data.
1412 bool isCompressed = hasSecFlag(Entry, SecCommonFlags::SecFlagCompress);
1413 if (isCompressed) {
1414 const uint8_t *DecompressBuf;
1415 uint64_t DecompressBufSize;
1416 if (std::error_code EC = decompressSection(
1417 SecStart, SecSize, DecompressBuf, DecompressBufSize))
1418 return EC;
1419 SecStart = DecompressBuf;
1420 SecSize = DecompressBufSize;
1421 }
1422
1423 if (std::error_code EC = readOneSection(SecStart, SecSize, Entry))
1424 return EC;
1425 if (Data != SecStart + SecSize)
1427
1428 // Change the pointee of 'Data' from DecompressBuf to original Buffer.
1429 if (isCompressed) {
1430 Data = BufStart + Entry.Offset;
1431 End = BufStart + Buffer->getBufferSize();
1432 }
1433 }
1434
1436}
1437
1438std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
1439 if (Magic == SPMagic())
1442}
1443
1444std::error_code SampleProfileReaderExtBinary::verifySPMagic(uint64_t Magic) {
1445 if (Magic == SPMagic(SPF_Ext_Binary))
1448}
1449
1451 auto Size = readNumber<size_t>();
1452 if (std::error_code EC = Size.getError())
1453 return EC;
1454
1455 // Normally if useMD5 is true, the name table should have MD5 values, not
1456 // strings, however in the case that ExtBinary profile has multiple name
1457 // tables mixing string and MD5, all of them have to be normalized to use MD5,
1458 // because optimization passes can only handle either type.
1459 bool UseMD5 = useMD5();
1460
1461 std::vector<FunctionId> TableVec;
1462 TableVec.reserve(*Size);
1463 if (!ProfileIsCS) {
1464 MD5SampleContextTable.clear();
1465 if (UseMD5)
1466 MD5SampleContextTable.reserve(*Size);
1467 else
1468 // If we are using strings, delay MD5 computation since only a portion of
1469 // names are used by top level functions. Use 0 to indicate MD5 value is
1470 // to be calculated as no known string has a MD5 value of 0.
1471 MD5SampleContextTable.resize(*Size);
1472 }
1473 for (size_t I = 0; I < *Size; ++I) {
1474 auto Name(readString());
1475 if (std::error_code EC = Name.getError())
1476 return EC;
1477 if (UseMD5) {
1478 FunctionId FID(*Name);
1479 if (!ProfileIsCS)
1480 MD5SampleContextTable.emplace_back(FID.getHashCode());
1481 TableVec.emplace_back(FID);
1482 } else
1483 TableVec.push_back(FunctionId(*Name));
1484 }
1485 if (!ProfileIsCS)
1487 if (UseMD5)
1488 NameTable =
1489 std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
1490 else
1491 NameTable =
1492 std::make_unique<StringSampleProfileNameTable>(std::move(TableVec));
1494}
1495
1497 bool IsMD5, bool FixedLengthMD5, bool IsEytzinger) {
1498 if (IsEytzinger)
1499 return readNameTableSecEytzinger(IsMD5, FixedLengthMD5);
1500 return readNameTableSecLegacy(IsMD5, FixedLengthMD5);
1501}
1502
1503// Read the Eytzinger layout for SecNameTable from an ExtBinary MD5 profile.
1504//
1505// The section consists of three sequential ULEB128 symbol counts (Nested, Flat,
1506// and Inlinees) followed by their corresponding arrays of 64-bit MD5 hash keys
1507// laid out in Eytzinger order.
1509 bool IsMD5, bool FixedLengthMD5) {
1510 assert(IsMD5 && "Eytzinger name tables require MD5 representation");
1511 if (!IsMD5)
1513
1514 // Read the table sizes for Nested, flat, and inlinee symbols.
1515 std::array<uint64_t, static_cast<size_t>(EytzingerSpan::NumSpans)> Counts;
1516 for (uint64_t &Count : Counts) {
1517 auto ValOrErr = readNumber<uint64_t>();
1518 if (std::error_code EC = ValOrErr.getError())
1519 return EC;
1520 Count = *ValOrErr;
1521 }
1522 auto [NumNested, NumFlat, NumInlinees] = Counts;
1523
1524 // Guard against unsigned overflow in total entry computation.
1525 if (NumNested > std::numeric_limits<uint32_t>::max() ||
1526 NumFlat > std::numeric_limits<uint32_t>::max() ||
1527 NumInlinees > std::numeric_limits<uint32_t>::max())
1529
1530 uint64_t TotalEntries = NumNested + NumFlat + NumInlinees;
1531 if (static_cast<size_t>(End - Data) < TotalEntries * sizeof(uint64_t))
1533
1534 NameTable = std::make_unique<EytzingerSampleProfileNameTable>(
1535 reinterpret_cast<const support::ulittle64_t *>(Data), NumNested, NumFlat,
1536 NumInlinees);
1537
1538 if (!ProfileIsCS)
1539 MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
1540 Data = Data + TotalEntries * sizeof(uint64_t);
1542}
1543
1544std::error_code
1546 bool FixedLengthMD5) {
1547 if (FixedLengthMD5) {
1548 if (!IsMD5)
1549 errs() << "If FixedLengthMD5 is true, UseMD5 has to be true";
1550 auto Size = readNumber<size_t>();
1551 if (std::error_code EC = Size.getError())
1552 return EC;
1553
1554 assert(Data + (*Size) * sizeof(uint64_t) == End &&
1555 "Fixed length MD5 name table does not contain specified number of "
1556 "entries");
1557 if (Data + (*Size) * sizeof(uint64_t) > End)
1559
1560 if (LazyLoadNameTable) {
1561 NameTable = std::make_unique<LazySampleProfileNameTable>(Data, *Size);
1562 } else {
1563 std::vector<FunctionId> TableVec;
1564 TableVec.reserve(*Size);
1565 for (size_t I = 0; I < *Size; ++I) {
1566 using namespace support;
1567 uint64_t FID = endian::read<uint64_t, unaligned>(
1568 Data + I * sizeof(uint64_t), endianness::little);
1569 TableVec.emplace_back(FunctionId(FID));
1570 }
1571 NameTable =
1572 std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
1573 }
1574 if (!ProfileIsCS)
1575 MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
1576 Data = Data + (*Size) * sizeof(uint64_t);
1578 }
1579
1580 if (IsMD5) {
1581 assert(!FixedLengthMD5 && "FixedLengthMD5 should be unreachable here");
1582 auto Size = readNumber<size_t>();
1583 if (std::error_code EC = Size.getError())
1584 return EC;
1585
1586 std::vector<FunctionId> TableVec;
1587 TableVec.reserve(*Size);
1588 if (!ProfileIsCS)
1589 MD5SampleContextTable.resize(*Size);
1590 for (size_t I = 0; I < *Size; ++I) {
1591 auto FID = readNumber<uint64_t>();
1592 if (std::error_code EC = FID.getError())
1593 return EC;
1594 if (!ProfileIsCS)
1596 TableVec.emplace_back(FunctionId(*FID));
1597 }
1598 if (!ProfileIsCS)
1600 NameTable =
1601 std::make_unique<MD5SampleProfileNameTable>(std::move(TableVec));
1603 }
1604
1606}
1607
1608// Read in the CS name table section, which basically contains a list of context
1609// vectors. Each element of a context vector, aka a frame, refers to the
1610// underlying raw function names that are stored in the name table, as well as
1611// a callsite identifier that only makes sense for non-leaf frames.
1613 auto Size = readNumber<size_t>();
1614 if (std::error_code EC = Size.getError())
1615 return EC;
1616
1617 CSNameTable.clear();
1618 CSNameTable.reserve(*Size);
1619 if (ProfileIsCS) {
1620 // Delay MD5 computation of CS context until they are needed. Use 0 to
1621 // indicate MD5 value is to be calculated as no known string has a MD5
1622 // value of 0.
1623 MD5SampleContextTable.clear();
1624 MD5SampleContextTable.resize(*Size);
1626 }
1627 for (size_t I = 0; I < *Size; ++I) {
1628 CSNameTable.emplace_back(SampleContextFrameVector());
1629 auto ContextSize = readNumber<uint32_t>();
1630 if (std::error_code EC = ContextSize.getError())
1631 return EC;
1632 for (uint32_t J = 0; J < *ContextSize; ++J) {
1633 auto FName(readStringFromTable());
1634 if (std::error_code EC = FName.getError())
1635 return EC;
1636 auto LineOffset = readNumber<uint64_t>();
1637 if (std::error_code EC = LineOffset.getError())
1638 return EC;
1639
1640 if (!isOffsetLegal(*LineOffset))
1642
1643 auto Discriminator = readNumber<uint64_t>();
1644 if (std::error_code EC = Discriminator.getError())
1645 return EC;
1646
1647 CSNameTable.back().emplace_back(
1648 FName.get(), LineLocation(LineOffset.get(), Discriminator.get()));
1649 }
1650 }
1651
1653}
1654
1655std::error_code
1657 if (Data < End) {
1658 if (ProfileIsProbeBased) {
1659 auto Checksum = readNumber<uint64_t>();
1660 if (std::error_code EC = Checksum.getError())
1661 return EC;
1662 if (FProfile)
1663 FProfile->setFunctionHash(*Checksum);
1664 }
1665
1666 if (ProfileHasAttribute) {
1667 auto Attributes = readNumber<uint32_t>();
1668 if (std::error_code EC = Attributes.getError())
1669 return EC;
1670 if (FProfile)
1671 FProfile->getContext().setAllAttributes(*Attributes);
1672 }
1673
1674 if (!ProfileIsCS) {
1675 // Read all the attributes for inlined function calls.
1676 auto NumCallsites = readNumber<uint32_t>();
1677 if (std::error_code EC = NumCallsites.getError())
1678 return EC;
1679
1680 for (uint32_t J = 0; J < *NumCallsites; ++J) {
1681 auto LineOffset = readNumber<uint64_t>();
1682 if (std::error_code EC = LineOffset.getError())
1683 return EC;
1684
1685 auto Discriminator = readNumber<uint64_t>();
1686 if (std::error_code EC = Discriminator.getError())
1687 return EC;
1688
1689 auto FContextHash(readSampleContextFromTable());
1690 if (std::error_code EC = FContextHash.getError())
1691 return EC;
1692
1693 auto &[FContext, Hash] = *FContextHash;
1694 FunctionSamples *CalleeProfile = nullptr;
1695 if (FProfile) {
1696 CalleeProfile = const_cast<FunctionSamples *>(
1698 *LineOffset, *Discriminator))[FContext.getFunction()]);
1699 }
1700 if (std::error_code EC = readFuncMetadata(CalleeProfile))
1701 return EC;
1702 }
1703 }
1704 }
1705
1707}
1708
1711 if (FuncMetadataIndex.empty())
1713
1714 for (auto *FProfile : Profiles) {
1715 auto R = FuncMetadataIndex.find(FProfile->getContext().getHashCode());
1716 if (R == FuncMetadataIndex.end())
1717 continue;
1718
1719 Data = R->second.first;
1720 End = R->second.second;
1721 if (std::error_code EC = readFuncMetadata(FProfile))
1722 return EC;
1723 assert(Data == End && "More data is read than expected");
1724 }
1726}
1727
1729 while (Data < End) {
1730 auto FContextHash(readSampleContextFromTable());
1731 if (std::error_code EC = FContextHash.getError())
1732 return EC;
1733 auto &[FContext, Hash] = *FContextHash;
1734 FunctionSamples *FProfile = nullptr;
1735 auto It = Profiles.find(FContext);
1736 if (It != Profiles.end())
1737 FProfile = &It->second;
1738
1739 const uint8_t *Start = Data;
1740 if (std::error_code EC = readFuncMetadata(FProfile))
1741 return EC;
1742
1743 FuncMetadataIndex[FContext.getHashCode()] = {Start, Data};
1744 }
1745
1746 assert(Data == End && "More data is read than expected");
1748}
1749
1750std::error_code
1752 SecHdrTableEntry Entry;
1754 if (std::error_code EC = Type.getError())
1755 return EC;
1756 Entry.Type = static_cast<SecType>(*Type);
1757
1758 // Reject a section whose encoding is newer than the declared file version.
1759 if ((Entry.Type == SecCompositeProfile ||
1760 Entry.Type == SecCompositeFuncOffsetTable) &&
1763
1764 auto Flags = readUnencodedNumber<uint64_t>();
1765 if (std::error_code EC = Flags.getError())
1766 return EC;
1767 Entry.Flags = *Flags;
1768
1770 if (std::error_code EC = Offset.getError())
1771 return EC;
1772 Entry.Offset = *Offset;
1773
1775 if (std::error_code EC = Size.getError())
1776 return EC;
1777 Entry.Size = *Size;
1778
1779 Entry.LayoutIndex = Idx;
1780 SecHdrTable.push_back(std::move(Entry));
1782}
1783
1785 auto EntryNum = readUnencodedNumber<uint64_t>();
1786 if (std::error_code EC = EntryNum.getError())
1787 return EC;
1788
1789 for (uint64_t i = 0; i < (*EntryNum); i++)
1790 if (std::error_code EC = readSecHdrTableEntry(i))
1791 return EC;
1792
1794}
1795
1797 const uint8_t *BufStart =
1798 reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
1799 Data = BufStart;
1800 End = BufStart + Buffer->getBufferSize();
1801
1802 if (std::error_code EC = readMagicIdent())
1803 return EC;
1804
1805 if (std::error_code EC = readSecHdrTable())
1806 return EC;
1807
1809}
1810
1812 uint64_t Size = 0;
1813 for (auto &Entry : SecHdrTable) {
1814 if (Entry.Type == Type)
1815 Size += Entry.Size;
1816 }
1817 return Size;
1818}
1819
1821 // Sections in SecHdrTable is not necessarily in the same order as
1822 // sections in the profile because section like FuncOffsetTable needs
1823 // to be written after section LBRProfile but needs to be read before
1824 // section LBRProfile, so we cannot simply use the last entry in
1825 // SecHdrTable to calculate the file size.
1826 uint64_t FileSize = 0;
1827 for (auto &Entry : SecHdrTable) {
1828 FileSize = std::max(Entry.Offset + Entry.Size, FileSize);
1829 }
1830 return FileSize;
1831}
1832
1833static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) {
1834 std::string Flags;
1836 Flags.append("{compressed,");
1837 else
1838 Flags.append("{");
1839
1841 Flags.append("flat,");
1842
1843 switch (Entry.Type) {
1844 case SecNameTable:
1846 Flags.append("eytzinger,");
1848 Flags.append("fixlenmd5,");
1850 Flags.append("md5,");
1852 Flags.append("uniq,");
1853 break;
1854 case SecProfSummary:
1856 Flags.append("partial,");
1858 Flags.append("context,");
1860 Flags.append("preInlined,");
1862 Flags.append("fs-discriminator,");
1863 break;
1864 case SecFuncOffsetTable:
1867 Flags.append("ordered,");
1869 Flags.append("eytzinger,");
1870 break;
1871 case SecFuncMetadata:
1873 Flags.append("probe,");
1875 Flags.append("attr,");
1876 break;
1879 Flags.append("md5,");
1880 break;
1881 default:
1882 break;
1883 }
1884 char &last = Flags.back();
1885 if (last == ',')
1886 last = '}';
1887 else
1888 Flags.append("}");
1889 return Flags;
1890}
1891
1893 uint64_t TotalSecsSize = 0;
1894 for (auto &Entry : SecHdrTable) {
1895 OS << getSecName(Entry.Type) << " - Offset: " << Entry.Offset
1896 << ", Size: " << Entry.Size << ", Flags: " << getSecFlagsStr(Entry)
1897 << "\n";
1898 ;
1899 TotalSecsSize += Entry.Size;
1900 }
1901 uint64_t HeaderSize = SecHdrTable.front().Offset;
1902 assert(HeaderSize + TotalSecsSize == getFileSize() &&
1903 "Size of 'header + sections' doesn't match the total size of profile");
1904
1905 OS << "Header Size: " << HeaderSize << "\n";
1906 OS << "Total Sections Size: " << TotalSecsSize << "\n";
1907 OS << "File Size: " << getFileSize() << "\n";
1908 return true;
1909}
1910
1912 // Read and check the magic identifier.
1913 auto Magic = readNumber<uint64_t>();
1914 if (std::error_code EC = Magic.getError())
1915 return EC;
1916 else if (std::error_code EC = verifySPMagic(*Magic))
1917 return EC;
1918
1919 // Read the version number.
1921 if (std::error_code EC = Version.getError())
1922 return EC;
1926
1928}
1929
1931 Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
1932 End = Data + Buffer->getBufferSize();
1933
1934 if (std::error_code EC = readMagicIdent())
1935 return EC;
1936
1937 if (std::error_code EC = readSummary())
1938 return EC;
1939
1940 if (std::error_code EC = readNameTable())
1941 return EC;
1943}
1944
1945std::error_code SampleProfileReaderBinary::readSummaryEntry(
1946 std::vector<ProfileSummaryEntry> &Entries) {
1947 auto Cutoff = readNumber<uint64_t>();
1948 if (std::error_code EC = Cutoff.getError())
1949 return EC;
1950
1951 auto MinBlockCount = readNumber<uint64_t>();
1952 if (std::error_code EC = MinBlockCount.getError())
1953 return EC;
1954
1955 auto NumBlocks = readNumber<uint64_t>();
1956 if (std::error_code EC = NumBlocks.getError())
1957 return EC;
1958
1959 Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
1961}
1962
1964 auto TotalCount = readNumber<uint64_t>();
1965 if (std::error_code EC = TotalCount.getError())
1966 return EC;
1967
1968 auto MaxBlockCount = readNumber<uint64_t>();
1969 if (std::error_code EC = MaxBlockCount.getError())
1970 return EC;
1971
1972 auto MaxFunctionCount = readNumber<uint64_t>();
1973 if (std::error_code EC = MaxFunctionCount.getError())
1974 return EC;
1975
1976 auto NumBlocks = readNumber<uint64_t>();
1977 if (std::error_code EC = NumBlocks.getError())
1978 return EC;
1979
1980 auto NumFunctions = readNumber<uint64_t>();
1981 if (std::error_code EC = NumFunctions.getError())
1982 return EC;
1983
1984 auto NumSummaryEntries = readNumber<uint64_t>();
1985 if (std::error_code EC = NumSummaryEntries.getError())
1986 return EC;
1987
1988 std::vector<ProfileSummaryEntry> Entries;
1989 for (unsigned i = 0; i < *NumSummaryEntries; i++) {
1990 std::error_code EC = readSummaryEntry(Entries);
1991 if (EC != sampleprof_error::success)
1992 return EC;
1993 }
1994 Summary = std::make_unique<ProfileSummary>(
1995 ProfileSummary::PSK_Sample, Entries, *TotalCount, *MaxBlockCount, 0,
1996 *MaxFunctionCount, *NumBlocks, *NumFunctions);
1997
1999}
2000
2001/// Return whether Buffer starts with ExpectedMagic without reading beyond it.
2002static bool hasBinaryFormat(const MemoryBuffer &Buffer,
2003 uint64_t ExpectedMagic) {
2004 const uint8_t *Data =
2005 reinterpret_cast<const uint8_t *>(Buffer.getBufferStart());
2006 const uint8_t *End = reinterpret_cast<const uint8_t *>(Buffer.getBufferEnd());
2008 uint64_t Magic = decodeULEB128(Data, nullptr, End, nullptr, &DecodeError);
2009 return DecodeError == ULEB128DecodeError::None && Magic == ExpectedMagic;
2010}
2011
2015
2019
2021 uint32_t dummy;
2022 if (!GcovBuffer.readInt(dummy))
2025}
2026
2028 if (sizeof(T) <= sizeof(uint32_t)) {
2029 uint32_t Val;
2030 if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
2031 return static_cast<T>(Val);
2032 } else if (sizeof(T) <= sizeof(uint64_t)) {
2033 uint64_t Val;
2034 if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max())
2035 return static_cast<T>(Val);
2036 }
2037
2038 std::error_code EC = sampleprof_error::malformed;
2039 reportError(0, EC.message());
2040 return EC;
2041}
2042
2044 StringRef Str;
2045 if (!GcovBuffer.readString(Str))
2047 return Str;
2048}
2049
2051 // Read the magic identifier.
2052 if (!GcovBuffer.readGCDAFormat())
2054
2055 // Read the version number. Note - the GCC reader does not validate this
2056 // version, but the profile creator generates v704.
2057 GCOV::GCOVVersion version;
2058 if (!GcovBuffer.readGCOVVersion(version))
2060
2061 if (version != GCOV::V407)
2063
2064 // Skip the empty integer.
2065 if (std::error_code EC = skipNextWord())
2066 return EC;
2067
2069}
2070
2072 uint32_t Tag;
2073 if (!GcovBuffer.readInt(Tag))
2075
2076 if (Tag != Expected)
2078
2079 if (std::error_code EC = skipNextWord())
2080 return EC;
2081
2083}
2084
2086 if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
2087 return EC;
2088
2089 uint32_t Size;
2090 if (!GcovBuffer.readInt(Size))
2092
2093 for (uint32_t I = 0; I < Size; ++I) {
2094 StringRef Str;
2095 if (!GcovBuffer.readString(Str))
2097 Names.push_back(std::string(Str));
2098 }
2099
2101}
2102
2104 if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
2105 return EC;
2106
2107 uint32_t NumFunctions;
2108 if (!GcovBuffer.readInt(NumFunctions))
2110
2111 InlineCallStack Stack;
2112 for (uint32_t I = 0; I < NumFunctions; ++I)
2113 if (std::error_code EC = readOneFunctionProfile(Stack, true, 0))
2114 return EC;
2115
2118}
2119
2121 const InlineCallStack &InlineStack, bool Update, uint32_t Offset) {
2122 uint64_t HeadCount = 0;
2123 if (InlineStack.size() == 0)
2124 if (!GcovBuffer.readInt64(HeadCount))
2126
2127 uint32_t NameIdx;
2128 if (!GcovBuffer.readInt(NameIdx))
2130
2131 StringRef Name(Names[NameIdx]);
2132
2133 uint32_t NumPosCounts;
2134 if (!GcovBuffer.readInt(NumPosCounts))
2136
2137 uint32_t NumCallsites;
2138 if (!GcovBuffer.readInt(NumCallsites))
2140
2141 FunctionSamples *FProfile = nullptr;
2142 if (InlineStack.size() == 0) {
2143 // If this is a top function that we have already processed, do not
2144 // update its profile again. This happens in the presence of
2145 // function aliases. Since these aliases share the same function
2146 // body, there will be identical replicated profiles for the
2147 // original function. In this case, we simply not bother updating
2148 // the profile of the original function.
2149 FProfile = &Profiles[FunctionId(Name)];
2150 FProfile->addHeadSamples(HeadCount);
2151 if (FProfile->getTotalSamples() > 0)
2152 Update = false;
2153 } else {
2154 // Otherwise, we are reading an inlined instance. The top of the
2155 // inline stack contains the profile of the caller. Insert this
2156 // callee in the caller's CallsiteMap.
2157 FunctionSamples *CallerProfile = InlineStack.front();
2158 uint32_t LineOffset = Offset >> 16;
2159 uint32_t Discriminator = Offset & 0xffff;
2160 FProfile = &CallerProfile->functionSamplesAt(
2161 LineLocation(LineOffset, Discriminator))[FunctionId(Name)];
2162 }
2163 FProfile->setFunction(FunctionId(Name));
2164 FProfile->reserveBodySamples(NumPosCounts);
2165
2166 for (uint32_t I = 0; I < NumPosCounts; ++I) {
2168 if (!GcovBuffer.readInt(Offset))
2170
2171 uint32_t NumTargets;
2172 if (!GcovBuffer.readInt(NumTargets))
2174
2175 uint64_t Count;
2176 if (!GcovBuffer.readInt64(Count))
2178
2179 // The line location is encoded in the offset as:
2180 // high 16 bits: line offset to the start of the function.
2181 // low 16 bits: discriminator.
2182 uint32_t LineOffset = Offset >> 16;
2183 uint32_t Discriminator = Offset & 0xffff;
2184
2185 InlineCallStack NewStack;
2186 NewStack.push_back(FProfile);
2187 llvm::append_range(NewStack, InlineStack);
2188 if (Update) {
2189 // Walk up the inline stack, adding the samples on this line to
2190 // the total sample count of the callers in the chain.
2191 for (auto *CallerProfile : NewStack)
2192 CallerProfile->addTotalSamples(Count);
2193
2194 // Update the body samples for the current profile.
2195 FProfile->addBodySamples(LineOffset, Discriminator, Count);
2196 }
2197
2198 // Process the list of functions called at an indirect call site.
2199 // These are all the targets that a function pointer (or virtual
2200 // function) resolved at runtime.
2201 for (uint32_t J = 0; J < NumTargets; J++) {
2202 uint32_t HistVal;
2203 if (!GcovBuffer.readInt(HistVal))
2205
2206 if (HistVal != HIST_TYPE_INDIR_CALL_TOPN)
2208
2209 uint64_t TargetIdx;
2210 if (!GcovBuffer.readInt64(TargetIdx))
2212 StringRef TargetName(Names[TargetIdx]);
2213
2214 uint64_t TargetCount;
2215 if (!GcovBuffer.readInt64(TargetCount))
2217
2218 if (Update)
2219 FProfile->addCalledTargetSamples(LineOffset, Discriminator,
2220 FunctionId(TargetName), TargetCount);
2221 }
2222 }
2223
2224 // Process all the inlined callers into the current function. These
2225 // are all the callsites that were inlined into this function.
2226 for (uint32_t I = 0; I < NumCallsites; I++) {
2227 // The offset is encoded as:
2228 // high 16 bits: line offset to the start of the function.
2229 // low 16 bits: discriminator.
2231 if (!GcovBuffer.readInt(Offset))
2233 InlineCallStack NewStack;
2234 NewStack.push_back(FProfile);
2235 llvm::append_range(NewStack, InlineStack);
2236 if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
2237 return EC;
2238 }
2239
2241}
2242
2243/// Read a GCC AutoFDO profile.
2244///
2245/// This format is generated by the Linux Perf conversion tool at
2246/// https://github.com/google/autofdo.
2248 assert(!ProfileIsFSDisciminator && "Gcc profiles not support FSDisciminator");
2249 // Read the string table.
2250 if (std::error_code EC = readNameTable())
2251 return EC;
2252
2253 // Read the source profile.
2254 if (std::error_code EC = readFunctionProfiles())
2255 return EC;
2256
2258}
2259
2261 StringRef Contents = Buffer.getBuffer();
2262 // Preserve exact magic matching, including a magic-only eight-byte buffer.
2263 return Contents.starts_with("adcg*704") &&
2264 (Contents.size() == 8 || Contents[8] == '\0');
2265}
2266
2268 // If the reader uses MD5 to represent string, we can't remap it because
2269 // we don't know what the original function names were.
2270 if (Reader.useMD5()) {
2271 Ctx.diagnose(DiagnosticInfoSampleProfile(
2272 Reader.getBuffer()->getBufferIdentifier(),
2273 "Profile data remapping cannot be applied to profile data "
2274 "using MD5 names (original mangled names are not available).",
2275 DS_Warning));
2276 return;
2277 }
2278
2279 // CSSPGO-TODO: Remapper is not yet supported.
2280 // We will need to remap the entire context string.
2281 assert(Remappings && "should be initialized while creating remapper");
2282 for (auto &Sample : Reader.getProfiles()) {
2283 DenseSet<FunctionId> NamesInSample;
2284 Sample.second.findAllNames(NamesInSample);
2285 for (auto &Name : NamesInSample) {
2286 StringRef NameStr = Name.stringRef();
2287 if (auto Key = Remappings->insert(NameStr))
2288 NameMap.insert({Key, NameStr});
2289 }
2290 }
2291
2292 RemappingApplied = true;
2293}
2294
2295std::optional<StringRef>
2297 if (auto Key = Remappings->lookup(Fname)) {
2298 StringRef Result = NameMap.lookup(Key);
2299 if (!Result.empty())
2300 return Result;
2301 }
2302 return std::nullopt;
2303}
2304
2305/// Prepare a memory buffer for the contents of \p Filename.
2306///
2307/// \returns an error code indicating the status of the buffer.
2310 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
2311 : FS.getBufferForFile(Filename);
2312 if (std::error_code EC = BufferOrErr.getError())
2313 return EC;
2314 auto Buffer = std::move(BufferOrErr.get());
2315
2316 return std::move(Buffer);
2317}
2318
2319/// Create a sample profile reader based on the format of the input file.
2320///
2321/// \param Filename The file to open.
2322///
2323/// \param C The LLVM context to use to emit diagnostics.
2324///
2325/// \param P The FSDiscriminatorPass.
2326///
2327/// \param RemapFilename The file used for profile remapping.
2328///
2329/// \returns an error code indicating the status of the created reader.
2330ErrorOr<std::unique_ptr<SampleProfileReader>>
2333 StringRef RemapFilename) {
2334 auto BufferOrError = setupMemoryBuffer(Filename, FS);
2335 if (std::error_code EC = BufferOrError.getError())
2336 return EC;
2337 return create(BufferOrError.get(), C, FS, P, RemapFilename);
2338}
2339
2340/// Create a sample profile remapper from the given input, to remap the
2341/// function names in the given profile data.
2342///
2343/// \param Filename The file to open.
2344///
2345/// \param Reader The profile reader the remapper is going to be applied to.
2346///
2347/// \param C The LLVM context to use to emit diagnostics.
2348///
2349/// \returns an error code indicating the status of the created reader.
2352 vfs::FileSystem &FS,
2353 SampleProfileReader &Reader,
2354 LLVMContext &C) {
2355 auto BufferOrError = setupMemoryBuffer(Filename, FS);
2356 if (std::error_code EC = BufferOrError.getError())
2357 return EC;
2358 return create(BufferOrError.get(), Reader, C);
2359}
2360
2361/// Create a sample profile remapper from the given input, to remap the
2362/// function names in the given profile data.
2363///
2364/// \param B The memory buffer to create the reader from (assumes ownership).
2365///
2366/// \param C The LLVM context to use to emit diagnostics.
2367///
2368/// \param Reader The profile reader the remapper is going to be applied to.
2369///
2370/// \returns an error code indicating the status of the created reader.
2372SampleProfileReaderItaniumRemapper::create(std::unique_ptr<MemoryBuffer> &B,
2373 SampleProfileReader &Reader,
2374 LLVMContext &C) {
2375 auto Remappings = std::make_unique<SymbolRemappingReader>();
2376 if (Error E = Remappings->read(*B)) {
2378 std::move(E), [&](const SymbolRemappingParseError &ParseError) {
2379 C.diagnose(DiagnosticInfoSampleProfile(B->getBufferIdentifier(),
2380 ParseError.getLineNum(),
2381 ParseError.getMessage()));
2382 });
2384 }
2385
2386 return std::make_unique<SampleProfileReaderItaniumRemapper>(
2387 std::move(B), std::move(Remappings), Reader);
2388}
2389
2390/// Create a sample profile reader based on the format of the input data.
2391///
2392/// \param B The memory buffer to create the reader from (assumes ownership).
2393///
2394/// \param C The LLVM context to use to emit diagnostics.
2395///
2396/// \param P The FSDiscriminatorPass.
2397///
2398/// \param RemapFilename The file used for profile remapping.
2399///
2400/// \returns an error code indicating the status of the created reader.
2402SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
2404 StringRef RemapFilename) {
2405 std::unique_ptr<SampleProfileReader> Reader;
2407 Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C));
2409 Reader.reset(new SampleProfileReaderExtBinary(std::move(B), C));
2411 Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
2413 Reader.reset(new SampleProfileReaderText(std::move(B), C));
2414 else
2416
2417 if (!RemapFilename.empty()) {
2419 RemapFilename, FS, *Reader, C);
2420 if (std::error_code EC = ReaderOrErr.getError()) {
2421 std::string Msg = "Could not create remapper: " + EC.message();
2422 C.diagnose(DiagnosticInfoSampleProfile(RemapFilename, Msg));
2423 return EC;
2424 }
2425 Reader->Remapper = std::move(ReaderOrErr.get());
2426 }
2427
2428 if (std::error_code EC = Reader->readHeader()) {
2429 return EC;
2430 }
2431
2432 Reader->setDiscriminatorMaskedBitFrom(P);
2433
2434 return std::move(Reader);
2435}
2436
2437// For text and GCC file formats, we compute the summary after reading the
2438// 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:854
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:861
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:880
void reserveBodySamples(size_t NumEntries)
Definition SampleProf.h:908
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:894
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:888
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:912
void setAllAttributes(uint32_t A)
Definition SampleProf.h:720
FunctionId getFunction() const
Definition SampleProf.h:726
std::string toString() const
Definition SampleProf.h:742
bool isPrefixOf(const SampleContext &That) const
Definition SampleProf.h:805
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:423
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:845
static bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:336
SortedVectorMap< LineLocation, SampleRecord, 0 > BodySampleMap
Definition SampleProf.h:841
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:264
@ SecFlagHasVTableTypeProf
SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
Definition SampleProf.h:267
@ SecFlagPartial
SecFlagPartial means the profile is for common/shared code.
Definition SampleProf.h:255
@ SecFlagFSDiscriminator
SecFlagFSDiscriminator means this profile uses flow-sensitive discriminators.
Definition SampleProf.h:261
@ SecFlagFullContext
SecFlagContext means this is context-sensitive flat profile for CSSPGO.
Definition SampleProf.h:258
static StringRef getProfTypeName(uint64_t Type)
Definition SampleProf.h:197
SmallVector< SampleContextFrame, 1 > SampleContextFrameVector
Definition SampleProf.h:614
static std::string getSecName(SecType Type)
Definition SampleProf.h:165
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:403
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 >
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingAdd(T X, T Y, bool *ResultOverflowed=nullptr)
Add two unsigned integers, X and Y, of type T.
Definition MathExtras.h:604
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:352
const uint8_t * Start
First byte of the retained section.
const uint8_t * End
One-past-the-end byte of the retained section.