//===- MCPseudoProbe.h - Pseudo probe encoding support ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains the declaration of the MCPseudoProbe to support the pseudo // probe encoding for AutoFDO. Pseudo probes together with their inline context // are encoded in a DFS recursive way in the .pseudoprobe sections. For each // .pseudoprobe section, the encoded binary data consist of a single or mutiple // function records each for one outlined function. A function record has the // following format : // // FUNCTION BODY (one for each outlined function present in the text section) // GUID (uint64) // GUID of the function // NPROBES (ULEB128) // Number of probes originating from this function. // NUM_INLINED_FUNCTIONS (ULEB128) // Number of callees inlined into this function, aka number of // first-level inlinees // PROBE RECORDS // A list of NPROBES entries. Each entry contains: // INDEX (ULEB128) // TYPE (uint4) // 0 - block probe, 1 - indirect call, 2 - direct call // ATTRIBUTE (uint3) // 1 - reserved // ADDRESS_TYPE (uint1) // 0 - code address, 1 - address delta // CODE_ADDRESS (uint64 or ULEB128) // code address or address delta, depending on ADDRESS_TYPE // INLINED FUNCTION RECORDS // A list of NUM_INLINED_FUNCTIONS entries describing each of the inlined // callees. Each record contains: // INLINE SITE // ID of the callsite probe (ULEB128) // FUNCTION BODY // A FUNCTION BODY entry describing the inlined function. //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MCPSEUDOPROBE_H #define LLVM_MC_MCPSEUDOPROBE_H #include "llvm/ADT/MapVector.h" #include "llvm/MC/MCSection.h" #include #include #include namespace llvm { class MCStreamer; class MCSymbol; class MCObjectStreamer; enum class MCPseudoProbeFlag { // If set, indicates that the probe is encoded as an address delta // instead of a real code address. AddressDelta = 0x1, }; /// Instances of this class represent a pseudo probe instance for a pseudo probe /// table entry, which is created during a machine instruction is assembled and /// uses an address from a temporary label created at the current address in the /// current section. class MCPseudoProbe { MCSymbol *Label; uint64_t Guid; uint64_t Index; uint8_t Type; uint8_t Attributes; public: MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attributes) : Label(Label), Guid(Guid), Index(Index), Type(Type), Attributes(Attributes) { assert(Type <= 0xFF && "Probe type too big to encode, exceeding 2^8"); assert(Attributes <= 0xFF && "Probe attributes too big to encode, exceeding 2^16"); } MCSymbol *getLabel() const { return Label; } uint64_t getGuid() const { return Guid; } uint64_t getIndex() const { return Index; } uint8_t getType() const { return Type; } uint8_t getAttributes() const { return Attributes; } void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const; }; // An inline frame has the form using InlineSite = std::tuple; using MCPseudoProbeInlineStack = SmallVector; // A Tri-tree based data structure to group probes by inline stack. // A tree is allocated for a standalone .text section. A fake // instance is created as the root of a tree. // A real instance of this class is created for each function, either an // unlined function that has code in .text section or an inlined function. class MCPseudoProbeInlineTree { uint64_t Guid; // Set of probes that come with the function. std::vector Probes; // Use std::map for a deterministic output. std::map Inlinees; // Root node has a GUID 0. bool isRoot() { return Guid == 0; } MCPseudoProbeInlineTree *getOrAddNode(InlineSite Site); public: MCPseudoProbeInlineTree() = default; MCPseudoProbeInlineTree(uint64_t Guid) : Guid(Guid) {} ~MCPseudoProbeInlineTree(); void addPseudoProbe(const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack); void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe); }; /// Instances of this class represent the pseudo probes inserted into a compile /// unit. class MCPseudoProbeSection { public: void addPseudoProbe(MCSection *Sec, const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) { MCProbeDivisions[Sec].addPseudoProbe(Probe, InlineStack); } // TODO: Sort by getOrdinal to ensure a determinstic section order using MCProbeDivisionMap = std::map; private: // A collection of MCPseudoProbe for each text section. The MCPseudoProbes // are grouped by GUID of the functions where they are from and will be // encoded by groups. In the comdat scenario where a text section really only // contains the code of a function solely, the probes associated with a comdat // function are still grouped by GUIDs due to inlining that can bring probes // from different functions into one function. MCProbeDivisionMap MCProbeDivisions; public: const MCProbeDivisionMap &getMCProbes() const { return MCProbeDivisions; } bool empty() const { return MCProbeDivisions.empty(); } void emit(MCObjectStreamer *MCOS); }; class MCPseudoProbeTable { // A collection of MCPseudoProbe in the current module grouped by text // sections. MCPseudoProbes will be encoded into a corresponding // .pseudoprobe section. With functions emitted as separate comdats, // a text section really only contains the code of a function solely, and the // probes associated with the text section will be emitted into a standalone // .pseudoprobe section that shares the same comdat group with the function. MCPseudoProbeSection MCProbeSections; public: static void emit(MCObjectStreamer *MCOS); MCPseudoProbeSection &getProbeSections() { return MCProbeSections; } #ifndef NDEBUG static int DdgPrintIndent; #endif }; } // end namespace llvm #endif // LLVM_MC_MCPSEUDOPROBE_H