[RISCV] Refactor predicates for rvv intrinsic patterns.
[llvm-project.git] / llvm / lib / MC / MCPseudoProbe.cpp
blob35eafec7216959b4666263a4aaa06d59063a56e4
1 //===- lib/MC/MCPseudoProbe.cpp - Pseudo probe encoding support ----------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/MC/MCPseudoProbe.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/IR/PseudoProbe.h"
12 #include "llvm/MC/MCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCFragment.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCObjectStreamer.h"
18 #include "llvm/MC/MCSymbol.h"
19 #include "llvm/Support/Endian.h"
20 #include "llvm/Support/LEB128.h"
21 #include "llvm/Support/MD5.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <limits>
26 #include <memory>
27 #include <sstream>
28 #include <vector>
30 #define DEBUG_TYPE "mcpseudoprobe"
32 using namespace llvm;
33 using namespace support;
35 #ifndef NDEBUG
36 int MCPseudoProbeTable::DdgPrintIndent = 0;
37 #endif
39 static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A,
40 const MCSymbol *B) {
41 MCContext &Context = MCOS->getContext();
42 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
43 const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
44 const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
45 const MCExpr *AddrDelta =
46 MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
47 return AddrDelta;
50 void MCPseudoProbe::emit(MCObjectStreamer *MCOS,
51 const MCPseudoProbe *LastProbe) const {
52 bool IsSentinel = isSentinelProbe(getAttributes());
53 assert((LastProbe || IsSentinel) &&
54 "Last probe should not be null for non-sentinel probes");
56 // Emit Index
57 MCOS->emitULEB128IntValue(Index);
58 // Emit Type and the flag:
59 // Type (bit 0 to 3), with bit 4 to 6 for attributes.
60 // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether
61 // the following field is a symbolic code address or an address delta.
62 // Emit FS discriminator
63 assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");
64 auto NewAttributes = Attributes;
65 if (Discriminator)
66 NewAttributes |= (uint32_t)PseudoProbeAttributes::HasDiscriminator;
67 assert(NewAttributes <= 0x7 &&
68 "Probe attributes too big to encode, exceeding 7");
69 uint8_t PackedType = Type | (NewAttributes << 4);
70 uint8_t Flag =
71 !IsSentinel ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0;
72 MCOS->emitInt8(Flag | PackedType);
74 if (!IsSentinel) {
75 // Emit the delta between the address label and LastProbe.
76 const MCExpr *AddrDelta =
77 buildSymbolDiff(MCOS, Label, LastProbe->getLabel());
78 int64_t Delta;
79 if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {
80 MCOS->emitSLEB128IntValue(Delta);
81 } else {
82 MCOS->insert(new MCPseudoProbeAddrFragment(AddrDelta));
84 } else {
85 // Emit the GUID of the split function that the sentinel probe represents.
86 MCOS->emitInt64(Guid);
89 if (Discriminator)
90 MCOS->emitULEB128IntValue(Discriminator);
92 LLVM_DEBUG({
93 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
94 dbgs() << "Probe: " << Index << "\n";
95 });
98 void MCPseudoProbeInlineTree::addPseudoProbe(
99 const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {
100 // The function should not be called on the root.
101 assert(isRoot() && "Should only be called on root");
103 // When it comes here, the input look like:
104 // Probe: GUID of C, ...
105 // InlineStack: [88, A], [66, B]
106 // which means, Function A inlines function B at call site with a probe id of
107 // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0,
108 // A], [88, B], [66, C]} to locate the tree node where the probe should be
109 // added. Note that the edge [0, A] means A is the top-level function we are
110 // emitting probes for.
112 // Make a [0, A] edge.
113 // An empty inline stack means the function that the probe originates from
114 // is a top-level function.
115 InlineSite Top;
116 if (InlineStack.empty()) {
117 Top = InlineSite(Probe.getGuid(), 0);
118 } else {
119 Top = InlineSite(std::get<0>(InlineStack.front()), 0);
122 auto *Cur = getOrAddNode(Top);
124 // Make interior edges by walking the inline stack. Once it's done, Cur should
125 // point to the node that the probe originates from.
126 if (!InlineStack.empty()) {
127 auto Iter = InlineStack.begin();
128 auto Index = std::get<1>(*Iter);
129 Iter++;
130 for (; Iter != InlineStack.end(); Iter++) {
131 // Make an edge by using the previous probe id and current GUID.
132 Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));
133 Index = std::get<1>(*Iter);
135 Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index));
138 Cur->Probes.push_back(Probe);
141 void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,
142 const MCPseudoProbe *&LastProbe) {
143 LLVM_DEBUG({
144 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
145 dbgs() << "Group [\n";
146 MCPseudoProbeTable::DdgPrintIndent += 2;
148 assert(!isRoot() && "Root should be handled seperately");
150 // Emit probes grouped by GUID.
151 LLVM_DEBUG({
152 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
153 dbgs() << "GUID: " << Guid << "\n";
155 // Emit Guid
156 MCOS->emitInt64(Guid);
157 // Emit number of probes in this node, including a sentinel probe for
158 // top-level functions if needed.
159 bool NeedSentinel = false;
160 if (Parent->isRoot()) {
161 assert(isSentinelProbe(LastProbe->getAttributes()) &&
162 "Starting probe of a top-level function should be a sentinel probe");
163 // The main body of a split function doesn't need a sentinel probe.
164 if (LastProbe->getGuid() != Guid)
165 NeedSentinel = true;
168 MCOS->emitULEB128IntValue(Probes.size() + NeedSentinel);
169 // Emit number of direct inlinees
170 MCOS->emitULEB128IntValue(Children.size());
171 // Emit sentinel probe for top-level functions
172 if (NeedSentinel)
173 LastProbe->emit(MCOS, nullptr);
175 // Emit probes in this group
176 for (const auto &Probe : Probes) {
177 Probe.emit(MCOS, LastProbe);
178 LastProbe = &Probe;
181 // Emit sorted descendant. InlineSite is unique for each pair, so there will
182 // be no ordering of Inlinee based on MCPseudoProbeInlineTree*
183 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
184 auto Comparer = [](const InlineeType &A, const InlineeType &B) {
185 return A.first < B.first;
187 std::vector<InlineeType> Inlinees;
188 for (const auto &Child : Children)
189 Inlinees.emplace_back(Child.first, Child.second.get());
190 std::sort(Inlinees.begin(), Inlinees.end(), Comparer);
192 for (const auto &Inlinee : Inlinees) {
193 // Emit probe index
194 MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first));
195 LLVM_DEBUG({
196 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
197 dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";
199 // Emit the group
200 Inlinee.second->emit(MCOS, LastProbe);
203 LLVM_DEBUG({
204 MCPseudoProbeTable::DdgPrintIndent -= 2;
205 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
206 dbgs() << "]\n";
210 void MCPseudoProbeSections::emit(MCObjectStreamer *MCOS) {
211 MCContext &Ctx = MCOS->getContext();
212 for (auto &ProbeSec : MCProbeDivisions) {
213 const auto *FuncSym = ProbeSec.first;
214 const auto &Root = ProbeSec.second;
215 if (auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(
216 FuncSym->getSection())) {
217 // Switch to the .pseudoprobe section or a comdat group.
218 MCOS->switchSection(S);
219 // Emit probes grouped by GUID.
220 // Emit sorted descendant. InlineSite is unique for each pair, so there
221 // will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
222 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
223 auto Comparer = [](const InlineeType &A, const InlineeType &B) {
224 return A.first < B.first;
226 std::vector<InlineeType> Inlinees;
227 for (const auto &Child : Root.getChildren())
228 Inlinees.emplace_back(Child.first, Child.second.get());
229 std::sort(Inlinees.begin(), Inlinees.end(), Comparer);
231 for (const auto &Inlinee : Inlinees) {
232 // Emit the group guarded by a sentinel probe.
233 MCPseudoProbe SentinelProbe(
234 const_cast<MCSymbol *>(FuncSym), MD5Hash(FuncSym->getName()),
235 (uint32_t)PseudoProbeReservedId::Invalid,
236 (uint32_t)PseudoProbeType::Block,
237 (uint32_t)PseudoProbeAttributes::Sentinel, 0);
238 const MCPseudoProbe *Probe = &SentinelProbe;
239 Inlinee.second->emit(MCOS, Probe);
246 // This emits the pseudo probe tables.
248 void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) {
249 MCContext &Ctx = MCOS->getContext();
250 auto &ProbeTable = Ctx.getMCPseudoProbeTable();
252 // Bail out early so we don't switch to the pseudo_probe section needlessly
253 // and in doing so create an unnecessary (if empty) section.
254 auto &ProbeSections = ProbeTable.getProbeSections();
255 if (ProbeSections.empty())
256 return;
258 LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent = 0);
260 // Put out the probe.
261 ProbeSections.emit(MCOS);
264 static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
265 uint64_t GUID) {
266 auto It = GUID2FuncMAP.find(GUID);
267 assert(It != GUID2FuncMAP.end() &&
268 "Probe function must exist for a valid GUID");
269 return It->second.FuncName;
272 void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {
273 OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";
274 OS << "Hash: " << FuncHash << "\n";
277 void MCDecodedPseudoProbe::getInlineContext(
278 SmallVectorImpl<MCPseduoProbeFrameLocation> &ContextStack,
279 const GUIDProbeFunctionMap &GUID2FuncMAP) const {
280 uint32_t Begin = ContextStack.size();
281 MCDecodedPseudoProbeInlineTree *Cur = InlineTree;
282 // It will add the string of each node's inline site during iteration.
283 // Note that it won't include the probe's belonging function(leaf location)
284 while (Cur->hasInlineSite()) {
285 StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Cur->Parent->Guid);
286 ContextStack.emplace_back(
287 MCPseduoProbeFrameLocation(FuncName, std::get<1>(Cur->ISite)));
288 Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
290 // Make the ContextStack in caller-callee order
291 std::reverse(ContextStack.begin() + Begin, ContextStack.end());
294 std::string MCDecodedPseudoProbe::getInlineContextStr(
295 const GUIDProbeFunctionMap &GUID2FuncMAP) const {
296 std::ostringstream OContextStr;
297 SmallVector<MCPseduoProbeFrameLocation, 16> ContextStack;
298 getInlineContext(ContextStack, GUID2FuncMAP);
299 for (auto &Cxt : ContextStack) {
300 if (OContextStr.str().size())
301 OContextStr << " @ ";
302 OContextStr << Cxt.first.str() << ":" << Cxt.second;
304 return OContextStr.str();
307 static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",
308 "DirectCall"};
310 void MCDecodedPseudoProbe::print(raw_ostream &OS,
311 const GUIDProbeFunctionMap &GUID2FuncMAP,
312 bool ShowName) const {
313 OS << "FUNC: ";
314 if (ShowName) {
315 StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Guid);
316 OS << FuncName.str() << " ";
317 } else {
318 OS << Guid << " ";
320 OS << "Index: " << Index << " ";
321 if (Discriminator)
322 OS << "Discriminator: " << Discriminator << " ";
323 OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << " ";
324 std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);
325 if (InlineContextStr.size()) {
326 OS << "Inlined: @ ";
327 OS << InlineContextStr;
329 OS << "\n";
332 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
333 if (Data + sizeof(T) > End) {
334 return std::error_code();
336 T Val = endian::readNext<T, little, unaligned>(Data);
337 return ErrorOr<T>(Val);
340 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
341 unsigned NumBytesRead = 0;
342 uint64_t Val = decodeULEB128(Data, &NumBytesRead);
343 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
344 return std::error_code();
346 Data += NumBytesRead;
347 return ErrorOr<T>(static_cast<T>(Val));
350 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
351 unsigned NumBytesRead = 0;
352 int64_t Val = decodeSLEB128(Data, &NumBytesRead);
353 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
354 return std::error_code();
356 Data += NumBytesRead;
357 return ErrorOr<T>(static_cast<T>(Val));
360 ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {
361 StringRef Str(reinterpret_cast<const char *>(Data), Size);
362 if (Data + Size > End) {
363 return std::error_code();
365 Data += Size;
366 return ErrorOr<StringRef>(Str);
369 bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,
370 std::size_t Size) {
371 // The pseudo_probe_desc section has a format like:
372 // .section .pseudo_probe_desc,"",@progbits
373 // .quad -5182264717993193164 // GUID
374 // .quad 4294967295 // Hash
375 // .uleb 3 // Name size
376 // .ascii "foo" // Name
377 // .quad -2624081020897602054
378 // .quad 174696971957
379 // .uleb 34
380 // .ascii "main"
382 Data = Start;
383 End = Data + Size;
385 while (Data < End) {
386 auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
387 if (!ErrorOrGUID)
388 return false;
390 auto ErrorOrHash = readUnencodedNumber<uint64_t>();
391 if (!ErrorOrHash)
392 return false;
394 auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
395 if (!ErrorOrNameSize)
396 return false;
397 uint32_t NameSize = std::move(*ErrorOrNameSize);
399 auto ErrorOrName = readString(NameSize);
400 if (!ErrorOrName)
401 return false;
403 uint64_t GUID = std::move(*ErrorOrGUID);
404 uint64_t Hash = std::move(*ErrorOrHash);
405 StringRef Name = std::move(*ErrorOrName);
407 // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
408 GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));
410 assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
411 return true;
414 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
415 MCDecodedPseudoProbeInlineTree *Cur, uint64_t &LastAddr,
416 const Uint64Set &GuidFilter, const Uint64Map &FuncStartAddrs) {
417 // The pseudo_probe section encodes an inline forest and each tree has a
418 // format defined in MCPseudoProbe.h
420 uint32_t Index = 0;
421 bool IsTopLevelFunc = Cur == &DummyInlineRoot;
422 if (IsTopLevelFunc) {
423 // Use a sequential id for top level inliner.
424 Index = Cur->getChildren().size();
425 } else {
426 // Read inline site for inlinees
427 auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
428 if (!ErrorOrIndex)
429 return false;
430 Index = std::move(*ErrorOrIndex);
433 // Read guid
434 auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
435 if (!ErrorOrCurGuid)
436 return false;
437 uint64_t Guid = std::move(*ErrorOrCurGuid);
439 // Decide if top-level node should be disgarded.
440 if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(Guid))
441 Cur = nullptr;
443 // If the incoming node is null, all its children nodes should be disgarded.
444 if (Cur) {
445 // Switch/add to a new tree node(inlinee)
446 Cur = Cur->getOrAddNode(std::make_tuple(Guid, Index));
447 Cur->Guid = Guid;
448 if (IsTopLevelFunc && !EncodingIsAddrBased) {
449 if (auto V = FuncStartAddrs.lookup(Guid))
450 LastAddr = V;
454 // Read number of probes in the current node.
455 auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
456 if (!ErrorOrNodeCount)
457 return false;
458 uint32_t NodeCount = std::move(*ErrorOrNodeCount);
459 // Read number of direct inlinees
460 auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
461 if (!ErrorOrCurChildrenToProcess)
462 return false;
463 // Read all probes in this node
464 for (std::size_t I = 0; I < NodeCount; I++) {
465 // Read index
466 auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
467 if (!ErrorOrIndex)
468 return false;
469 uint32_t Index = std::move(*ErrorOrIndex);
470 // Read type | flag.
471 auto ErrorOrValue = readUnencodedNumber<uint8_t>();
472 if (!ErrorOrValue)
473 return false;
474 uint8_t Value = std::move(*ErrorOrValue);
475 uint8_t Kind = Value & 0xf;
476 uint8_t Attr = (Value & 0x70) >> 4;
477 // Read address
478 uint64_t Addr = 0;
479 if (Value & 0x80) {
480 auto ErrorOrOffset = readSignedNumber<int64_t>();
481 if (!ErrorOrOffset)
482 return false;
483 int64_t Offset = std::move(*ErrorOrOffset);
484 Addr = LastAddr + Offset;
485 } else {
486 auto ErrorOrAddr = readUnencodedNumber<int64_t>();
487 if (!ErrorOrAddr)
488 return false;
489 Addr = std::move(*ErrorOrAddr);
490 if (isSentinelProbe(Attr)) {
491 // For sentinel probe, the addr field actually stores the GUID of the
492 // split function. Convert it to the real address.
493 if (auto V = FuncStartAddrs.lookup(Addr))
494 Addr = V;
495 } else {
496 // For now we assume all probe encoding should be either based on
497 // leading probe address or function start address.
498 // The scheme is for downwards compatibility.
499 // TODO: retire this scheme once compatibility is no longer an issue.
500 EncodingIsAddrBased = true;
504 uint32_t Discriminator = 0;
505 if (hasDiscriminator(Attr)) {
506 auto ErrorOrDiscriminator = readUnsignedNumber<uint32_t>();
507 if (!ErrorOrDiscriminator)
508 return false;
509 Discriminator = std::move(*ErrorOrDiscriminator);
512 if (Cur && !isSentinelProbe(Attr)) {
513 // Populate Address2ProbesMap
514 auto &Probes = Address2ProbesMap[Addr];
515 Probes.emplace_back(Addr, Cur->Guid, Index, PseudoProbeType(Kind), Attr,
516 Discriminator, Cur);
517 Cur->addProbes(&Probes.back());
519 LastAddr = Addr;
522 uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
523 for (uint32_t I = 0; I < ChildrenToProcess; I++) {
524 buildAddress2ProbeMap(Cur, LastAddr, GuidFilter, FuncStartAddrs);
527 return true;
530 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
531 const uint8_t *Start, std::size_t Size, const Uint64Set &GuidFilter,
532 const Uint64Map &FuncStartAddrs) {
533 Data = Start;
534 End = Data + Size;
535 uint64_t LastAddr = 0;
536 while (Data < End)
537 buildAddress2ProbeMap(&DummyInlineRoot, LastAddr, GuidFilter,
538 FuncStartAddrs);
539 assert(Data == End && "Have unprocessed data in pseudo_probe section");
540 return true;
543 void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
544 OS << "Pseudo Probe Desc:\n";
545 // Make the output deterministic
546 std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
547 GUID2FuncDescMap.end());
548 for (auto &I : OrderedMap) {
549 I.second.print(OS);
553 void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,
554 uint64_t Address) {
555 auto It = Address2ProbesMap.find(Address);
556 if (It != Address2ProbesMap.end()) {
557 for (auto &Probe : It->second) {
558 OS << " [Probe]:\t";
559 Probe.print(OS, GUID2FuncDescMap, true);
564 void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream &OS) {
565 std::vector<uint64_t> Addresses;
566 for (auto Entry : Address2ProbesMap)
567 Addresses.push_back(Entry.first);
568 llvm::sort(Addresses);
569 for (auto K : Addresses) {
570 OS << "Address:\t";
571 OS << K;
572 OS << "\n";
573 printProbeForAddress(OS, K);
577 const MCDecodedPseudoProbe *
578 MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {
579 auto It = Address2ProbesMap.find(Address);
580 if (It == Address2ProbesMap.end())
581 return nullptr;
582 const auto &Probes = It->second;
584 const MCDecodedPseudoProbe *CallProbe = nullptr;
585 for (const auto &Probe : Probes) {
586 if (Probe.isCall()) {
587 assert(!CallProbe &&
588 "There should be only one call probe corresponding to address "
589 "which is a callsite.");
590 CallProbe = &Probe;
593 return CallProbe;
596 const MCPseudoProbeFuncDesc *
597 MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
598 auto It = GUID2FuncDescMap.find(GUID);
599 assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
600 return &It->second;
603 void MCPseudoProbeDecoder::getInlineContextForProbe(
604 const MCDecodedPseudoProbe *Probe,
605 SmallVectorImpl<MCPseduoProbeFrameLocation> &InlineContextStack,
606 bool IncludeLeaf) const {
607 Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);
608 if (!IncludeLeaf)
609 return;
610 // Note that the context from probe doesn't include leaf frame,
611 // hence we need to retrieve and prepend leaf if requested.
612 const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());
613 InlineContextStack.emplace_back(
614 MCPseduoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));
617 const MCPseudoProbeFuncDesc *MCPseudoProbeDecoder::getInlinerDescForProbe(
618 const MCDecodedPseudoProbe *Probe) const {
619 MCDecodedPseudoProbeInlineTree *InlinerNode = Probe->getInlineTreeNode();
620 if (!InlinerNode->hasInlineSite())
621 return nullptr;
622 return getFuncDescForGUID(InlinerNode->Parent->Guid);