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 //===----------------------------------------------------------------------===// 8 9 #include "llvm/MC/MCPseudoProbe.h" 10 #include "llvm/MC/MCAsmInfo.h" 11 #include "llvm/MC/MCContext.h" 12 #include "llvm/MC/MCObjectFileInfo.h" 13 #include "llvm/MC/MCObjectStreamer.h" 14 #include "llvm/MC/MCStreamer.h" 15 16 #define DEBUG_TYPE "mcpseudoprobe" 17 18 using namespace llvm; 19 20 #ifndef NDEBUG 21 int MCPseudoProbeTable::DdgPrintIndent = 0; 22 #endif 23 24 static const MCExpr *buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A, 25 const MCSymbol *B) { 26 MCContext &Context = MCOS->getContext(); 27 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 28 const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context); 29 const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context); 30 const MCExpr *AddrDelta = 31 MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context); 32 return AddrDelta; 33 } 34 35 void MCPseudoProbe::emit(MCObjectStreamer *MCOS, 36 const MCPseudoProbe *LastProbe) const { 37 // Emit Index 38 MCOS->emitULEB128IntValue(Index); 39 // Emit Type and the flag: 40 // Type (bit 0 to 3), with bit 4 to 6 for attributes. 41 // Flag (bit 7, 0 - code address, 1 - address delta). This indicates whether 42 // the following field is a symbolic code address or an address delta. 43 assert(Type <= 0xF && "Probe type too big to encode, exceeding 15"); 44 assert(Attributes <= 0x7 && 45 "Probe attributes too big to encode, exceeding 7"); 46 uint8_t PackedType = Type | (Attributes << 4); 47 uint8_t Flag = LastProbe ? ((int8_t)MCPseudoProbeFlag::AddressDelta << 7) : 0; 48 MCOS->emitInt8(Flag | PackedType); 49 50 if (LastProbe) { 51 // Emit the delta between the address label and LastProbe. 52 const MCExpr *AddrDelta = 53 buildSymbolDiff(MCOS, Label, LastProbe->getLabel()); 54 int64_t Delta; 55 if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) { 56 MCOS->emitSLEB128IntValue(Delta); 57 } else { 58 MCOS->insert(new MCPseudoProbeAddrFragment(AddrDelta)); 59 } 60 } else { 61 // Emit label as a symbolic code address. 62 MCOS->emitSymbolValue( 63 Label, MCOS->getContext().getAsmInfo()->getCodePointerSize()); 64 } 65 66 LLVM_DEBUG({ 67 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent); 68 dbgs() << "Probe: " << Index << "\n"; 69 }); 70 } 71 72 MCPseudoProbeInlineTree::~MCPseudoProbeInlineTree() { 73 for (auto &Inlinee : Inlinees) 74 delete Inlinee.second; 75 } 76 77 MCPseudoProbeInlineTree * 78 MCPseudoProbeInlineTree::getOrAddNode(InlineSite Site) { 79 auto Iter = Inlinees.find(Site); 80 if (Iter == Inlinees.end()) { 81 auto *Node = new MCPseudoProbeInlineTree(std::get<0>(Site)); 82 Inlinees[Site] = Node; 83 return Node; 84 } else { 85 return Iter->second; 86 } 87 } 88 89 void MCPseudoProbeInlineTree::addPseudoProbe( 90 const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) { 91 // The function should not be called on the root. 92 assert(isRoot() && "Should not be called on root"); 93 94 // When it comes here, the input look like: 95 // Probe: GUID of C, ... 96 // InlineStack: [88, A], [66, B] 97 // which means, Function A inlines function B at call site with a probe id of 98 // 88, and B inlines C at probe 66. The tri-tree expects a tree path like {[0, 99 // A], [88, B], [66, C]} to locate the tree node where the probe should be 100 // added. Note that the edge [0, A] means A is the top-level function we are 101 // emitting probes for. 102 103 // Make a [0, A] edge. 104 // An empty inline stack means the function that the probe originates from 105 // is a top-level function. 106 InlineSite Top; 107 if (InlineStack.empty()) { 108 Top = InlineSite(Probe.getGuid(), 0); 109 } else { 110 Top = InlineSite(std::get<0>(InlineStack.front()), 0); 111 } 112 113 auto *Cur = getOrAddNode(Top); 114 115 // Make interior edges by walking the inline stack. Once it's done, Cur should 116 // point to the node that the probe originates from. 117 if (!InlineStack.empty()) { 118 auto Iter = InlineStack.begin(); 119 auto Index = std::get<1>(*Iter); 120 Iter++; 121 for (; Iter != InlineStack.end(); Iter++) { 122 // Make an edge by using the previous probe id and current GUID. 123 Cur = Cur->getOrAddNode(InlineSite(std::get<0>(*Iter), Index)); 124 Index = std::get<1>(*Iter); 125 } 126 Cur = Cur->getOrAddNode(InlineSite(Probe.getGuid(), Index)); 127 } 128 129 Cur->Probes.push_back(Probe); 130 } 131 132 void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS, 133 const MCPseudoProbe *&LastProbe) { 134 LLVM_DEBUG({ 135 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent); 136 dbgs() << "Group [\n"; 137 MCPseudoProbeTable::DdgPrintIndent += 2; 138 }); 139 // Emit probes grouped by GUID. 140 if (Guid != 0) { 141 LLVM_DEBUG({ 142 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent); 143 dbgs() << "GUID: " << Guid << "\n"; 144 }); 145 // Emit Guid 146 MCOS->emitInt64(Guid); 147 // Emit number of probes in this node 148 MCOS->emitULEB128IntValue(Probes.size()); 149 // Emit number of direct inlinees 150 MCOS->emitULEB128IntValue(Inlinees.size()); 151 // Emit probes in this group 152 for (const auto &Probe : Probes) { 153 Probe.emit(MCOS, LastProbe); 154 LastProbe = &Probe; 155 } 156 } else { 157 assert(Probes.empty() && "Root should not have probes"); 158 } 159 160 // Emit descendent 161 for (const auto &Inlinee : Inlinees) { 162 if (Guid) { 163 // Emit probe index 164 MCOS->emitULEB128IntValue(std::get<1>(Inlinee.first)); 165 LLVM_DEBUG({ 166 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent); 167 dbgs() << "InlineSite: " << std::get<1>(Inlinee.first) << "\n"; 168 }); 169 } 170 // Emit the group 171 Inlinee.second->emit(MCOS, LastProbe); 172 } 173 174 LLVM_DEBUG({ 175 MCPseudoProbeTable::DdgPrintIndent -= 2; 176 dbgs().indent(MCPseudoProbeTable::DdgPrintIndent); 177 dbgs() << "]\n"; 178 }); 179 } 180 181 void MCPseudoProbeSection::emit(MCObjectStreamer *MCOS) { 182 MCContext &Ctx = MCOS->getContext(); 183 184 for (auto &ProbeSec : MCProbeDivisions) { 185 const MCPseudoProbe *LastProbe = nullptr; 186 if (auto *S = 187 Ctx.getObjectFileInfo()->getPseudoProbeSection(ProbeSec.first)) { 188 // Switch to the .pseudoprobe section or a comdat group. 189 MCOS->SwitchSection(S); 190 // Emit probes grouped by GUID. 191 ProbeSec.second.emit(MCOS, LastProbe); 192 } 193 } 194 } 195 196 // 197 // This emits the pseudo probe tables. 198 // 199 void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) { 200 MCContext &Ctx = MCOS->getContext(); 201 auto &ProbeTable = Ctx.getMCPseudoProbeTable(); 202 203 // Bail out early so we don't switch to the pseudo_probe section needlessly 204 // and in doing so create an unnecessary (if empty) section. 205 auto &ProbeSections = ProbeTable.getProbeSections(); 206 if (ProbeSections.empty()) 207 return; 208 209 LLVM_DEBUG(MCPseudoProbeTable::DdgPrintIndent = 0); 210 211 // Put out the probe. 212 ProbeSections.emit(MCOS); 213 } 214