1 //===- llvm/CodeGen/PseudoProbePrinter.cpp - Pseudo Probe Emission -------===// 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 support for writing pseudo probe info into asm files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "PseudoProbePrinter.h" 14 #include "llvm/CodeGen/AsmPrinter.h" 15 #include "llvm/IR/DebugInfoMetadata.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/IR/PseudoProbe.h" 18 #include "llvm/MC/MCPseudoProbe.h" 19 #include "llvm/MC/MCStreamer.h" 20 21 using namespace llvm; 22 23 #define DEBUG_TYPE "pseudoprobe" 24 25 PseudoProbeHandler::~PseudoProbeHandler() = default; 26 27 PseudoProbeHandler::PseudoProbeHandler(AsmPrinter *A, Module *M) : Asm(A) { 28 NamedMDNode *FuncInfo = M->getNamedMetadata(PseudoProbeDescMetadataName); 29 assert(FuncInfo && "Pseudo probe descriptors are missing"); 30 for (const auto *Operand : FuncInfo->operands()) { 31 const auto *MD = cast<MDNode>(Operand); 32 auto GUID = 33 mdconst::dyn_extract<ConstantInt>(MD->getOperand(0))->getZExtValue(); 34 auto Name = cast<MDString>(MD->getOperand(2))->getString(); 35 // We may see pairs with same name but different GUIDs here in LTO mode, due 36 // to static same-named functions inlined from other modules into this 37 // module. Function profiles with the same name will be merged no matter 38 // whether they are collected on the same function. Therefore we just pick 39 // up the last <Name, GUID> pair here to represent the same-named function 40 // collection and all probes from the collection will be merged into a 41 // single profile eventually. 42 Names[Name] = GUID; 43 } 44 45 LLVM_DEBUG(dump()); 46 } 47 48 void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index, 49 uint64_t Type, uint64_t Attr, 50 const DILocation *DebugLoc) { 51 // Gather all the inlined-at nodes. 52 // When it's done ReversedInlineStack looks like ([66, B], [88, A]) 53 // which means, Function A inlines function B at calliste with a probe id 88, 54 // and B inlines C at probe 66 where C is represented by Guid. 55 SmallVector<InlineSite, 8> ReversedInlineStack; 56 auto *InlinedAt = DebugLoc ? DebugLoc->getInlinedAt() : nullptr; 57 while (InlinedAt) { 58 const DISubprogram *SP = InlinedAt->getScope()->getSubprogram(); 59 // Use linkage name for C++ if possible. 60 auto Name = SP->getLinkageName(); 61 if (Name.empty()) 62 Name = SP->getName(); 63 assert(Names.count(Name) && "Pseudo probe descriptor missing for function"); 64 uint64_t CallerGuid = Names[Name]; 65 uint64_t CallerProbeId = PseudoProbeDwarfDiscriminator::extractProbeIndex( 66 InlinedAt->getDiscriminator()); 67 ReversedInlineStack.emplace_back(CallerGuid, CallerProbeId); 68 InlinedAt = InlinedAt->getInlinedAt(); 69 } 70 71 SmallVector<InlineSite, 8> InlineStack(ReversedInlineStack.rbegin(), 72 ReversedInlineStack.rend()); 73 Asm->OutStreamer->emitPseudoProbe(Guid, Index, Type, Attr, InlineStack); 74 } 75 76 #ifndef NDEBUG 77 void PseudoProbeHandler::dump() const { 78 dbgs() << "\n=============================\n"; 79 dbgs() << "\nFunction Name to GUID map:\n"; 80 dbgs() << "\n=============================\n"; 81 for (const auto &Item : Names) 82 dbgs() << "Func: " << Item.first << " GUID: " << Item.second << "\n"; 83 } 84 #endif 85