xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ProfileData/InstrProfCorrelator.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- InstrProfCorrelator.h ------------------------------------*- C++ -*-===//
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 // This file defines InstrProfCorrelator used to generate PGO/coverage profiles
9 // from raw profile data and debug info/binary file.
10 //===----------------------------------------------------------------------===//
11 
12 #ifndef LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
13 #define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
14 
15 #include "llvm/ADT/DenseSet.h"
16 #include "llvm/Debuginfod/BuildIDFetcher.h"
17 #include "llvm/Object/BuildID.h"
18 #include "llvm/ProfileData/InstrProf.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/YAMLTraits.h"
23 #include <optional>
24 #include <vector>
25 
26 namespace llvm {
27 class DWARFContext;
28 class DWARFDie;
29 namespace object {
30 class ObjectFile;
31 }
32 
33 /// InstrProfCorrelator - A base class used to create raw instrumentation data
34 /// to their functions.
35 class InstrProfCorrelator {
36 public:
37   /// Indicate if we should use the debug info or profile metadata sections to
38   /// correlate.
39   enum ProfCorrelatorKind { NONE, DEBUG_INFO, BINARY };
40 
41   LLVM_ABI static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
42   get(StringRef Filename, ProfCorrelatorKind FileKind,
43       const object::BuildIDFetcher *BIDFetcher = nullptr,
44       const ArrayRef<llvm::object::BuildID> BIs = {});
45 
46   /// Construct a ProfileData vector used to correlate raw instrumentation data
47   /// to their functions.
48   /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
49   virtual Error correlateProfileData(int MaxWarnings) = 0;
50 
51   /// Process debug info and dump the correlation data.
52   /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
53   virtual Error dumpYaml(int MaxWarnings, raw_ostream &OS) = 0;
54 
55   /// Return the number of ProfileData elements.
56   LLVM_ABI std::optional<size_t> getDataSize() const;
57 
58   /// Return a pointer to the names string that this class constructs.
getNamesPointer()59   const char *getNamesPointer() const { return Names.c_str(); }
60 
61   /// Return the number of bytes in the names string.
getNamesSize()62   size_t getNamesSize() const { return Names.size(); }
63 
64   /// Return the size of the counters section in bytes.
getCountersSectionSize()65   uint64_t getCountersSectionSize() const {
66     return Ctx->CountersSectionEnd - Ctx->CountersSectionStart;
67   }
68 
69   LLVM_ABI static const char *FunctionNameAttributeName;
70   LLVM_ABI static const char *CFGHashAttributeName;
71   LLVM_ABI static const char *NumCountersAttributeName;
72 
73   enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit };
getKind()74   InstrProfCorrelatorKind getKind() const { return Kind; }
75   virtual ~InstrProfCorrelator() = default;
76 
77 protected:
78   struct Context {
79     LLVM_ABI static llvm::Expected<std::unique_ptr<Context>>
80     get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj,
81         ProfCorrelatorKind FileKind);
82     std::unique_ptr<MemoryBuffer> Buffer;
83     /// The address range of the __llvm_prf_cnts section.
84     uint64_t CountersSectionStart;
85     uint64_t CountersSectionEnd;
86     /// The pointer points to start/end of profile data/name sections if
87     /// FileKind is Binary.
88     const char *DataStart;
89     const char *DataEnd;
90     const char *NameStart;
91     size_t NameSize;
92     /// True if target and host have different endian orders.
93     bool ShouldSwapBytes;
94   };
95   const std::unique_ptr<Context> Ctx;
96 
InstrProfCorrelator(InstrProfCorrelatorKind K,std::unique_ptr<Context> Ctx)97   InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx)
98       : Ctx(std::move(Ctx)), Kind(K) {}
99 
100   std::string Names;
101   std::vector<std::string> NamesVec;
102 
103   struct Probe {
104     std::string FunctionName;
105     std::optional<std::string> LinkageName;
106     yaml::Hex64 CFGHash;
107     yaml::Hex64 CounterOffset;
108     uint32_t NumCounters;
109     std::optional<std::string> FilePath;
110     std::optional<int> LineNumber;
111   };
112 
113   struct CorrelationData {
114     std::vector<Probe> Probes;
115   };
116 
117   friend struct yaml::MappingTraits<Probe>;
118   friend struct yaml::SequenceElementTraits<Probe>;
119   friend struct yaml::MappingTraits<CorrelationData>;
120 
121 private:
122   static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
123   get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind);
124 
125   const InstrProfCorrelatorKind Kind;
126 };
127 
128 /// InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template
129 /// pointer type so that the ProfileData vector can be materialized.
130 template <class IntPtrT>
131 class InstrProfCorrelatorImpl : public InstrProfCorrelator {
132 public:
133   InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx);
134   static bool classof(const InstrProfCorrelator *C);
135 
136   /// Return a pointer to the underlying ProfileData vector that this class
137   /// constructs.
138   const RawInstrProf::ProfileData<IntPtrT> *getDataPointer() const {
139     return Data.empty() ? nullptr : Data.data();
140   }
141 
142   /// Return the number of ProfileData elements.
143   size_t getDataSize() const { return Data.size(); }
144 
145   static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
146   get(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
147       const object::ObjectFile &Obj, ProfCorrelatorKind FileKind);
148 
149 protected:
150   std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
151 
152   Error correlateProfileData(int MaxWarnings) override;
153   virtual void correlateProfileDataImpl(
154       int MaxWarnings,
155       InstrProfCorrelator::CorrelationData *Data = nullptr) = 0;
156 
157   virtual Error correlateProfileNameImpl() = 0;
158 
159   Error dumpYaml(int MaxWarnings, raw_ostream &OS) override;
160 
161   void addDataProbe(uint64_t FunctionName, uint64_t CFGHash,
162                     IntPtrT CounterOffset, IntPtrT FunctionPtr,
163                     uint32_t NumCounters);
164 
165   // Byte-swap the value if necessary.
166   template <class T> T maybeSwap(T Value) const {
167     return Ctx->ShouldSwapBytes ? llvm::byteswap(Value) : Value;
168   }
169 
170 private:
171   InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind,
172                           std::unique_ptr<InstrProfCorrelator::Context> Ctx)
173       : InstrProfCorrelator(Kind, std::move(Ctx)){};
174   llvm::DenseSet<IntPtrT> CounterOffsets;
175 };
176 
177 /// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes
178 /// DWARF debug info as input to correlate profiles.
179 template <class IntPtrT>
180 class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
181 public:
182   DwarfInstrProfCorrelator(std::unique_ptr<DWARFContext> DICtx,
183                            std::unique_ptr<InstrProfCorrelator::Context> Ctx)
184       : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)),
185         DICtx(std::move(DICtx)) {}
186 
187 private:
188   std::unique_ptr<DWARFContext> DICtx;
189 
190   /// Return the address of the object that the provided DIE symbolizes.
191   std::optional<uint64_t> getLocation(const DWARFDie &Die) const;
192 
193   /// Returns true if the provided DIE symbolizes an instrumentation probe
194   /// symbol.
195   static bool isDIEOfProbe(const DWARFDie &Die);
196 
197   /// Iterate over DWARF DIEs to find those that symbolize instrumentation
198   /// probes and construct the ProfileData vector and Names string.
199   ///
200   /// Here is some example DWARF for an instrumentation probe we are looking
201   /// for:
202   /// \code
203   ///   DW_TAG_subprogram
204   ///   DW_AT_low_pc	(0x0000000000000000)
205   ///   DW_AT_high_pc	(0x0000000000000014)
206   ///   DW_AT_name	("foo")
207   ///     DW_TAG_variable
208   ///       DW_AT_name	("__profc_foo")
209   ///       DW_AT_location	(DW_OP_addr 0x0)
210   ///       DW_TAG_LLVM_annotation
211   ///         DW_AT_name	("Function Name")
212   ///         DW_AT_const_value	("foo")
213   ///       DW_TAG_LLVM_annotation
214   ///         DW_AT_name	("CFG Hash")
215   ///         DW_AT_const_value	(12345678)
216   ///       DW_TAG_LLVM_annotation
217   ///         DW_AT_name	("Num Counters")
218   ///         DW_AT_const_value	(2)
219   ///       NULL
220   ///     NULL
221   /// \endcode
222   /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
223   /// \param Data if provided, populate with the correlation data found
224   void correlateProfileDataImpl(
225       int MaxWarnings,
226       InstrProfCorrelator::CorrelationData *Data = nullptr) override;
227 
228   Error correlateProfileNameImpl() override;
229 };
230 
231 /// BinaryInstrProfCorrelator - A child of InstrProfCorrelatorImpl that
232 /// takes an object file as input to correlate profiles.
233 template <class IntPtrT>
234 class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
235 public:
236   BinaryInstrProfCorrelator(std::unique_ptr<InstrProfCorrelator::Context> Ctx)
237       : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)) {}
238 
239   /// Return a pointer to the names string that this class constructs.
240   const char *getNamesPointer() const { return this->Ctx.NameStart; }
241 
242   /// Return the number of bytes in the names string.
243   size_t getNamesSize() const { return this->Ctx.NameSize; }
244 
245 private:
246   void correlateProfileDataImpl(
247       int MaxWarnings,
248       InstrProfCorrelator::CorrelationData *Data = nullptr) override;
249 
250   Error correlateProfileNameImpl() override;
251 };
252 
253 } // end namespace llvm
254 
255 #endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
256