xref: /aosp_15_r20/external/llvm/include/llvm/ProfileData/InstrProfReader.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains support for reading profiling data for instrumentation
11*9880d681SAndroid Build Coastguard Worker // based PGO and coverage.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
16*9880d681SAndroid Build Coastguard Worker #define LLVM_PROFILEDATA_INSTRPROFREADER_H
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ProfileData/InstrProf.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LineIterator.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/OnDiskHashTable.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
26*9880d681SAndroid Build Coastguard Worker #include <iterator>
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker namespace llvm {
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker class InstrProfReader;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker /// A file format agnostic iterator over profiling data.
33*9880d681SAndroid Build Coastguard Worker class InstrProfIterator : public std::iterator<std::input_iterator_tag,
34*9880d681SAndroid Build Coastguard Worker                                                InstrProfRecord> {
35*9880d681SAndroid Build Coastguard Worker   InstrProfReader *Reader;
36*9880d681SAndroid Build Coastguard Worker   InstrProfRecord Record;
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   void Increment();
39*9880d681SAndroid Build Coastguard Worker public:
InstrProfIterator()40*9880d681SAndroid Build Coastguard Worker   InstrProfIterator() : Reader(nullptr) {}
InstrProfIterator(InstrProfReader * Reader)41*9880d681SAndroid Build Coastguard Worker   InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   InstrProfIterator &operator++() { Increment(); return *this; }
44*9880d681SAndroid Build Coastguard Worker   bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
45*9880d681SAndroid Build Coastguard Worker   bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
46*9880d681SAndroid Build Coastguard Worker   InstrProfRecord &operator*() { return Record; }
47*9880d681SAndroid Build Coastguard Worker   InstrProfRecord *operator->() { return &Record; }
48*9880d681SAndroid Build Coastguard Worker };
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker /// Base class and interface for reading profiling data of any known instrprof
51*9880d681SAndroid Build Coastguard Worker /// format. Provides an iterator over InstrProfRecords.
52*9880d681SAndroid Build Coastguard Worker class InstrProfReader {
53*9880d681SAndroid Build Coastguard Worker   instrprof_error LastError;
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker public:
InstrProfReader()56*9880d681SAndroid Build Coastguard Worker   InstrProfReader() : LastError(instrprof_error::success), Symtab() {}
~InstrProfReader()57*9880d681SAndroid Build Coastguard Worker   virtual ~InstrProfReader() {}
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   /// Read the header.  Required before reading first record.
60*9880d681SAndroid Build Coastguard Worker   virtual Error readHeader() = 0;
61*9880d681SAndroid Build Coastguard Worker   /// Read a single record.
62*9880d681SAndroid Build Coastguard Worker   virtual Error readNextRecord(InstrProfRecord &Record) = 0;
63*9880d681SAndroid Build Coastguard Worker   /// Iterator over profile data.
begin()64*9880d681SAndroid Build Coastguard Worker   InstrProfIterator begin() { return InstrProfIterator(this); }
end()65*9880d681SAndroid Build Coastguard Worker   InstrProfIterator end() { return InstrProfIterator(); }
66*9880d681SAndroid Build Coastguard Worker   virtual bool isIRLevelProfile() const = 0;
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   /// Return the PGO symtab. There are three different readers:
69*9880d681SAndroid Build Coastguard Worker   /// Raw, Text, and Indexed profile readers. The first two types
70*9880d681SAndroid Build Coastguard Worker   /// of readers are used only by llvm-profdata tool, while the indexed
71*9880d681SAndroid Build Coastguard Worker   /// profile reader is also used by llvm-cov tool and the compiler (
72*9880d681SAndroid Build Coastguard Worker   /// backend or frontend). Since creating PGO symtab can create
73*9880d681SAndroid Build Coastguard Worker   /// significant runtime and memory overhead (as it touches data
74*9880d681SAndroid Build Coastguard Worker   /// for the whole program), InstrProfSymtab for the indexed profile
75*9880d681SAndroid Build Coastguard Worker   /// reader should be created on demand and it is recommended to be
76*9880d681SAndroid Build Coastguard Worker   /// only used for dumping purpose with llvm-proftool, not with the
77*9880d681SAndroid Build Coastguard Worker   /// compiler.
78*9880d681SAndroid Build Coastguard Worker   virtual InstrProfSymtab &getSymtab() = 0;
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker protected:
81*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<InstrProfSymtab> Symtab;
82*9880d681SAndroid Build Coastguard Worker   /// Set the current error and return same.
error(instrprof_error Err)83*9880d681SAndroid Build Coastguard Worker   Error error(instrprof_error Err) {
84*9880d681SAndroid Build Coastguard Worker     LastError = Err;
85*9880d681SAndroid Build Coastguard Worker     if (Err == instrprof_error::success)
86*9880d681SAndroid Build Coastguard Worker       return Error::success();
87*9880d681SAndroid Build Coastguard Worker     return make_error<InstrProfError>(Err);
88*9880d681SAndroid Build Coastguard Worker   }
error(Error E)89*9880d681SAndroid Build Coastguard Worker   Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   /// Clear the current error and return a successful one.
success()92*9880d681SAndroid Build Coastguard Worker   Error success() { return error(instrprof_error::success); }
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker public:
95*9880d681SAndroid Build Coastguard Worker   /// Return true if the reader has finished reading the profile data.
isEOF()96*9880d681SAndroid Build Coastguard Worker   bool isEOF() { return LastError == instrprof_error::eof; }
97*9880d681SAndroid Build Coastguard Worker   /// Return true if the reader encountered an error reading profiling data.
hasError()98*9880d681SAndroid Build Coastguard Worker   bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
99*9880d681SAndroid Build Coastguard Worker   /// Get the current error.
getError()100*9880d681SAndroid Build Coastguard Worker   Error getError() {
101*9880d681SAndroid Build Coastguard Worker     if (hasError())
102*9880d681SAndroid Build Coastguard Worker       return make_error<InstrProfError>(LastError);
103*9880d681SAndroid Build Coastguard Worker     return Error::success();
104*9880d681SAndroid Build Coastguard Worker   }
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker   /// Factory method to create an appropriately typed reader for the given
107*9880d681SAndroid Build Coastguard Worker   /// instrprof file.
108*9880d681SAndroid Build Coastguard Worker   static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   static Expected<std::unique_ptr<InstrProfReader>>
111*9880d681SAndroid Build Coastguard Worker   create(std::unique_ptr<MemoryBuffer> Buffer);
112*9880d681SAndroid Build Coastguard Worker };
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker /// Reader for the simple text based instrprof format.
115*9880d681SAndroid Build Coastguard Worker ///
116*9880d681SAndroid Build Coastguard Worker /// This format is a simple text format that's suitable for test data. Records
117*9880d681SAndroid Build Coastguard Worker /// are separated by one or more blank lines, and record fields are separated by
118*9880d681SAndroid Build Coastguard Worker /// new lines.
119*9880d681SAndroid Build Coastguard Worker ///
120*9880d681SAndroid Build Coastguard Worker /// Each record consists of a function name, a function hash, a number of
121*9880d681SAndroid Build Coastguard Worker /// counters, and then each counter value, in that order.
122*9880d681SAndroid Build Coastguard Worker class TextInstrProfReader : public InstrProfReader {
123*9880d681SAndroid Build Coastguard Worker private:
124*9880d681SAndroid Build Coastguard Worker   /// The profile data file contents.
125*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> DataBuffer;
126*9880d681SAndroid Build Coastguard Worker   /// Iterator over the profile data.
127*9880d681SAndroid Build Coastguard Worker   line_iterator Line;
128*9880d681SAndroid Build Coastguard Worker   bool IsIRLevelProfile;
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker   TextInstrProfReader(const TextInstrProfReader &) = delete;
131*9880d681SAndroid Build Coastguard Worker   TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
132*9880d681SAndroid Build Coastguard Worker   Error readValueProfileData(InstrProfRecord &Record);
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)135*9880d681SAndroid Build Coastguard Worker   TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
136*9880d681SAndroid Build Coastguard Worker       : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'),
137*9880d681SAndroid Build Coastguard Worker         IsIRLevelProfile(false) {}
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker   /// Return true if the given buffer is in text instrprof format.
140*9880d681SAndroid Build Coastguard Worker   static bool hasFormat(const MemoryBuffer &Buffer);
141*9880d681SAndroid Build Coastguard Worker 
isIRLevelProfile()142*9880d681SAndroid Build Coastguard Worker   bool isIRLevelProfile() const override { return IsIRLevelProfile; }
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker   /// Read the header.
145*9880d681SAndroid Build Coastguard Worker   Error readHeader() override;
146*9880d681SAndroid Build Coastguard Worker   /// Read a single record.
147*9880d681SAndroid Build Coastguard Worker   Error readNextRecord(InstrProfRecord &Record) override;
148*9880d681SAndroid Build Coastguard Worker 
getSymtab()149*9880d681SAndroid Build Coastguard Worker   InstrProfSymtab &getSymtab() override {
150*9880d681SAndroid Build Coastguard Worker     assert(Symtab.get());
151*9880d681SAndroid Build Coastguard Worker     return *Symtab.get();
152*9880d681SAndroid Build Coastguard Worker   }
153*9880d681SAndroid Build Coastguard Worker };
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker /// Reader for the raw instrprof binary format from runtime.
156*9880d681SAndroid Build Coastguard Worker ///
157*9880d681SAndroid Build Coastguard Worker /// This format is a raw memory dump of the instrumentation-baed profiling data
158*9880d681SAndroid Build Coastguard Worker /// from the runtime.  It has no index.
159*9880d681SAndroid Build Coastguard Worker ///
160*9880d681SAndroid Build Coastguard Worker /// Templated on the unsigned type whose size matches pointers on the platform
161*9880d681SAndroid Build Coastguard Worker /// that wrote the profile.
162*9880d681SAndroid Build Coastguard Worker template <class IntPtrT>
163*9880d681SAndroid Build Coastguard Worker class RawInstrProfReader : public InstrProfReader {
164*9880d681SAndroid Build Coastguard Worker private:
165*9880d681SAndroid Build Coastguard Worker   /// The profile data file contents.
166*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> DataBuffer;
167*9880d681SAndroid Build Coastguard Worker   bool ShouldSwapBytes;
168*9880d681SAndroid Build Coastguard Worker   // The value of the version field of the raw profile data header. The lower 56
169*9880d681SAndroid Build Coastguard Worker   // bits specifies the format version and the most significant 8 bits specify
170*9880d681SAndroid Build Coastguard Worker   // the variant types of the profile.
171*9880d681SAndroid Build Coastguard Worker   uint64_t Version;
172*9880d681SAndroid Build Coastguard Worker   uint64_t CountersDelta;
173*9880d681SAndroid Build Coastguard Worker   uint64_t NamesDelta;
174*9880d681SAndroid Build Coastguard Worker   const RawInstrProf::ProfileData<IntPtrT> *Data;
175*9880d681SAndroid Build Coastguard Worker   const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
176*9880d681SAndroid Build Coastguard Worker   const uint64_t *CountersStart;
177*9880d681SAndroid Build Coastguard Worker   const char *NamesStart;
178*9880d681SAndroid Build Coastguard Worker   uint64_t NamesSize;
179*9880d681SAndroid Build Coastguard Worker   // After value profile is all read, this pointer points to
180*9880d681SAndroid Build Coastguard Worker   // the header of next profile data (if exists)
181*9880d681SAndroid Build Coastguard Worker   const uint8_t *ValueDataStart;
182*9880d681SAndroid Build Coastguard Worker   uint32_t ValueKindLast;
183*9880d681SAndroid Build Coastguard Worker   uint32_t CurValueDataSize;
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker   InstrProfRecord::ValueMapType FunctionPtrToNameMap;
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker   RawInstrProfReader(const RawInstrProfReader &) = delete;
188*9880d681SAndroid Build Coastguard Worker   RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
189*9880d681SAndroid Build Coastguard Worker public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)190*9880d681SAndroid Build Coastguard Worker   RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
191*9880d681SAndroid Build Coastguard Worker       : DataBuffer(std::move(DataBuffer)) { }
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker   static bool hasFormat(const MemoryBuffer &DataBuffer);
194*9880d681SAndroid Build Coastguard Worker   Error readHeader() override;
195*9880d681SAndroid Build Coastguard Worker   Error readNextRecord(InstrProfRecord &Record) override;
isIRLevelProfile()196*9880d681SAndroid Build Coastguard Worker   bool isIRLevelProfile() const override {
197*9880d681SAndroid Build Coastguard Worker     return (Version & VARIANT_MASK_IR_PROF) != 0;
198*9880d681SAndroid Build Coastguard Worker   }
199*9880d681SAndroid Build Coastguard Worker 
getSymtab()200*9880d681SAndroid Build Coastguard Worker   InstrProfSymtab &getSymtab() override {
201*9880d681SAndroid Build Coastguard Worker     assert(Symtab.get());
202*9880d681SAndroid Build Coastguard Worker     return *Symtab.get();
203*9880d681SAndroid Build Coastguard Worker   }
204*9880d681SAndroid Build Coastguard Worker 
205*9880d681SAndroid Build Coastguard Worker private:
206*9880d681SAndroid Build Coastguard Worker   Error createSymtab(InstrProfSymtab &Symtab);
207*9880d681SAndroid Build Coastguard Worker   Error readNextHeader(const char *CurrentPos);
208*9880d681SAndroid Build Coastguard Worker   Error readHeader(const RawInstrProf::Header &Header);
swap(IntT Int)209*9880d681SAndroid Build Coastguard Worker   template <class IntT> IntT swap(IntT Int) const {
210*9880d681SAndroid Build Coastguard Worker     return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
211*9880d681SAndroid Build Coastguard Worker   }
getDataEndianness()212*9880d681SAndroid Build Coastguard Worker   support::endianness getDataEndianness() const {
213*9880d681SAndroid Build Coastguard Worker     support::endianness HostEndian = getHostEndianness();
214*9880d681SAndroid Build Coastguard Worker     if (!ShouldSwapBytes)
215*9880d681SAndroid Build Coastguard Worker       return HostEndian;
216*9880d681SAndroid Build Coastguard Worker     if (HostEndian == support::little)
217*9880d681SAndroid Build Coastguard Worker       return support::big;
218*9880d681SAndroid Build Coastguard Worker     else
219*9880d681SAndroid Build Coastguard Worker       return support::little;
220*9880d681SAndroid Build Coastguard Worker   }
221*9880d681SAndroid Build Coastguard Worker 
getNumPaddingBytes(uint64_t SizeInBytes)222*9880d681SAndroid Build Coastguard Worker   inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
223*9880d681SAndroid Build Coastguard Worker     return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
224*9880d681SAndroid Build Coastguard Worker   }
225*9880d681SAndroid Build Coastguard Worker   Error readName(InstrProfRecord &Record);
226*9880d681SAndroid Build Coastguard Worker   Error readFuncHash(InstrProfRecord &Record);
227*9880d681SAndroid Build Coastguard Worker   Error readRawCounts(InstrProfRecord &Record);
228*9880d681SAndroid Build Coastguard Worker   Error readValueProfilingData(InstrProfRecord &Record);
atEnd()229*9880d681SAndroid Build Coastguard Worker   bool atEnd() const { return Data == DataEnd; }
advanceData()230*9880d681SAndroid Build Coastguard Worker   void advanceData() {
231*9880d681SAndroid Build Coastguard Worker     Data++;
232*9880d681SAndroid Build Coastguard Worker     ValueDataStart += CurValueDataSize;
233*9880d681SAndroid Build Coastguard Worker   }
getNextHeaderPos()234*9880d681SAndroid Build Coastguard Worker   const char *getNextHeaderPos() const {
235*9880d681SAndroid Build Coastguard Worker       assert(atEnd());
236*9880d681SAndroid Build Coastguard Worker       return (const char *)ValueDataStart;
237*9880d681SAndroid Build Coastguard Worker   }
238*9880d681SAndroid Build Coastguard Worker 
getCounter(IntPtrT CounterPtr)239*9880d681SAndroid Build Coastguard Worker   const uint64_t *getCounter(IntPtrT CounterPtr) const {
240*9880d681SAndroid Build Coastguard Worker     ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
241*9880d681SAndroid Build Coastguard Worker     return CountersStart + Offset;
242*9880d681SAndroid Build Coastguard Worker   }
getName(uint64_t NameRef)243*9880d681SAndroid Build Coastguard Worker   StringRef getName(uint64_t NameRef) const {
244*9880d681SAndroid Build Coastguard Worker     return Symtab->getFuncName(swap(NameRef));
245*9880d681SAndroid Build Coastguard Worker   }
246*9880d681SAndroid Build Coastguard Worker };
247*9880d681SAndroid Build Coastguard Worker 
248*9880d681SAndroid Build Coastguard Worker typedef RawInstrProfReader<uint32_t> RawInstrProfReader32;
249*9880d681SAndroid Build Coastguard Worker typedef RawInstrProfReader<uint64_t> RawInstrProfReader64;
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker namespace IndexedInstrProf {
252*9880d681SAndroid Build Coastguard Worker enum class HashT : uint32_t;
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker /// Trait for lookups into the on-disk hash table for the binary instrprof
256*9880d681SAndroid Build Coastguard Worker /// format.
257*9880d681SAndroid Build Coastguard Worker class InstrProfLookupTrait {
258*9880d681SAndroid Build Coastguard Worker   std::vector<InstrProfRecord> DataBuffer;
259*9880d681SAndroid Build Coastguard Worker   IndexedInstrProf::HashT HashType;
260*9880d681SAndroid Build Coastguard Worker   unsigned FormatVersion;
261*9880d681SAndroid Build Coastguard Worker   // Endianness of the input value profile data.
262*9880d681SAndroid Build Coastguard Worker   // It should be LE by default, but can be changed
263*9880d681SAndroid Build Coastguard Worker   // for testing purpose.
264*9880d681SAndroid Build Coastguard Worker   support::endianness ValueProfDataEndianness;
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker public:
InstrProfLookupTrait(IndexedInstrProf::HashT HashType,unsigned FormatVersion)267*9880d681SAndroid Build Coastguard Worker   InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
268*9880d681SAndroid Build Coastguard Worker       : HashType(HashType), FormatVersion(FormatVersion),
269*9880d681SAndroid Build Coastguard Worker         ValueProfDataEndianness(support::little) {}
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker   typedef ArrayRef<InstrProfRecord> data_type;
272*9880d681SAndroid Build Coastguard Worker 
273*9880d681SAndroid Build Coastguard Worker   typedef StringRef internal_key_type;
274*9880d681SAndroid Build Coastguard Worker   typedef StringRef external_key_type;
275*9880d681SAndroid Build Coastguard Worker   typedef uint64_t hash_value_type;
276*9880d681SAndroid Build Coastguard Worker   typedef uint64_t offset_type;
277*9880d681SAndroid Build Coastguard Worker 
EqualKey(StringRef A,StringRef B)278*9880d681SAndroid Build Coastguard Worker   static bool EqualKey(StringRef A, StringRef B) { return A == B; }
GetInternalKey(StringRef K)279*9880d681SAndroid Build Coastguard Worker   static StringRef GetInternalKey(StringRef K) { return K; }
GetExternalKey(StringRef K)280*9880d681SAndroid Build Coastguard Worker   static StringRef GetExternalKey(StringRef K) { return K; }
281*9880d681SAndroid Build Coastguard Worker 
282*9880d681SAndroid Build Coastguard Worker   hash_value_type ComputeHash(StringRef K);
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker   static std::pair<offset_type, offset_type>
ReadKeyDataLength(const unsigned char * & D)285*9880d681SAndroid Build Coastguard Worker   ReadKeyDataLength(const unsigned char *&D) {
286*9880d681SAndroid Build Coastguard Worker     using namespace support;
287*9880d681SAndroid Build Coastguard Worker     offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
288*9880d681SAndroid Build Coastguard Worker     offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
289*9880d681SAndroid Build Coastguard Worker     return std::make_pair(KeyLen, DataLen);
290*9880d681SAndroid Build Coastguard Worker   }
291*9880d681SAndroid Build Coastguard Worker 
ReadKey(const unsigned char * D,offset_type N)292*9880d681SAndroid Build Coastguard Worker   StringRef ReadKey(const unsigned char *D, offset_type N) {
293*9880d681SAndroid Build Coastguard Worker     return StringRef((const char *)D, N);
294*9880d681SAndroid Build Coastguard Worker   }
295*9880d681SAndroid Build Coastguard Worker 
296*9880d681SAndroid Build Coastguard Worker   bool readValueProfilingData(const unsigned char *&D,
297*9880d681SAndroid Build Coastguard Worker                               const unsigned char *const End);
298*9880d681SAndroid Build Coastguard Worker   data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   // Used for testing purpose only.
setValueProfDataEndianness(support::endianness Endianness)301*9880d681SAndroid Build Coastguard Worker   void setValueProfDataEndianness(support::endianness Endianness) {
302*9880d681SAndroid Build Coastguard Worker     ValueProfDataEndianness = Endianness;
303*9880d681SAndroid Build Coastguard Worker   }
304*9880d681SAndroid Build Coastguard Worker };
305*9880d681SAndroid Build Coastguard Worker 
306*9880d681SAndroid Build Coastguard Worker struct InstrProfReaderIndexBase {
307*9880d681SAndroid Build Coastguard Worker   // Read all the profile records with the same key pointed to the current
308*9880d681SAndroid Build Coastguard Worker   // iterator.
309*9880d681SAndroid Build Coastguard Worker   virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
310*9880d681SAndroid Build Coastguard Worker   // Read all the profile records with the key equal to FuncName
311*9880d681SAndroid Build Coastguard Worker   virtual Error getRecords(StringRef FuncName,
312*9880d681SAndroid Build Coastguard Worker                                      ArrayRef<InstrProfRecord> &Data) = 0;
313*9880d681SAndroid Build Coastguard Worker   virtual void advanceToNextKey() = 0;
314*9880d681SAndroid Build Coastguard Worker   virtual bool atEnd() const = 0;
315*9880d681SAndroid Build Coastguard Worker   virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
~InstrProfReaderIndexBaseInstrProfReaderIndexBase316*9880d681SAndroid Build Coastguard Worker   virtual ~InstrProfReaderIndexBase() {}
317*9880d681SAndroid Build Coastguard Worker   virtual uint64_t getVersion() const = 0;
318*9880d681SAndroid Build Coastguard Worker   virtual bool isIRLevelProfile() const = 0;
319*9880d681SAndroid Build Coastguard Worker   virtual void populateSymtab(InstrProfSymtab &) = 0;
320*9880d681SAndroid Build Coastguard Worker };
321*9880d681SAndroid Build Coastguard Worker 
322*9880d681SAndroid Build Coastguard Worker typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait>
323*9880d681SAndroid Build Coastguard Worker     OnDiskHashTableImplV3;
324*9880d681SAndroid Build Coastguard Worker 
325*9880d681SAndroid Build Coastguard Worker template <typename HashTableImpl>
326*9880d681SAndroid Build Coastguard Worker class InstrProfReaderIndex : public InstrProfReaderIndexBase {
327*9880d681SAndroid Build Coastguard Worker 
328*9880d681SAndroid Build Coastguard Worker private:
329*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<HashTableImpl> HashTable;
330*9880d681SAndroid Build Coastguard Worker   typename HashTableImpl::data_iterator RecordIterator;
331*9880d681SAndroid Build Coastguard Worker   uint64_t FormatVersion;
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker public:
334*9880d681SAndroid Build Coastguard Worker   InstrProfReaderIndex(const unsigned char *Buckets,
335*9880d681SAndroid Build Coastguard Worker                        const unsigned char *const Payload,
336*9880d681SAndroid Build Coastguard Worker                        const unsigned char *const Base,
337*9880d681SAndroid Build Coastguard Worker                        IndexedInstrProf::HashT HashType, uint64_t Version);
338*9880d681SAndroid Build Coastguard Worker 
339*9880d681SAndroid Build Coastguard Worker   Error getRecords(ArrayRef<InstrProfRecord> &Data) override;
340*9880d681SAndroid Build Coastguard Worker   Error getRecords(StringRef FuncName,
341*9880d681SAndroid Build Coastguard Worker                    ArrayRef<InstrProfRecord> &Data) override;
advanceToNextKey()342*9880d681SAndroid Build Coastguard Worker   void advanceToNextKey() override { RecordIterator++; }
atEnd()343*9880d681SAndroid Build Coastguard Worker   bool atEnd() const override {
344*9880d681SAndroid Build Coastguard Worker     return RecordIterator == HashTable->data_end();
345*9880d681SAndroid Build Coastguard Worker   }
setValueProfDataEndianness(support::endianness Endianness)346*9880d681SAndroid Build Coastguard Worker   void setValueProfDataEndianness(support::endianness Endianness) override {
347*9880d681SAndroid Build Coastguard Worker     HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
348*9880d681SAndroid Build Coastguard Worker   }
~InstrProfReaderIndex()349*9880d681SAndroid Build Coastguard Worker   ~InstrProfReaderIndex() override {}
getVersion()350*9880d681SAndroid Build Coastguard Worker   uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
isIRLevelProfile()351*9880d681SAndroid Build Coastguard Worker   bool isIRLevelProfile() const override {
352*9880d681SAndroid Build Coastguard Worker     return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
353*9880d681SAndroid Build Coastguard Worker   }
populateSymtab(InstrProfSymtab & Symtab)354*9880d681SAndroid Build Coastguard Worker   void populateSymtab(InstrProfSymtab &Symtab) override {
355*9880d681SAndroid Build Coastguard Worker     Symtab.create(HashTable->keys());
356*9880d681SAndroid Build Coastguard Worker   }
357*9880d681SAndroid Build Coastguard Worker };
358*9880d681SAndroid Build Coastguard Worker 
359*9880d681SAndroid Build Coastguard Worker /// Reader for the indexed binary instrprof format.
360*9880d681SAndroid Build Coastguard Worker class IndexedInstrProfReader : public InstrProfReader {
361*9880d681SAndroid Build Coastguard Worker private:
362*9880d681SAndroid Build Coastguard Worker   /// The profile data file contents.
363*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> DataBuffer;
364*9880d681SAndroid Build Coastguard Worker   /// The index into the profile data.
365*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<InstrProfReaderIndexBase> Index;
366*9880d681SAndroid Build Coastguard Worker   /// Profile summary data.
367*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<ProfileSummary> Summary;
368*9880d681SAndroid Build Coastguard Worker 
369*9880d681SAndroid Build Coastguard Worker   IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
370*9880d681SAndroid Build Coastguard Worker   IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker   // Read the profile summary. Return a pointer pointing to one byte past the
373*9880d681SAndroid Build Coastguard Worker   // end of the summary data if it exists or the input \c Cur.
374*9880d681SAndroid Build Coastguard Worker   const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
375*9880d681SAndroid Build Coastguard Worker                                    const unsigned char *Cur);
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker public:
378*9880d681SAndroid Build Coastguard Worker   /// Return the profile version.
getVersion()379*9880d681SAndroid Build Coastguard Worker   uint64_t getVersion() const { return Index->getVersion(); }
isIRLevelProfile()380*9880d681SAndroid Build Coastguard Worker   bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)381*9880d681SAndroid Build Coastguard Worker   IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
382*9880d681SAndroid Build Coastguard Worker       : DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
383*9880d681SAndroid Build Coastguard Worker 
384*9880d681SAndroid Build Coastguard Worker   /// Return true if the given buffer is in an indexed instrprof format.
385*9880d681SAndroid Build Coastguard Worker   static bool hasFormat(const MemoryBuffer &DataBuffer);
386*9880d681SAndroid Build Coastguard Worker 
387*9880d681SAndroid Build Coastguard Worker   /// Read the file header.
388*9880d681SAndroid Build Coastguard Worker   Error readHeader() override;
389*9880d681SAndroid Build Coastguard Worker   /// Read a single record.
390*9880d681SAndroid Build Coastguard Worker   Error readNextRecord(InstrProfRecord &Record) override;
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker   /// Return the pointer to InstrProfRecord associated with FuncName
393*9880d681SAndroid Build Coastguard Worker   /// and FuncHash
394*9880d681SAndroid Build Coastguard Worker   Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
395*9880d681SAndroid Build Coastguard Worker                                                uint64_t FuncHash);
396*9880d681SAndroid Build Coastguard Worker 
397*9880d681SAndroid Build Coastguard Worker   /// Fill Counts with the profile data for the given function name.
398*9880d681SAndroid Build Coastguard Worker   Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
399*9880d681SAndroid Build Coastguard Worker                           std::vector<uint64_t> &Counts);
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker   /// Return the maximum of all known function counts.
getMaximumFunctionCount()402*9880d681SAndroid Build Coastguard Worker   uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
403*9880d681SAndroid Build Coastguard Worker 
404*9880d681SAndroid Build Coastguard Worker   /// Factory method to create an indexed reader.
405*9880d681SAndroid Build Coastguard Worker   static Expected<std::unique_ptr<IndexedInstrProfReader>>
406*9880d681SAndroid Build Coastguard Worker   create(const Twine &Path);
407*9880d681SAndroid Build Coastguard Worker 
408*9880d681SAndroid Build Coastguard Worker   static Expected<std::unique_ptr<IndexedInstrProfReader>>
409*9880d681SAndroid Build Coastguard Worker   create(std::unique_ptr<MemoryBuffer> Buffer);
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker   // Used for testing purpose only.
setValueProfDataEndianness(support::endianness Endianness)412*9880d681SAndroid Build Coastguard Worker   void setValueProfDataEndianness(support::endianness Endianness) {
413*9880d681SAndroid Build Coastguard Worker     Index->setValueProfDataEndianness(Endianness);
414*9880d681SAndroid Build Coastguard Worker   }
415*9880d681SAndroid Build Coastguard Worker 
416*9880d681SAndroid Build Coastguard Worker   // See description in the base class. This interface is designed
417*9880d681SAndroid Build Coastguard Worker   // to be used by llvm-profdata (for dumping). Avoid using this when
418*9880d681SAndroid Build Coastguard Worker   // the client is the compiler.
419*9880d681SAndroid Build Coastguard Worker   InstrProfSymtab &getSymtab() override;
getSummary()420*9880d681SAndroid Build Coastguard Worker   ProfileSummary &getSummary() { return *(Summary.get()); }
421*9880d681SAndroid Build Coastguard Worker };
422*9880d681SAndroid Build Coastguard Worker 
423*9880d681SAndroid Build Coastguard Worker } // end namespace llvm
424*9880d681SAndroid Build Coastguard Worker 
425*9880d681SAndroid Build Coastguard Worker #endif
426