[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / llvm / lib / MC / MCPseudoProbe.cpp
blobeb3894dbb3c254c4aafb48bf25afe44fb05e5ac8
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/MCAssembler.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCFragment.h"
17 #include "llvm/MC/MCObjectFileInfo.h"
18 #include "llvm/MC/MCObjectStreamer.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/LEB128.h"
22 #include "llvm/Support/MD5.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include <algorithm>
25 #include <cassert>
26 #include <limits>
27 #include <memory>
28 #include <sstream>
29 #include <vector>
31 #define DEBUG_TYPE "mcpseudoprobe"
33 using namespace llvm;
34 using namespace support;
36 #ifndef NDEBUG
37 int MCPseudoProbeTable::DdgPrintIndent = 0;
38 #endif
40 static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A,
41 const MCSymbol *B) {
42 MCContext &Context = MCOS->getContext();
43 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
44 const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
45 const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
46 const MCExpr *AddrDelta =
47 MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
48 return AddrDelta;
51 void MCPseudoProbe::emit(MCObjectStreamer *MCOS,
52 const MCPseudoProbe *LastProbe) const {
53 bool IsSentinel = isSentinelProbe(getAttributes());
54 assert((LastProbe || IsSentinel) &&
55 "Last probe should not be null for non-sentinel probes");
57 // Emit Index
58 MCOS->emitULEB128IntValue(Index);
59 // Emit Type and the flag:
60 // Type (bit 0 to 3), with bit 4 to 6 for attributes.
61 // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether
62 // the following field is a symbolic code address or an address delta.
63 // Emit FS discriminator
64 assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");
65 auto NewAttributes = Attributes;
66 if (Discriminator)
67 NewAttributes |= (uint32_t)PseudoProbeAttributes::HasDiscriminator;
68 assert(NewAttributes <= 0x7 &&
69 "Probe attributes too big to encode, exceeding 7");
70 uint8_t PackedType = Type | (NewAttributes << 4);
71 uint8_t Flag =
72 !IsSentinel ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0;
73 MCOS->emitInt8(Flag | PackedType);
75 if (!IsSentinel) {
76 // Emit the delta between the address label and LastProbe.
77 const MCExpr *AddrDelta =
78 buildSymbolDiff(MCOS, Label, LastProbe->getLabel());
79 int64_t Delta;
80 if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {
81 MCOS->emitSLEB128IntValue(Delta);
82 } else {
83 MCOS->insert(new MCPseudoProbeAddrFragment(AddrDelta));
85 } else {
86 // Emit the GUID of the split function that the sentinel probe represents.
87 MCOS->emitInt64(Guid);
90 if (Discriminator)
91 MCOS->emitULEB128IntValue(Discriminator);
93 LLVM_DEBUG({
94 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
95 dbgs() << "Probe: " << Index << "\n";
96 });
99 void MCPseudoProbeInlineTree::addPseudoProbe(
100 const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {
101 // The function should not be called on the root.
102 assert(isRoot() && "Should only be called on root");
104 // When it comes here, the input look like:
105 // Probe: GUID of C, ...
106 // InlineStack: [88, A], [66, B]
107 // which means, Function A inlines function B at call site with a probe id of
108 // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0,
109 // A], [88, B], [66, C]} to locate the tree node where the probe should be
110 // added. Note that the edge [0, A] means A is the top-level function we are
111 // emitting probes for.
113 // Make a [0, A] edge.
114 // An empty inline stack means the function that the probe originates from
115 // is a top-level function.
116 InlineSite Top;
117 if (InlineStack.empty()) {
118 Top = InlineSite(Probe.getGuid(), 0);
119 } else {
120 Top = InlineSite(std::get<0>(InlineStack.front()), 0);
123 auto *Cur = getOrAddNode(Top);
125 // Make interior edges by walking the inline stack. Once it's done, Cur should
126 // point to the node that the probe originates from.
127 if (!InlineStack.empty()) {
128 auto Iter = InlineStack.begin();
129 auto Index = std::get<1>(*Iter);
130 Iter++;
131 for (; Iter != InlineStack.end(); Iter++) {
132 // Make an edge by using the previous probe id and current GUID.
133 Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));
134 Index = std::get<1>(*Iter);
136 Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index));
139 Cur->Probes.push_back(Probe);
142 void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,
143 const MCPseudoProbe *&LastProbe) {
144 LLVM_DEBUG({
145 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
146 dbgs() << "Group [\n";
147 MCPseudoProbeTable::DdgPrintIndent += 2;
149 assert(!isRoot() && "Root should be handled seperately");
151 // Emit probes grouped by GUID.
152 LLVM_DEBUG({
153 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
154 dbgs() << "GUID: " << Guid << "\n";
156 // Emit Guid
157 MCOS->emitInt64(Guid);
158 // Emit number of probes in this node, including a sentinel probe for
159 // top-level functions if needed.
160 bool NeedSentinel = false;
161 if (Parent->isRoot()) {
162 assert(isSentinelProbe(LastProbe->getAttributes()) &&
163 "Starting probe of a top-level function should be a sentinel probe");
164 // The main body of a split function doesn't need a sentinel probe.
165 if (LastProbe->getGuid() != Guid)
166 NeedSentinel = true;
169 MCOS->emitULEB128IntValue(Probes.size() + NeedSentinel);
170 // Emit number of direct inlinees
171 MCOS->emitULEB128IntValue(Children.size());
172 // Emit sentinel probe for top-level functions
173 if (NeedSentinel)
174 LastProbe->emit(MCOS, nullptr);
176 // Emit probes in this group
177 for (const auto &Probe : Probes) {
178 Probe.emit(MCOS, LastProbe);
179 LastProbe = &Probe;
182 // Emit sorted descendant. InlineSite is unique for each pair, so there will
183 // be no ordering of Inlinee based on MCPseudoProbeInlineTree*
184 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
185 auto Comparer = [](const InlineeType &A, const InlineeType &B) {
186 return A.first < B.first;
188 std::vector<InlineeType> Inlinees;
189 for (const auto &Child : Children)
190 Inlinees.emplace_back(Child.first, Child.second.get());
191 std::sort(Inlinees.begin(), Inlinees.end(), Comparer);
193 for (const auto &Inlinee : Inlinees) {
194 // Emit probe index
195 MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first));
196 LLVM_DEBUG({
197 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
198 dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";
200 // Emit the group
201 Inlinee.second->emit(MCOS, LastProbe);
204 LLVM_DEBUG({
205 MCPseudoProbeTable::DdgPrintIndent -= 2;
206 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);
207 dbgs() << "]\n";
211 void MCPseudoProbeSections::emit(MCObjectStreamer *MCOS) {
212 MCContext &Ctx = MCOS->getContext();
213 SmallVector<std::pair<MCSymbol *, MCPseudoProbeInlineTree *>> Vec;
214 Vec.reserve(MCProbeDivisions.size());
215 for (auto &ProbeSec : MCProbeDivisions)
216 Vec.emplace_back(ProbeSec.first, &ProbeSec.second);
217 for (auto I : llvm::enumerate(MCOS->getAssembler()))
218 I.value().setOrdinal(I.index());
219 llvm::sort(Vec, [](auto A, auto B) {
220 return A.first->getSection().getOrdinal() <
221 B.first->getSection().getOrdinal();
223 for (auto [FuncSym, RootPtr] : Vec) {
224 const auto &Root = *RootPtr;
225 if (auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(
226 FuncSym->getSection())) {
227 // Switch to the .pseudoprobe section or a comdat group.
228 MCOS->switchSection(S);
229 // Emit probes grouped by GUID.
230 // Emit sorted descendant. InlineSite is unique for each pair, so there
231 // will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
232 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
233 auto Comparer = [](const InlineeType &A, const InlineeType &B) {
234 return A.first < B.first;
236 std::vector<InlineeType> Inlinees;
237 for (const auto &Child : Root.getChildren())
238 Inlinees.emplace_back(Child.first, Child.second.get());
239 std::sort(Inlinees.begin(), Inlinees.end(), Comparer);
241 for (const auto &Inlinee : Inlinees) {
242 // Emit the group guarded by a sentinel probe.
243 MCPseudoProbe SentinelProbe(
244 const_cast<MCSymbol *>(FuncSym), MD5Hash(FuncSym->getName()),
245 (uint32_t)PseudoProbeReservedId::Invalid,
246 (uint32_t)PseudoProbeType::Block,
247 (uint32_t)PseudoProbeAttributes::Sentinel, 0);
248 const MCPseudoProbe *Probe = &SentinelProbe;
249 Inlinee.second->emit(MCOS, Probe);
256 // This emits the pseudo probe tables.
258 void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) {
259 MCContext &Ctx = MCOS->getContext();
260 auto &ProbeTable = Ctx.getMCPseudoProbeTable();
262 // Bail out early so we don't switch to the pseudo_probe section needlessly
263 // and in doing so create an unnecessary (if empty) section.
264 auto &ProbeSections = ProbeTable.getProbeSections();
265 if (ProbeSections.empty())
266 return;
268 LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent = 0);
270 // Put out the probe.
271 ProbeSections.emit(MCOS);
274 static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
275 uint64_t GUID) {
276 auto It = GUID2FuncMAP.find(GUID);
277 assert(It != GUID2FuncMAP.end() &&
278 "Probe function must exist for a valid GUID");
279 return It->second.FuncName;
282 void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {
283 OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";
284 OS << "Hash: " << FuncHash << "\n";
287 void MCDecodedPseudoProbe::getInlineContext(
288 SmallVectorImpl<MCPseduoProbeFrameLocation> &ContextStack,
289 const GUIDProbeFunctionMap &GUID2FuncMAP) const {
290 uint32_t Begin = ContextStack.size();
291 MCDecodedPseudoProbeInlineTree *Cur = InlineTree;
292 // It will add the string of each node's inline site during iteration.
293 // Note that it won't include the probe's belonging function(leaf location)
294 while (Cur->hasInlineSite()) {
295 StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Cur->Parent->Guid);
296 ContextStack.emplace_back(
297 MCPseduoProbeFrameLocation(FuncName, std::get<1>(Cur->ISite)));
298 Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
300 // Make the ContextStack in caller-callee order
301 std::reverse(ContextStack.begin() + Begin, ContextStack.end());
304 std::string MCDecodedPseudoProbe::getInlineContextStr(
305 const GUIDProbeFunctionMap &GUID2FuncMAP) const {
306 std::ostringstream OContextStr;
307 SmallVector<MCPseduoProbeFrameLocation, 16> ContextStack;
308 getInlineContext(ContextStack, GUID2FuncMAP);
309 for (auto &Cxt : ContextStack) {
310 if (OContextStr.str().size())
311 OContextStr << " @ ";
312 OContextStr << Cxt.first.str() << ":" << Cxt.second;
314 return OContextStr.str();
317 static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",
318 "DirectCall"};
320 void MCDecodedPseudoProbe::print(raw_ostream &OS,
321 const GUIDProbeFunctionMap &GUID2FuncMAP,
322 bool ShowName) const {
323 OS << "FUNC: ";
324 if (ShowName) {
325 StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Guid);
326 OS << FuncName.str() << " ";
327 } else {
328 OS << Guid << " ";
330 OS << "Index: " << Index << " ";
331 if (Discriminator)
332 OS << "Discriminator: " << Discriminator << " ";
333 OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << " ";
334 std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);
335 if (InlineContextStr.size()) {
336 OS << "Inlined: @ ";
337 OS << InlineContextStr;
339 OS << "\n";
342 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
343 if (Data + sizeof(T) > End) {
344 return std::error_code();
346 T Val = endian::readNext<T, llvm::endianness::little, unaligned>(Data);
347 return ErrorOr<T>(Val);
350 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
351 unsigned NumBytesRead = 0;
352 uint64_t Val = decodeULEB128(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 template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
361 unsigned NumBytesRead = 0;
362 int64_t Val = decodeSLEB128(Data, &NumBytesRead);
363 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
364 return std::error_code();
366 Data += NumBytesRead;
367 return ErrorOr<T>(static_cast<T>(Val));
370 ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {
371 StringRef Str(reinterpret_cast<const char *>(Data), Size);
372 if (Data + Size > End) {
373 return std::error_code();
375 Data += Size;
376 return ErrorOr<StringRef>(Str);
379 bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,
380 std::size_t Size) {
381 // The pseudo_probe_desc section has a format like:
382 // .section .pseudo_probe_desc,"",@progbits
383 // .quad -5182264717993193164 // GUID
384 // .quad 4294967295 // Hash
385 // .uleb 3 // Name size
386 // .ascii "foo" // Name
387 // .quad -2624081020897602054
388 // .quad 174696971957
389 // .uleb 34
390 // .ascii "main"
392 Data = Start;
393 End = Data + Size;
395 while (Data < End) {
396 auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
397 if (!ErrorOrGUID)
398 return false;
400 auto ErrorOrHash = readUnencodedNumber<uint64_t>();
401 if (!ErrorOrHash)
402 return false;
404 auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
405 if (!ErrorOrNameSize)
406 return false;
407 uint32_t NameSize = std::move(*ErrorOrNameSize);
409 auto ErrorOrName = readString(NameSize);
410 if (!ErrorOrName)
411 return false;
413 uint64_t GUID = std::move(*ErrorOrGUID);
414 uint64_t Hash = std::move(*ErrorOrHash);
415 StringRef Name = std::move(*ErrorOrName);
417 // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
418 GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));
420 assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
421 return true;
424 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
425 MCDecodedPseudoProbeInlineTree *Cur, uint64_t &LastAddr,
426 const Uint64Set &GuidFilter, const Uint64Map &FuncStartAddrs) {
427 // The pseudo_probe section encodes an inline forest and each tree has a
428 // format defined in MCPseudoProbe.h
430 uint32_t Index = 0;
431 bool IsTopLevelFunc = Cur == &DummyInlineRoot;
432 if (IsTopLevelFunc) {
433 // Use a sequential id for top level inliner.
434 Index = Cur->getChildren().size();
435 } else {
436 // Read inline site for inlinees
437 auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
438 if (!ErrorOrIndex)
439 return false;
440 Index = std::move(*ErrorOrIndex);
443 // Read guid
444 auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
445 if (!ErrorOrCurGuid)
446 return false;
447 uint64_t Guid = std::move(*ErrorOrCurGuid);
449 // Decide if top-level node should be disgarded.
450 if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(Guid))
451 Cur = nullptr;
453 // If the incoming node is null, all its children nodes should be disgarded.
454 if (Cur) {
455 // Switch/add to a new tree node(inlinee)
456 Cur = Cur->getOrAddNode(std::make_tuple(Guid, Index));
457 Cur->Guid = Guid;
458 if (IsTopLevelFunc && !EncodingIsAddrBased) {
459 if (auto V = FuncStartAddrs.lookup(Guid))
460 LastAddr = V;
464 // Read number of probes in the current node.
465 auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
466 if (!ErrorOrNodeCount)
467 return false;
468 uint32_t NodeCount = std::move(*ErrorOrNodeCount);
469 // Read number of direct inlinees
470 auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
471 if (!ErrorOrCurChildrenToProcess)
472 return false;
473 // Read all probes in this node
474 for (std::size_t I = 0; I < NodeCount; I++) {
475 // Read index
476 auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
477 if (!ErrorOrIndex)
478 return false;
479 uint32_t Index = std::move(*ErrorOrIndex);
480 // Read type | flag.
481 auto ErrorOrValue = readUnencodedNumber<uint8_t>();
482 if (!ErrorOrValue)
483 return false;
484 uint8_t Value = std::move(*ErrorOrValue);
485 uint8_t Kind = Value & 0xf;
486 uint8_t Attr = (Value & 0x70) >> 4;
487 // Read address
488 uint64_t Addr = 0;
489 if (Value & 0x80) {
490 auto ErrorOrOffset = readSignedNumber<int64_t>();
491 if (!ErrorOrOffset)
492 return false;
493 int64_t Offset = std::move(*ErrorOrOffset);
494 Addr = LastAddr + Offset;
495 } else {
496 auto ErrorOrAddr = readUnencodedNumber<int64_t>();
497 if (!ErrorOrAddr)
498 return false;
499 Addr = std::move(*ErrorOrAddr);
500 if (isSentinelProbe(Attr)) {
501 // For sentinel probe, the addr field actually stores the GUID of the
502 // split function. Convert it to the real address.
503 if (auto V = FuncStartAddrs.lookup(Addr))
504 Addr = V;
505 } else {
506 // For now we assume all probe encoding should be either based on
507 // leading probe address or function start address.
508 // The scheme is for downwards compatibility.
509 // TODO: retire this scheme once compatibility is no longer an issue.
510 EncodingIsAddrBased = true;
514 uint32_t Discriminator = 0;
515 if (hasDiscriminator(Attr)) {
516 auto ErrorOrDiscriminator = readUnsignedNumber<uint32_t>();
517 if (!ErrorOrDiscriminator)
518 return false;
519 Discriminator = std::move(*ErrorOrDiscriminator);
522 if (Cur && !isSentinelProbe(Attr)) {
523 // Populate Address2ProbesMap
524 auto &Probes = Address2ProbesMap[Addr];
525 Probes.emplace_back(Addr, Cur->Guid, Index, PseudoProbeType(Kind), Attr,
526 Discriminator, Cur);
527 Cur->addProbes(&Probes.back());
529 LastAddr = Addr;
532 uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
533 for (uint32_t I = 0; I < ChildrenToProcess; I++) {
534 buildAddress2ProbeMap(Cur, LastAddr, GuidFilter, FuncStartAddrs);
537 return true;
540 bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
541 const uint8_t *Start, std::size_t Size, const Uint64Set &GuidFilter,
542 const Uint64Map &FuncStartAddrs) {
543 Data = Start;
544 End = Data + Size;
545 uint64_t LastAddr = 0;
546 while (Data < End)
547 buildAddress2ProbeMap(&DummyInlineRoot, LastAddr, GuidFilter,
548 FuncStartAddrs);
549 assert(Data == End && "Have unprocessed data in pseudo_probe section");
550 return true;
553 void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
554 OS << "Pseudo Probe Desc:\n";
555 // Make the output deterministic
556 std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
557 GUID2FuncDescMap.end());
558 for (auto &I : OrderedMap) {
559 I.second.print(OS);
563 void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,
564 uint64_t Address) {
565 auto It = Address2ProbesMap.find(Address);
566 if (It != Address2ProbesMap.end()) {
567 for (auto &Probe : It->second) {
568 OS << " [Probe]:\t";
569 Probe.print(OS, GUID2FuncDescMap, true);
574 void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream &OS) {
575 auto Entries = make_first_range(Address2ProbesMap);
576 SmallVector<uint64_t, 0> Addresses(Entries.begin(), Entries.end());
577 llvm::sort(Addresses);
578 for (auto K : Addresses) {
579 OS << "Address:\t";
580 OS << K;
581 OS << "\n";
582 printProbeForAddress(OS, K);
586 const MCDecodedPseudoProbe *
587 MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {
588 auto It = Address2ProbesMap.find(Address);
589 if (It == Address2ProbesMap.end())
590 return nullptr;
591 const auto &Probes = It->second;
593 const MCDecodedPseudoProbe *CallProbe = nullptr;
594 for (const auto &Probe : Probes) {
595 if (Probe.isCall()) {
596 // Disabling the assert and returning first call probe seen so far.
597 // Subsequent call probes, if any, are ignored. Due to the the way
598 // .pseudo_probe section is decoded, probes of the same-named independent
599 // static functions are merged thus multiple call probes may be seen for a
600 // callsite. This should only happen to compiler-generated statics, with
601 // -funique-internal-linkage-names where user statics get unique names.
603 // TODO: re-enable or narrow down the assert to static functions only.
605 // assert(!CallProbe &&
606 // "There should be only one call probe corresponding to address "
607 // "which is a callsite.");
608 CallProbe = &Probe;
609 break;
612 return CallProbe;
615 const MCPseudoProbeFuncDesc *
616 MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
617 auto It = GUID2FuncDescMap.find(GUID);
618 assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
619 return &It->second;
622 void MCPseudoProbeDecoder::getInlineContextForProbe(
623 const MCDecodedPseudoProbe *Probe,
624 SmallVectorImpl<MCPseduoProbeFrameLocation> &InlineContextStack,
625 bool IncludeLeaf) const {
626 Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);
627 if (!IncludeLeaf)
628 return;
629 // Note that the context from probe doesn't include leaf frame,
630 // hence we need to retrieve and prepend leaf if requested.
631 const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());
632 InlineContextStack.emplace_back(
633 MCPseduoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));
636 const MCPseudoProbeFuncDesc *MCPseudoProbeDecoder::getInlinerDescForProbe(
637 const MCDecodedPseudoProbe *Probe) const {
638 MCDecodedPseudoProbeInlineTree *InlinerNode = Probe->getInlineTreeNode();
639 if (!InlinerNode->hasInlineSite())
640 return nullptr;
641 return getFuncDescForGUID(InlinerNode->Parent->Guid);