Home | History | Annotate | Line # | Download | only in MC
      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