Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp
35233 views
//===- lib/MC/MCPseudoProbe.cpp - Pseudo probe encoding support ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/MC/MCPseudoProbe.h"9#include "llvm/ADT/STLExtras.h"10#include "llvm/IR/PseudoProbe.h"11#include "llvm/MC/MCAsmInfo.h"12#include "llvm/MC/MCAssembler.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>2930#define DEBUG_TYPE "mcpseudoprobe"3132using namespace llvm;33using namespace support;3435#ifndef NDEBUG36int MCPseudoProbeTable::DdgPrintIndent = 0;37#endif3839static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A,40const MCSymbol *B) {41MCContext &Context = MCOS->getContext();42MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;43const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);44const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);45const MCExpr *AddrDelta =46MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);47return AddrDelta;48}4950void MCPseudoProbe::emit(MCObjectStreamer *MCOS,51const MCPseudoProbe *LastProbe) const {52bool IsSentinel = isSentinelProbe(getAttributes());53assert((LastProbe || IsSentinel) &&54"Last probe should not be null for non-sentinel probes");5556// Emit Index57MCOS->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 whether61// the following field is a symbolic code address or an address delta.62// Emit FS discriminator63assert(Type <= 0xF && "Probe type too big to encode, exceeding 15");64auto NewAttributes = Attributes;65if (Discriminator)66NewAttributes |= (uint32_t)PseudoProbeAttributes::HasDiscriminator;67assert(NewAttributes <= 0x7 &&68"Probe attributes too big to encode, exceeding 7");69uint8_t PackedType = Type | (NewAttributes << 4);70uint8_t Flag =71!IsSentinel ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0;72MCOS->emitInt8(Flag | PackedType);7374if (!IsSentinel) {75// Emit the delta between the address label and LastProbe.76const MCExpr *AddrDelta =77buildSymbolDiff(MCOS, Label, LastProbe->getLabel());78int64_t Delta;79if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) {80MCOS->emitSLEB128IntValue(Delta);81} else {82MCOS->insert(MCOS->getContext().allocFragment<MCPseudoProbeAddrFragment>(83AddrDelta));84}85} else {86// Emit the GUID of the split function that the sentinel probe represents.87MCOS->emitInt64(Guid);88}8990if (Discriminator)91MCOS->emitULEB128IntValue(Discriminator);9293LLVM_DEBUG({94dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);95dbgs() << "Probe: " << Index << "\n";96});97}9899void MCPseudoProbeInlineTree::addPseudoProbe(100const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {101// The function should not be called on the root.102assert(isRoot() && "Should only be called on root");103104// 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 of108// 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 be110// added. Note that the edge [0, A] means A is the top-level function we are111// emitting probes for.112113// Make a [0, A] edge.114// An empty inline stack means the function that the probe originates from115// is a top-level function.116InlineSite Top;117if (InlineStack.empty()) {118Top = InlineSite(Probe.getGuid(), 0);119} else {120Top = InlineSite(std::get<0>(InlineStack.front()), 0);121}122123auto *Cur = getOrAddNode(Top);124125// Make interior edges by walking the inline stack. Once it's done, Cur should126// point to the node that the probe originates from.127if (!InlineStack.empty()) {128auto Iter = InlineStack.begin();129auto Index = std::get<1>(*Iter);130Iter++;131for (; Iter != InlineStack.end(); Iter++) {132// Make an edge by using the previous probe id and current GUID.133Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index));134Index = std::get<1>(*Iter);135}136Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index));137}138139Cur->Probes.push_back(Probe);140}141142void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,143const MCPseudoProbe *&LastProbe) {144LLVM_DEBUG({145dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);146dbgs() << "Group [\n";147MCPseudoProbeTable::DdgPrintIndent += 2;148});149assert(!isRoot() && "Root should be handled separately");150151// Emit probes grouped by GUID.152LLVM_DEBUG({153dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);154dbgs() << "GUID: " << Guid << "\n";155});156// Emit Guid157MCOS->emitInt64(Guid);158// Emit number of probes in this node, including a sentinel probe for159// top-level functions if needed.160bool NeedSentinel = false;161if (Parent->isRoot()) {162assert(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.165if (LastProbe->getGuid() != Guid)166NeedSentinel = true;167}168169MCOS->emitULEB128IntValue(Probes.size() + NeedSentinel);170// Emit number of direct inlinees171MCOS->emitULEB128IntValue(Children.size());172// Emit sentinel probe for top-level functions173if (NeedSentinel)174LastProbe->emit(MCOS, nullptr);175176// Emit probes in this group177for (const auto &Probe : Probes) {178Probe.emit(MCOS, LastProbe);179LastProbe = &Probe;180}181182// Emit sorted descendant. InlineSite is unique for each pair, so there will183// be no ordering of Inlinee based on MCPseudoProbeInlineTree*184using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;185std::vector<InlineeType> Inlinees;186for (const auto &Child : Children)187Inlinees.emplace_back(Child.first, Child.second.get());188llvm::sort(Inlinees, llvm::less_first());189190for (const auto &Inlinee : Inlinees) {191// Emit probe index192MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first));193LLVM_DEBUG({194dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);195dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n";196});197// Emit the group198Inlinee.second->emit(MCOS, LastProbe);199}200201LLVM_DEBUG({202MCPseudoProbeTable::DdgPrintIndent -= 2;203dbgs().indent(MCPseudoProbeTable::DdgPrintIndent);204dbgs() << "]\n";205});206}207208void MCPseudoProbeSections::emit(MCObjectStreamer *MCOS) {209MCContext &Ctx = MCOS->getContext();210SmallVector<std::pair<MCSymbol *, MCPseudoProbeInlineTree *>> Vec;211Vec.reserve(MCProbeDivisions.size());212for (auto &ProbeSec : MCProbeDivisions)213Vec.emplace_back(ProbeSec.first, &ProbeSec.second);214for (auto I : llvm::enumerate(MCOS->getAssembler()))215I.value().setOrdinal(I.index());216llvm::sort(Vec, [](auto A, auto B) {217return A.first->getSection().getOrdinal() <218B.first->getSection().getOrdinal();219});220for (auto [FuncSym, RootPtr] : Vec) {221const auto &Root = *RootPtr;222if (auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(223FuncSym->getSection())) {224// Switch to the .pseudoprobe section or a comdat group.225MCOS->switchSection(S);226// Emit probes grouped by GUID.227// Emit sorted descendant. InlineSite is unique for each pair, so there228// will be no ordering of Inlinee based on MCPseudoProbeInlineTree*229using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;230std::vector<InlineeType> Inlinees;231for (const auto &Child : Root.getChildren())232Inlinees.emplace_back(Child.first, Child.second.get());233llvm::sort(Inlinees, llvm::less_first());234235for (const auto &Inlinee : Inlinees) {236// Emit the group guarded by a sentinel probe.237MCPseudoProbe SentinelProbe(238const_cast<MCSymbol *>(FuncSym), MD5Hash(FuncSym->getName()),239(uint32_t)PseudoProbeReservedId::Invalid,240(uint32_t)PseudoProbeType::Block,241(uint32_t)PseudoProbeAttributes::Sentinel, 0);242const MCPseudoProbe *Probe = &SentinelProbe;243Inlinee.second->emit(MCOS, Probe);244}245}246}247}248249//250// This emits the pseudo probe tables.251//252void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) {253MCContext &Ctx = MCOS->getContext();254auto &ProbeTable = Ctx.getMCPseudoProbeTable();255256// Bail out early so we don't switch to the pseudo_probe section needlessly257// and in doing so create an unnecessary (if empty) section.258auto &ProbeSections = ProbeTable.getProbeSections();259if (ProbeSections.empty())260return;261262LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent = 0);263264// Put out the probe.265ProbeSections.emit(MCOS);266}267268static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,269uint64_t GUID) {270auto It = GUID2FuncMAP.find(GUID);271assert(It != GUID2FuncMAP.end() &&272"Probe function must exist for a valid GUID");273return It->second.FuncName;274}275276void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {277OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";278OS << "Hash: " << FuncHash << "\n";279}280281void MCDecodedPseudoProbe::getInlineContext(282SmallVectorImpl<MCPseudoProbeFrameLocation> &ContextStack,283const GUIDProbeFunctionMap &GUID2FuncMAP) const {284uint32_t Begin = ContextStack.size();285MCDecodedPseudoProbeInlineTree *Cur = InlineTree;286// It will add the string of each node's inline site during iteration.287// Note that it won't include the probe's belonging function(leaf location)288while (Cur->hasInlineSite()) {289StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Cur->Parent->Guid);290ContextStack.emplace_back(291MCPseudoProbeFrameLocation(FuncName, std::get<1>(Cur->ISite)));292Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);293}294// Make the ContextStack in caller-callee order295std::reverse(ContextStack.begin() + Begin, ContextStack.end());296}297298std::string MCDecodedPseudoProbe::getInlineContextStr(299const GUIDProbeFunctionMap &GUID2FuncMAP) const {300std::ostringstream OContextStr;301SmallVector<MCPseudoProbeFrameLocation, 16> ContextStack;302getInlineContext(ContextStack, GUID2FuncMAP);303for (auto &Cxt : ContextStack) {304if (OContextStr.str().size())305OContextStr << " @ ";306OContextStr << Cxt.first.str() << ":" << Cxt.second;307}308return OContextStr.str();309}310311static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",312"DirectCall"};313314void MCDecodedPseudoProbe::print(raw_ostream &OS,315const GUIDProbeFunctionMap &GUID2FuncMAP,316bool ShowName) const {317OS << "FUNC: ";318if (ShowName) {319StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Guid);320OS << FuncName.str() << " ";321} else {322OS << Guid << " ";323}324OS << "Index: " << Index << " ";325if (Discriminator)326OS << "Discriminator: " << Discriminator << " ";327OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << " ";328std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);329if (InlineContextStr.size()) {330OS << "Inlined: @ ";331OS << InlineContextStr;332}333OS << "\n";334}335336template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {337if (Data + sizeof(T) > End) {338return std::error_code();339}340T Val = endian::readNext<T, llvm::endianness::little>(Data);341return ErrorOr<T>(Val);342}343344template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {345unsigned NumBytesRead = 0;346uint64_t Val = decodeULEB128(Data, &NumBytesRead);347if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {348return std::error_code();349}350Data += NumBytesRead;351return ErrorOr<T>(static_cast<T>(Val));352}353354template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {355unsigned NumBytesRead = 0;356int64_t Val = decodeSLEB128(Data, &NumBytesRead);357if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {358return std::error_code();359}360Data += NumBytesRead;361return ErrorOr<T>(static_cast<T>(Val));362}363364ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {365StringRef Str(reinterpret_cast<const char *>(Data), Size);366if (Data + Size > End) {367return std::error_code();368}369Data += Size;370return ErrorOr<StringRef>(Str);371}372373bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,374std::size_t Size) {375// The pseudo_probe_desc section has a format like:376// .section .pseudo_probe_desc,"",@progbits377// .quad -5182264717993193164 // GUID378// .quad 4294967295 // Hash379// .uleb 3 // Name size380// .ascii "foo" // Name381// .quad -2624081020897602054382// .quad 174696971957383// .uleb 34384// .ascii "main"385386Data = Start;387End = Data + Size;388389while (Data < End) {390auto ErrorOrGUID = readUnencodedNumber<uint64_t>();391if (!ErrorOrGUID)392return false;393394auto ErrorOrHash = readUnencodedNumber<uint64_t>();395if (!ErrorOrHash)396return false;397398auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();399if (!ErrorOrNameSize)400return false;401uint32_t NameSize = std::move(*ErrorOrNameSize);402403auto ErrorOrName = readString(NameSize);404if (!ErrorOrName)405return false;406407uint64_t GUID = std::move(*ErrorOrGUID);408uint64_t Hash = std::move(*ErrorOrHash);409StringRef Name = std::move(*ErrorOrName);410411// Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap412GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));413}414assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");415return true;416}417418bool MCPseudoProbeDecoder::buildAddress2ProbeMap(419MCDecodedPseudoProbeInlineTree *Cur, uint64_t &LastAddr,420const Uint64Set &GuidFilter, const Uint64Map &FuncStartAddrs) {421// The pseudo_probe section encodes an inline forest and each tree has a422// format defined in MCPseudoProbe.h423424uint32_t Index = 0;425bool IsTopLevelFunc = Cur == &DummyInlineRoot;426if (IsTopLevelFunc) {427// Use a sequential id for top level inliner.428Index = Cur->getChildren().size();429} else {430// Read inline site for inlinees431auto ErrorOrIndex = readUnsignedNumber<uint32_t>();432if (!ErrorOrIndex)433return false;434Index = std::move(*ErrorOrIndex);435}436437// Read guid438auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();439if (!ErrorOrCurGuid)440return false;441uint64_t Guid = std::move(*ErrorOrCurGuid);442443// Decide if top-level node should be disgarded.444if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(Guid))445Cur = nullptr;446447// If the incoming node is null, all its children nodes should be disgarded.448if (Cur) {449// Switch/add to a new tree node(inlinee)450Cur = Cur->getOrAddNode(std::make_tuple(Guid, Index));451Cur->Guid = Guid;452if (IsTopLevelFunc && !EncodingIsAddrBased) {453if (auto V = FuncStartAddrs.lookup(Guid))454LastAddr = V;455}456}457458// Read number of probes in the current node.459auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();460if (!ErrorOrNodeCount)461return false;462uint32_t NodeCount = std::move(*ErrorOrNodeCount);463// Read number of direct inlinees464auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();465if (!ErrorOrCurChildrenToProcess)466return false;467// Read all probes in this node468for (std::size_t I = 0; I < NodeCount; I++) {469// Read index470auto ErrorOrIndex = readUnsignedNumber<uint32_t>();471if (!ErrorOrIndex)472return false;473uint32_t Index = std::move(*ErrorOrIndex);474// Read type | flag.475auto ErrorOrValue = readUnencodedNumber<uint8_t>();476if (!ErrorOrValue)477return false;478uint8_t Value = std::move(*ErrorOrValue);479uint8_t Kind = Value & 0xf;480uint8_t Attr = (Value & 0x70) >> 4;481// Read address482uint64_t Addr = 0;483if (Value & 0x80) {484auto ErrorOrOffset = readSignedNumber<int64_t>();485if (!ErrorOrOffset)486return false;487int64_t Offset = std::move(*ErrorOrOffset);488Addr = LastAddr + Offset;489} else {490auto ErrorOrAddr = readUnencodedNumber<int64_t>();491if (!ErrorOrAddr)492return false;493Addr = std::move(*ErrorOrAddr);494if (isSentinelProbe(Attr)) {495// For sentinel probe, the addr field actually stores the GUID of the496// split function. Convert it to the real address.497if (auto V = FuncStartAddrs.lookup(Addr))498Addr = V;499} else {500// For now we assume all probe encoding should be either based on501// leading probe address or function start address.502// The scheme is for downwards compatibility.503// TODO: retire this scheme once compatibility is no longer an issue.504EncodingIsAddrBased = true;505}506}507508uint32_t Discriminator = 0;509if (hasDiscriminator(Attr)) {510auto ErrorOrDiscriminator = readUnsignedNumber<uint32_t>();511if (!ErrorOrDiscriminator)512return false;513Discriminator = std::move(*ErrorOrDiscriminator);514}515516if (Cur && !isSentinelProbe(Attr)) {517// Populate Address2ProbesMap518auto &Probes = Address2ProbesMap[Addr];519Probes.emplace_back(Addr, Cur->Guid, Index, PseudoProbeType(Kind), Attr,520Discriminator, Cur);521Cur->addProbes(&Probes.back());522}523LastAddr = Addr;524}525526uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);527for (uint32_t I = 0; I < ChildrenToProcess; I++) {528buildAddress2ProbeMap(Cur, LastAddr, GuidFilter, FuncStartAddrs);529}530531return true;532}533534bool MCPseudoProbeDecoder::buildAddress2ProbeMap(535const uint8_t *Start, std::size_t Size, const Uint64Set &GuidFilter,536const Uint64Map &FuncStartAddrs) {537Data = Start;538End = Data + Size;539uint64_t LastAddr = 0;540while (Data < End)541buildAddress2ProbeMap(&DummyInlineRoot, LastAddr, GuidFilter,542FuncStartAddrs);543assert(Data == End && "Have unprocessed data in pseudo_probe section");544return true;545}546547void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {548OS << "Pseudo Probe Desc:\n";549// Make the output deterministic550std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),551GUID2FuncDescMap.end());552for (auto &I : OrderedMap) {553I.second.print(OS);554}555}556557void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,558uint64_t Address) {559auto It = Address2ProbesMap.find(Address);560if (It != Address2ProbesMap.end()) {561for (auto &Probe : It->second) {562OS << " [Probe]:\t";563Probe.print(OS, GUID2FuncDescMap, true);564}565}566}567568void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream &OS) {569auto Entries = make_first_range(Address2ProbesMap);570SmallVector<uint64_t, 0> Addresses(Entries.begin(), Entries.end());571llvm::sort(Addresses);572for (auto K : Addresses) {573OS << "Address:\t";574OS << K;575OS << "\n";576printProbeForAddress(OS, K);577}578}579580const MCDecodedPseudoProbe *581MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {582auto It = Address2ProbesMap.find(Address);583if (It == Address2ProbesMap.end())584return nullptr;585const auto &Probes = It->second;586587const MCDecodedPseudoProbe *CallProbe = nullptr;588for (const auto &Probe : Probes) {589if (Probe.isCall()) {590// Disabling the assert and returning first call probe seen so far.591// Subsequent call probes, if any, are ignored. Due to the the way592// .pseudo_probe section is decoded, probes of the same-named independent593// static functions are merged thus multiple call probes may be seen for a594// callsite. This should only happen to compiler-generated statics, with595// -funique-internal-linkage-names where user statics get unique names.596//597// TODO: re-enable or narrow down the assert to static functions only.598//599// assert(!CallProbe &&600// "There should be only one call probe corresponding to address "601// "which is a callsite.");602CallProbe = &Probe;603break;604}605}606return CallProbe;607}608609const MCPseudoProbeFuncDesc *610MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {611auto It = GUID2FuncDescMap.find(GUID);612assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");613return &It->second;614}615616void MCPseudoProbeDecoder::getInlineContextForProbe(617const MCDecodedPseudoProbe *Probe,618SmallVectorImpl<MCPseudoProbeFrameLocation> &InlineContextStack,619bool IncludeLeaf) const {620Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);621if (!IncludeLeaf)622return;623// Note that the context from probe doesn't include leaf frame,624// hence we need to retrieve and prepend leaf if requested.625const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());626InlineContextStack.emplace_back(627MCPseudoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));628}629630const MCPseudoProbeFuncDesc *MCPseudoProbeDecoder::getInlinerDescForProbe(631const MCDecodedPseudoProbe *Probe) const {632MCDecodedPseudoProbeInlineTree *InlinerNode = Probe->getInlineTreeNode();633if (!InlinerNode->hasInlineSite())634return nullptr;635return getFuncDescForGUID(InlinerNode->Parent->Guid);636}637638639