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