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