xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCPseudoProbe.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- MCPseudoProbe.h - Pseudo probe encoding support ---------*- C++ -*-===//
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 contains the declaration of the MCPseudoProbe to support the pseudo
10 // probe encoding for AutoFDO. Pseudo probes together with their inline context
11 // are encoded in a DFS recursive way in the .pseudoprobe sections. For each
12 // .pseudoprobe section, the encoded binary data consist of a single or mutiple
13 // function records each for one outlined function. A function record has the
14 // following format :
15 //
16 // FUNCTION BODY (one for each outlined function present in the text section)
17 //    GUID (uint64)
18 //        GUID of the function's source name which may be different from the
19 //        actual binary linkage name. This GUID will be used to decode and
20 //        generate a profile against the source function name.
21 //    NPROBES (ULEB128)
22 //        Number of probes originating from this function.
23 //    NUM_INLINED_FUNCTIONS (ULEB128)
24 //        Number of callees inlined into this function, aka number of
25 //        first-level inlinees
26 //    PROBE RECORDS
27 //        A list of NPROBES entries. Each entry contains:
28 //          INDEX (ULEB128)
29 //          TYPE (uint4)
30 //            0 - block probe, 1 - indirect call, 2 - direct call
31 //          ATTRIBUTE (uint3)
32 //            1 - reserved
33 //            2 - Sentinel
34 //            4 - HasDiscriminator
35 //          ADDRESS_TYPE (uint1)
36 //            0 - code address for regular probes (for downwards compatibility)
37 //              - GUID of linkage name for sentinel probes
38 //            1 - address delta
39 //          CODE_ADDRESS (uint64 or ULEB128)
40 //            code address or address delta, depending on ADDRESS_TYPE
41 //          DISCRIMINATOR (ULEB128) if HasDiscriminator
42 //    INLINED FUNCTION RECORDS
43 //        A list of NUM_INLINED_FUNCTIONS entries describing each of the inlined
44 //        callees.  Each record contains:
45 //          INLINE SITE
46 //            ID of the callsite probe (ULEB128)
47 //          FUNCTION BODY
48 //            A FUNCTION BODY entry describing the inlined function.
49 //
50 // TODO: retire the ADDRESS_TYPE encoding for code addresses once compatibility
51 // is no longer an issue.
52 //===----------------------------------------------------------------------===//
53 
54 #ifndef LLVM_MC_MCPSEUDOPROBE_H
55 #define LLVM_MC_MCPSEUDOPROBE_H
56 
57 #include "llvm/ADT/ArrayRef.h"
58 #include "llvm/ADT/DenseMap.h"
59 #include "llvm/ADT/DenseSet.h"
60 #include "llvm/ADT/SmallVector.h"
61 #include "llvm/ADT/StringRef.h"
62 #include "llvm/ADT/iterator.h"
63 #include "llvm/IR/PseudoProbe.h"
64 #include "llvm/Support/Allocator.h"
65 #include "llvm/Support/Compiler.h"
66 #include "llvm/Support/ErrorOr.h"
67 #include <functional>
68 #include <memory>
69 #include <string>
70 #include <tuple>
71 #include <type_traits>
72 #include <unordered_map>
73 #include <vector>
74 
75 namespace llvm {
76 
77 class MCSymbol;
78 class MCObjectStreamer;
79 class raw_ostream;
80 
81 enum class MCPseudoProbeFlag {
82   // If set, indicates that the probe is encoded as an address delta
83   // instead of a real code address.
84   AddressDelta = 0x1,
85 };
86 
87 // Function descriptor decoded from .pseudo_probe_desc section
88 struct MCPseudoProbeFuncDesc {
89   uint64_t FuncGUID = 0;
90   uint64_t FuncHash = 0;
91   StringRef FuncName;
92 
MCPseudoProbeFuncDescMCPseudoProbeFuncDesc93   MCPseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
94       : FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
95 
96   LLVM_ABI void print(raw_ostream &OS);
97 };
98 
99 class MCDecodedPseudoProbe;
100 
101 // An inline frame has the form <CalleeGuid, ProbeID>
102 using InlineSite = std::tuple<uint64_t, uint32_t>;
103 using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8>;
104 // GUID to PseudoProbeFuncDesc map
105 class GUIDProbeFunctionMap : public std::vector<MCPseudoProbeFuncDesc> {
106 public:
find(uint64_t GUID)107   auto find(uint64_t GUID) const {
108     auto CompareDesc = [](const MCPseudoProbeFuncDesc &Desc, uint64_t GUID) {
109       return Desc.FuncGUID < GUID;
110     };
111     auto It = llvm::lower_bound(*this, GUID, CompareDesc);
112     if (It->FuncGUID != GUID)
113       return end();
114     return It;
115   }
116 };
117 
118 class MCDecodedPseudoProbeInlineTree;
119 
120 class MCPseudoProbeBase {
121 protected:
122   uint32_t Index;
123   uint32_t Discriminator;
124   uint8_t Attributes;
125   uint8_t Type;
126   // The value should be equal to PseudoProbeReservedId::Last + 1 which is
127   // defined in SampleProfileProbe.h. The header file is not included here to
128   // reduce the dependency from MC to IPO.
129   const static uint32_t PseudoProbeFirstId = 1;
130 
131 public:
MCPseudoProbeBase(uint64_t I,uint64_t At,uint8_t T,uint32_t D)132   MCPseudoProbeBase(uint64_t I, uint64_t At, uint8_t T, uint32_t D)
133       : Index(I), Discriminator(D), Attributes(At), Type(T) {}
134 
isEntry()135   bool isEntry() const { return Index == PseudoProbeFirstId; }
136 
getIndex()137   uint32_t getIndex() const { return Index; }
138 
getDiscriminator()139   uint32_t getDiscriminator() const { return Discriminator; }
140 
getAttributes()141   uint8_t getAttributes() const { return Attributes; }
142 
getType()143   uint8_t getType() const { return Type; }
144 
isBlock()145   bool isBlock() const {
146     return Type == static_cast<uint8_t>(PseudoProbeType::Block);
147   }
148 
isIndirectCall()149   bool isIndirectCall() const {
150     return Type == static_cast<uint8_t>(PseudoProbeType::IndirectCall);
151   }
152 
isDirectCall()153   bool isDirectCall() const {
154     return Type == static_cast<uint8_t>(PseudoProbeType::DirectCall);
155   }
156 
isCall()157   bool isCall() const { return isIndirectCall() || isDirectCall(); }
158 
setAttributes(uint8_t Attr)159   void setAttributes(uint8_t Attr) { Attributes = Attr; }
160 };
161 
162 /// Instances of this class represent a pseudo probe instance for a pseudo probe
163 /// table entry, which is created during a machine instruction is assembled and
164 /// uses an address from a temporary label created at the current address in the
165 /// current section.
166 class MCPseudoProbe : public MCPseudoProbeBase {
167   uint64_t Guid;
168   MCSymbol *Label;
169 
170 public:
MCPseudoProbe(MCSymbol * Label,uint64_t Guid,uint64_t Index,uint64_t Type,uint64_t Attributes,uint32_t Discriminator)171   MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type,
172                 uint64_t Attributes, uint32_t Discriminator)
173       : MCPseudoProbeBase(Index, Attributes, Type, Discriminator), Guid(Guid),
174         Label(Label) {
175     assert(Type <= 0xFF && "Probe type too big to encode, exceeding 2^8");
176     assert(Attributes <= 0xFF &&
177            "Probe attributes too big to encode, exceeding 2^16");
178   }
179 
getGuid()180   uint64_t getGuid() const { return Guid; };
getLabel()181   MCSymbol *getLabel() const { return Label; }
182   LLVM_ABI void emit(MCObjectStreamer *MCOS,
183                      const MCPseudoProbe *LastProbe) const;
184 };
185 
186 // Represents a callsite with caller function name and probe id
187 using MCPseudoProbeFrameLocation = std::pair<StringRef, uint32_t>;
188 
189 class MCDecodedPseudoProbe : public MCPseudoProbeBase {
190   uint64_t Address;
191   MCDecodedPseudoProbeInlineTree *InlineTree;
192 
193 public:
MCDecodedPseudoProbe(uint64_t Ad,uint32_t I,PseudoProbeType K,uint8_t At,uint32_t D,MCDecodedPseudoProbeInlineTree * Tree)194   MCDecodedPseudoProbe(uint64_t Ad, uint32_t I, PseudoProbeType K, uint8_t At,
195                        uint32_t D, MCDecodedPseudoProbeInlineTree *Tree)
196       : MCPseudoProbeBase(I, At, static_cast<uint8_t>(K), D), Address(Ad),
197         InlineTree(Tree){};
198   LLVM_ABI uint64_t getGuid() const;
199 
getAddress()200   uint64_t getAddress() const { return Address; }
201 
setAddress(uint64_t Addr)202   void setAddress(uint64_t Addr) { Address = Addr; }
203 
getInlineTreeNode()204   MCDecodedPseudoProbeInlineTree *getInlineTreeNode() const {
205     return InlineTree;
206   }
207 
208   // Get the inlined context by traversing current inline tree backwards,
209   // each tree node has its InlineSite which is taken as the context.
210   // \p ContextStack is populated in root to leaf order
211   LLVM_ABI void
212   getInlineContext(SmallVectorImpl<MCPseudoProbeFrameLocation> &ContextStack,
213                    const GUIDProbeFunctionMap &GUID2FuncMAP) const;
214 
215   // Helper function to get the string from context stack
216   LLVM_ABI std::string
217   getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const;
218 
219   // Print pseudo probe while disassembling
220   LLVM_ABI void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP,
221                       bool ShowName) const;
222 };
223 
224 // Address to pseudo probes map.
225 class AddressProbesMap
226     : public std::vector<std::reference_wrapper<MCDecodedPseudoProbe>> {
getIt(uint64_t Addr)227   auto getIt(uint64_t Addr) const {
228     auto CompareProbe = [](const MCDecodedPseudoProbe &Probe, uint64_t Addr) {
229       return Probe.getAddress() < Addr;
230     };
231     return llvm::lower_bound(*this, Addr, CompareProbe);
232   }
233 
234 public:
235   // Returns range of probes within [\p From, \p To) address range.
find(uint64_t From,uint64_t To)236   auto find(uint64_t From, uint64_t To) const {
237     return llvm::make_range(getIt(From), getIt(To));
238   }
239   // Returns range of probes with given \p Address.
find(uint64_t Address)240   auto find(uint64_t Address) const {
241     auto FromIt = getIt(Address);
242     if (FromIt == end() || FromIt->get().getAddress() != Address)
243       return llvm::make_range(end(), end());
244     auto ToIt = getIt(Address + 1);
245     return llvm::make_range(FromIt, ToIt);
246   }
247 };
248 
249 template <typename ProbesType, typename DerivedProbeInlineTreeType,
250           typename InlinedProbeTreeMap>
251 class MCPseudoProbeInlineTreeBase {
252 protected:
253   // Track children (e.g. inlinees) of current context
254   InlinedProbeTreeMap Children;
255   // Set of probes that come with the function.
256   ProbesType Probes;
MCPseudoProbeInlineTreeBase()257   MCPseudoProbeInlineTreeBase() {
258     static_assert(std::is_base_of<MCPseudoProbeInlineTreeBase,
259                                   DerivedProbeInlineTreeType>::value,
260                   "DerivedProbeInlineTreeType must be subclass of "
261                   "MCPseudoProbeInlineTreeBase");
262   }
263 
264 public:
265   uint64_t Guid = 0;
266 
267   // Root node has a GUID 0.
isRoot()268   bool isRoot() const { return Guid == 0; }
getChildren()269   InlinedProbeTreeMap &getChildren() { return Children; }
getChildren()270   const InlinedProbeTreeMap &getChildren() const { return Children; }
getProbes()271   const ProbesType &getProbes() const { return Probes; }
272   // Caller node of the inline site
273   MCPseudoProbeInlineTreeBase<ProbesType, DerivedProbeInlineTreeType,
274                               InlinedProbeTreeMap> *Parent = nullptr;
getOrAddNode(const InlineSite & Site)275   DerivedProbeInlineTreeType *getOrAddNode(const InlineSite &Site) {
276     auto Ret = Children.emplace(
277         Site, std::make_unique<DerivedProbeInlineTreeType>(Site));
278     Ret.first->second->Parent = this;
279     return Ret.first->second.get();
280   };
281 };
282 
283 // A Tri-tree based data structure to group probes by inline stack.
284 // A tree is allocated for a standalone .text section. A fake
285 // instance is created as the root of a tree.
286 // A real instance of this class is created for each function, either a
287 // not inlined function that has code in .text section or an inlined function.
288 struct InlineSiteHash {
operatorInlineSiteHash289   uint64_t operator()(const InlineSite &Site) const {
290     return std::get<0>(Site) ^ std::get<1>(Site);
291   }
292 };
293 class MCPseudoProbeInlineTree
294     : public MCPseudoProbeInlineTreeBase<
295           std::vector<MCPseudoProbe>, MCPseudoProbeInlineTree,
296           std::unordered_map<InlineSite,
297                              std::unique_ptr<MCPseudoProbeInlineTree>,
298                              InlineSiteHash>> {
299 public:
300   MCPseudoProbeInlineTree() = default;
MCPseudoProbeInlineTree(uint64_t Guid)301   MCPseudoProbeInlineTree(uint64_t Guid) { this->Guid = Guid; }
MCPseudoProbeInlineTree(const InlineSite & Site)302   MCPseudoProbeInlineTree(const InlineSite &Site) {
303     this->Guid = std::get<0>(Site);
304   }
305 
306   // MCPseudoProbeInlineTree method based on Inlinees
307   LLVM_ABI void addPseudoProbe(const MCPseudoProbe &Probe,
308                                const MCPseudoProbeInlineStack &InlineStack);
309   LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe);
310 };
311 
312 // inline tree node for the decoded pseudo probe
313 class MCDecodedPseudoProbeInlineTree
314     : public MCPseudoProbeInlineTreeBase<
315           MCDecodedPseudoProbe *, MCDecodedPseudoProbeInlineTree,
316           MutableArrayRef<MCDecodedPseudoProbeInlineTree>> {
317   uint32_t NumProbes = 0;
318   uint32_t ProbeId = 0;
319 
320 public:
321   MCDecodedPseudoProbeInlineTree() = default;
MCDecodedPseudoProbeInlineTree(const InlineSite & Site,MCDecodedPseudoProbeInlineTree * Parent)322   MCDecodedPseudoProbeInlineTree(const InlineSite &Site,
323                                  MCDecodedPseudoProbeInlineTree *Parent)
324       : ProbeId(std::get<1>(Site)) {
325     this->Guid = std::get<0>(Site);
326     this->Parent = Parent;
327   }
328 
329   // Return false if it's a dummy inline site
hasInlineSite()330   bool hasInlineSite() const { return !isRoot() && !Parent->isRoot(); }
getInlineSite()331   InlineSite getInlineSite() const { return InlineSite(Guid, ProbeId); }
setProbes(MutableArrayRef<MCDecodedPseudoProbe> ProbesRef)332   void setProbes(MutableArrayRef<MCDecodedPseudoProbe> ProbesRef) {
333     Probes = ProbesRef.data();
334     NumProbes = ProbesRef.size();
335   }
getProbes()336   auto getProbes() const {
337     return MutableArrayRef<MCDecodedPseudoProbe>(Probes, NumProbes);
338   }
339 };
340 
341 /// Instances of this class represent the pseudo probes inserted into a compile
342 /// unit.
343 class MCPseudoProbeSections {
344 public:
addPseudoProbe(MCSymbol * FuncSym,const MCPseudoProbe & Probe,const MCPseudoProbeInlineStack & InlineStack)345   void addPseudoProbe(MCSymbol *FuncSym, const MCPseudoProbe &Probe,
346                       const MCPseudoProbeInlineStack &InlineStack) {
347     MCProbeDivisions[FuncSym].addPseudoProbe(Probe, InlineStack);
348   }
349 
350   // The addresses of MCPseudoProbeInlineTree are used by the tree structure and
351   // need to be stable.
352   using MCProbeDivisionMap = std::unordered_map<MCSymbol *, MCPseudoProbeInlineTree>;
353 
354 private:
355   // A collection of MCPseudoProbe for each function. The MCPseudoProbes are
356   // grouped by GUIDs due to inlining that can bring probes from different
357   // functions into one function.
358   MCProbeDivisionMap MCProbeDivisions;
359 
360 public:
getMCProbes()361   const MCProbeDivisionMap &getMCProbes() const { return MCProbeDivisions; }
362 
empty()363   bool empty() const { return MCProbeDivisions.empty(); }
364 
365   LLVM_ABI void emit(MCObjectStreamer *MCOS);
366 };
367 
368 class MCPseudoProbeTable {
369   // A collection of MCPseudoProbe in the current module grouped by
370   // functions. MCPseudoProbes will be encoded into a corresponding
371   // .pseudoprobe section. With functions emitted as separate comdats,
372   // a text section really only contains the code of a function solely, and the
373   // probes associated with the text section will be emitted into a standalone
374   // .pseudoprobe section that shares the same comdat group with the function.
375   MCPseudoProbeSections MCProbeSections;
376 
377 public:
378   LLVM_ABI static void emit(MCObjectStreamer *MCOS);
379 
getProbeSections()380   MCPseudoProbeSections &getProbeSections() { return MCProbeSections; }
381 
382 #ifndef NDEBUG
383   static int DdgPrintIndent;
384 #endif
385 };
386 
387 class MCPseudoProbeDecoder {
388   // Decoded pseudo probes vector.
389   std::vector<MCDecodedPseudoProbe> PseudoProbeVec;
390   // Injected pseudo probes, identified by the containing inline tree node.
391   // Need to keep injected probes separately for two reasons:
392   // 1) Probes cannot be added to the PseudoProbeVec: appending may cause
393   //    reallocation so that pointers to its elements will become invalid.
394   // 2) Probes belonging to function record must be contiguous in PseudoProbeVec
395   //    as owning InlineTree references them with an ArrayRef to save space.
396   std::unordered_map<const MCDecodedPseudoProbeInlineTree *,
397                      std::vector<MCDecodedPseudoProbe>>
398       InjectedProbeMap;
399   // Decoded inline records vector.
400   std::vector<MCDecodedPseudoProbeInlineTree> InlineTreeVec;
401 
402   // GUID to PseudoProbeFuncDesc map.
403   GUIDProbeFunctionMap GUID2FuncDescMap;
404 
405   BumpPtrAllocator FuncNameAllocator;
406 
407   // Address to probes map.
408   AddressProbesMap Address2ProbesMap;
409 
410   // The dummy root of the inline trie, all the outlined function will directly
411   // be the children of the dummy root, all the inlined function will be the
412   // children of its inlineer. So the relation would be like:
413   // DummyRoot --> OutlinedFunc --> InlinedFunc1 --> InlinedFunc2
414   MCDecodedPseudoProbeInlineTree DummyInlineRoot;
415 
416   /// Points to the current location in the buffer.
417   const uint8_t *Data = nullptr;
418 
419   /// Points to the end of the buffer.
420   const uint8_t *End = nullptr;
421 
422   /// Whether encoding is based on a starting probe with absolute code address.
423   bool EncodingIsAddrBased = false;
424 
425   // Decoding helper function
426   template <typename T> ErrorOr<T> readUnencodedNumber();
427   template <typename T> ErrorOr<T> readUnsignedNumber();
428   template <typename T> ErrorOr<T> readSignedNumber();
429   ErrorOr<StringRef> readString(uint32_t Size);
430 
431 public:
432   using Uint64Set = DenseSet<uint64_t>;
433   using Uint64Map = DenseMap<uint64_t, uint64_t>;
434 
435   // Decode pseudo_probe_desc section to build GUID to PseudoProbeFuncDesc map.
436   // If pseudo_probe_desc section is mapped to memory and \p IsMMapped is true,
437   // uses StringRefs pointing to the section.
438   LLVM_ABI bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size,
439                                       bool IsMMapped = false);
440 
441   // Decode pseudo_probe section to count the number of probes and inlined
442   // function records for each function record.
443   template <bool IsTopLevelFunc>
444   bool countRecords(bool &Discard, uint32_t &ProbeCount, uint32_t &InlinedCount,
445                     const Uint64Set &GuidFilter);
446 
447   // Decode pseudo_probe section to build address to probes map for specifed
448   // functions only.
449   LLVM_ABI bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size,
450                                       const Uint64Set &GuildFilter,
451                                       const Uint64Map &FuncStartAddrs);
452 
453   // Print pseudo_probe_desc section info
454   LLVM_ABI void printGUID2FuncDescMap(raw_ostream &OS);
455 
456   // Print pseudo_probe section info, used along with show-disassembly
457   LLVM_ABI void printProbeForAddress(raw_ostream &OS, uint64_t Address);
458 
459   // do printProbeForAddress for all addresses
460   LLVM_ABI void printProbesForAllAddresses(raw_ostream &OS);
461 
462   // Look up the probe of a call for the input address
463   LLVM_ABI const MCDecodedPseudoProbe *
464   getCallProbeForAddr(uint64_t Address) const;
465 
466   LLVM_ABI const MCPseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) const;
467 
468   // Helper function to populate one probe's inline stack into
469   // \p InlineContextStack.
470   // Current leaf location info will be added if IncludeLeaf is true
471   // Example:
472   //  Current probe(bar:3) inlined at foo:2 then inlined at main:1
473   //  IncludeLeaf = true,  Output: [main:1, foo:2, bar:3]
474   //  IncludeLeaf = false, Output: [main:1, foo:2]
475   LLVM_ABI void getInlineContextForProbe(
476       const MCDecodedPseudoProbe *Probe,
477       SmallVectorImpl<MCPseudoProbeFrameLocation> &InlineContextStack,
478       bool IncludeLeaf) const;
479 
getAddress2ProbesMap()480   const AddressProbesMap &getAddress2ProbesMap() const {
481     return Address2ProbesMap;
482   }
483 
getAddress2ProbesMap()484   AddressProbesMap &getAddress2ProbesMap() { return Address2ProbesMap; }
485 
getGUID2FuncDescMap()486   const GUIDProbeFunctionMap &getGUID2FuncDescMap() const {
487     return GUID2FuncDescMap;
488   }
489 
490   LLVM_ABI const MCPseudoProbeFuncDesc *
491   getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const;
492 
getDummyInlineRoot()493   const MCDecodedPseudoProbeInlineTree &getDummyInlineRoot() const {
494     return DummyInlineRoot;
495   }
496 
addInjectedProbe(const MCDecodedPseudoProbe & Probe,uint64_t Address)497   void addInjectedProbe(const MCDecodedPseudoProbe &Probe, uint64_t Address) {
498     const MCDecodedPseudoProbeInlineTree *Parent = Probe.getInlineTreeNode();
499     InjectedProbeMap[Parent].emplace_back(Probe).setAddress(Address);
500   }
501 
502   size_t
getNumInjectedProbes(const MCDecodedPseudoProbeInlineTree * Parent)503   getNumInjectedProbes(const MCDecodedPseudoProbeInlineTree *Parent) const {
504     auto It = InjectedProbeMap.find(Parent);
505     if (It == InjectedProbeMap.end())
506       return 0;
507     return It->second.size();
508   }
509 
getInjectedProbes(MCDecodedPseudoProbeInlineTree * Parent)510   auto getInjectedProbes(MCDecodedPseudoProbeInlineTree *Parent) {
511     auto It = InjectedProbeMap.find(Parent);
512     assert(It != InjectedProbeMap.end());
513     return iterator_range(It->second);
514   }
515 
getInlineTreeVec()516   ArrayRef<MCDecodedPseudoProbeInlineTree> getInlineTreeVec() const {
517     return InlineTreeVec;
518   }
519 
520 private:
521   // Recursively parse an inlining tree encoded in pseudo_probe section. Returns
522   // whether the the top-level node should be skipped.
523   template <bool IsTopLevelFunc>
524   bool buildAddress2ProbeMap(MCDecodedPseudoProbeInlineTree *Cur,
525                              uint64_t &LastAddr, const Uint64Set &GuildFilter,
526                              const Uint64Map &FuncStartAddrs,
527                              const uint32_t CurChildIndex);
528 };
529 
530 } // end namespace llvm
531 
532 #endif // LLVM_MC_MCPSEUDOPROBE_H
533