Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:24

0001 //===- InstrProfCorrelator.h ------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 // This file defines InstrProfCorrelator used to generate PGO/coverage profiles
0009 // from raw profile data and debug info/binary file.
0010 //===----------------------------------------------------------------------===//
0011 
0012 #ifndef LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
0013 #define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
0014 
0015 #include "llvm/ADT/DenseSet.h"
0016 #include "llvm/Debuginfod/BuildIDFetcher.h"
0017 #include "llvm/Object/BuildID.h"
0018 #include "llvm/ProfileData/InstrProf.h"
0019 #include "llvm/Support/Error.h"
0020 #include "llvm/Support/MemoryBuffer.h"
0021 #include "llvm/Support/YAMLTraits.h"
0022 #include <optional>
0023 #include <vector>
0024 
0025 namespace llvm {
0026 class DWARFContext;
0027 class DWARFDie;
0028 namespace object {
0029 class ObjectFile;
0030 }
0031 
0032 /// InstrProfCorrelator - A base class used to create raw instrumentation data
0033 /// to their functions.
0034 class InstrProfCorrelator {
0035 public:
0036   /// Indicate if we should use the debug info or profile metadata sections to
0037   /// correlate.
0038   enum ProfCorrelatorKind { NONE, DEBUG_INFO, BINARY };
0039 
0040   static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
0041   get(StringRef Filename, ProfCorrelatorKind FileKind,
0042       const object::BuildIDFetcher *BIDFetcher = nullptr,
0043       const ArrayRef<llvm::object::BuildID> BIs = {});
0044 
0045   /// Construct a ProfileData vector used to correlate raw instrumentation data
0046   /// to their functions.
0047   /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
0048   virtual Error correlateProfileData(int MaxWarnings) = 0;
0049 
0050   /// Process debug info and dump the correlation data.
0051   /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
0052   virtual Error dumpYaml(int MaxWarnings, raw_ostream &OS) = 0;
0053 
0054   /// Return the number of ProfileData elements.
0055   std::optional<size_t> getDataSize() const;
0056 
0057   /// Return a pointer to the names string that this class constructs.
0058   const char *getNamesPointer() const { return Names.c_str(); }
0059 
0060   /// Return the number of bytes in the names string.
0061   size_t getNamesSize() const { return Names.size(); }
0062 
0063   /// Return the size of the counters section in bytes.
0064   uint64_t getCountersSectionSize() const {
0065     return Ctx->CountersSectionEnd - Ctx->CountersSectionStart;
0066   }
0067 
0068   static const char *FunctionNameAttributeName;
0069   static const char *CFGHashAttributeName;
0070   static const char *NumCountersAttributeName;
0071 
0072   enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit };
0073   InstrProfCorrelatorKind getKind() const { return Kind; }
0074   virtual ~InstrProfCorrelator() = default;
0075 
0076 protected:
0077   struct Context {
0078     static llvm::Expected<std::unique_ptr<Context>>
0079     get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj,
0080         ProfCorrelatorKind FileKind);
0081     std::unique_ptr<MemoryBuffer> Buffer;
0082     /// The address range of the __llvm_prf_cnts section.
0083     uint64_t CountersSectionStart;
0084     uint64_t CountersSectionEnd;
0085     /// The pointer points to start/end of profile data/name sections if
0086     /// FileKind is Binary.
0087     const char *DataStart;
0088     const char *DataEnd;
0089     const char *NameStart;
0090     size_t NameSize;
0091     /// True if target and host have different endian orders.
0092     bool ShouldSwapBytes;
0093   };
0094   const std::unique_ptr<Context> Ctx;
0095 
0096   InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx)
0097       : Ctx(std::move(Ctx)), Kind(K) {}
0098 
0099   std::string Names;
0100   std::vector<std::string> NamesVec;
0101 
0102   struct Probe {
0103     std::string FunctionName;
0104     std::optional<std::string> LinkageName;
0105     yaml::Hex64 CFGHash;
0106     yaml::Hex64 CounterOffset;
0107     uint32_t NumCounters;
0108     std::optional<std::string> FilePath;
0109     std::optional<int> LineNumber;
0110   };
0111 
0112   struct CorrelationData {
0113     std::vector<Probe> Probes;
0114   };
0115 
0116   friend struct yaml::MappingTraits<Probe>;
0117   friend struct yaml::SequenceElementTraits<Probe>;
0118   friend struct yaml::MappingTraits<CorrelationData>;
0119 
0120 private:
0121   static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
0122   get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind);
0123 
0124   const InstrProfCorrelatorKind Kind;
0125 };
0126 
0127 /// InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template
0128 /// pointer type so that the ProfileData vector can be materialized.
0129 template <class IntPtrT>
0130 class InstrProfCorrelatorImpl : public InstrProfCorrelator {
0131 public:
0132   InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx);
0133   static bool classof(const InstrProfCorrelator *C);
0134 
0135   /// Return a pointer to the underlying ProfileData vector that this class
0136   /// constructs.
0137   const RawInstrProf::ProfileData<IntPtrT> *getDataPointer() const {
0138     return Data.empty() ? nullptr : Data.data();
0139   }
0140 
0141   /// Return the number of ProfileData elements.
0142   size_t getDataSize() const { return Data.size(); }
0143 
0144   static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
0145   get(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
0146       const object::ObjectFile &Obj, ProfCorrelatorKind FileKind);
0147 
0148 protected:
0149   std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
0150 
0151   Error correlateProfileData(int MaxWarnings) override;
0152   virtual void correlateProfileDataImpl(
0153       int MaxWarnings,
0154       InstrProfCorrelator::CorrelationData *Data = nullptr) = 0;
0155 
0156   virtual Error correlateProfileNameImpl() = 0;
0157 
0158   Error dumpYaml(int MaxWarnings, raw_ostream &OS) override;
0159 
0160   void addDataProbe(uint64_t FunctionName, uint64_t CFGHash,
0161                     IntPtrT CounterOffset, IntPtrT FunctionPtr,
0162                     uint32_t NumCounters);
0163 
0164   // Byte-swap the value if necessary.
0165   template <class T> T maybeSwap(T Value) const {
0166     return Ctx->ShouldSwapBytes ? llvm::byteswap(Value) : Value;
0167   }
0168 
0169 private:
0170   InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind,
0171                           std::unique_ptr<InstrProfCorrelator::Context> Ctx)
0172       : InstrProfCorrelator(Kind, std::move(Ctx)){};
0173   llvm::DenseSet<IntPtrT> CounterOffsets;
0174 };
0175 
0176 /// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes
0177 /// DWARF debug info as input to correlate profiles.
0178 template <class IntPtrT>
0179 class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
0180 public:
0181   DwarfInstrProfCorrelator(std::unique_ptr<DWARFContext> DICtx,
0182                            std::unique_ptr<InstrProfCorrelator::Context> Ctx)
0183       : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)),
0184         DICtx(std::move(DICtx)) {}
0185 
0186 private:
0187   std::unique_ptr<DWARFContext> DICtx;
0188 
0189   /// Return the address of the object that the provided DIE symbolizes.
0190   std::optional<uint64_t> getLocation(const DWARFDie &Die) const;
0191 
0192   /// Returns true if the provided DIE symbolizes an instrumentation probe
0193   /// symbol.
0194   static bool isDIEOfProbe(const DWARFDie &Die);
0195 
0196   /// Iterate over DWARF DIEs to find those that symbolize instrumentation
0197   /// probes and construct the ProfileData vector and Names string.
0198   ///
0199   /// Here is some example DWARF for an instrumentation probe we are looking
0200   /// for:
0201   /// \code
0202   ///   DW_TAG_subprogram
0203   ///   DW_AT_low_pc    (0x0000000000000000)
0204   ///   DW_AT_high_pc   (0x0000000000000014)
0205   ///   DW_AT_name  ("foo")
0206   ///     DW_TAG_variable
0207   ///       DW_AT_name  ("__profc_foo")
0208   ///       DW_AT_location  (DW_OP_addr 0x0)
0209   ///       DW_TAG_LLVM_annotation
0210   ///         DW_AT_name    ("Function Name")
0211   ///         DW_AT_const_value ("foo")
0212   ///       DW_TAG_LLVM_annotation
0213   ///         DW_AT_name    ("CFG Hash")
0214   ///         DW_AT_const_value (12345678)
0215   ///       DW_TAG_LLVM_annotation
0216   ///         DW_AT_name    ("Num Counters")
0217   ///         DW_AT_const_value (2)
0218   ///       NULL
0219   ///     NULL
0220   /// \endcode
0221   /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
0222   /// \param Data if provided, populate with the correlation data found
0223   void correlateProfileDataImpl(
0224       int MaxWarnings,
0225       InstrProfCorrelator::CorrelationData *Data = nullptr) override;
0226 
0227   Error correlateProfileNameImpl() override;
0228 };
0229 
0230 /// BinaryInstrProfCorrelator - A child of InstrProfCorrelatorImpl that
0231 /// takes an object file as input to correlate profiles.
0232 template <class IntPtrT>
0233 class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
0234 public:
0235   BinaryInstrProfCorrelator(std::unique_ptr<InstrProfCorrelator::Context> Ctx)
0236       : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)) {}
0237 
0238   /// Return a pointer to the names string that this class constructs.
0239   const char *getNamesPointer() const { return this->Ctx.NameStart; }
0240 
0241   /// Return the number of bytes in the names string.
0242   size_t getNamesSize() const { return this->Ctx.NameSize; }
0243 
0244 private:
0245   void correlateProfileDataImpl(
0246       int MaxWarnings,
0247       InstrProfCorrelator::CorrelationData *Data = nullptr) override;
0248 
0249   Error correlateProfileNameImpl() override;
0250 };
0251 
0252 } // end namespace llvm
0253 
0254 #endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H