Fix build after r255319.
[oota-llvm.git] / include / llvm / ProfileData / InstrProfReader.h
1 //=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains support for reading profiling data for instrumentation
11 // based PGO and coverage.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
16 #define LLVM_PROFILEDATA_INSTRPROFREADER_H
17
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ProfileData/InstrProf.h"
21 #include "llvm/Support/EndianStream.h"
22 #include "llvm/Support/ErrorOr.h"
23 #include "llvm/Support/LineIterator.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/OnDiskHashTable.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <iterator>
28
29 namespace llvm {
30
31 class InstrProfReader;
32
33 /// A file format agnostic iterator over profiling data.
34 class InstrProfIterator : public std::iterator<std::input_iterator_tag,
35                                                InstrProfRecord> {
36   InstrProfReader *Reader;
37   InstrProfRecord Record;
38
39   void Increment();
40 public:
41   InstrProfIterator() : Reader(nullptr) {}
42   InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
43
44   InstrProfIterator &operator++() { Increment(); return *this; }
45   bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
46   bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
47   InstrProfRecord &operator*() { return Record; }
48   InstrProfRecord *operator->() { return &Record; }
49 };
50
51 /// Base class and interface for reading profiling data of any known instrprof
52 /// format. Provides an iterator over InstrProfRecords.
53 class InstrProfReader {
54   std::error_code LastError;
55
56 public:
57   InstrProfReader() : LastError(instrprof_error::success) {}
58   virtual ~InstrProfReader() {}
59
60   /// Read the header.  Required before reading first record.
61   virtual std::error_code readHeader() = 0;
62   /// Read a single record.
63   virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0;
64   /// Iterator over profile data.
65   InstrProfIterator begin() { return InstrProfIterator(this); }
66   InstrProfIterator end() { return InstrProfIterator(); }
67
68  protected:
69   /// Set the current std::error_code and return same.
70   std::error_code error(std::error_code EC) {
71     LastError = EC;
72     return EC;
73   }
74
75   /// Clear the current error code and return a successful one.
76   std::error_code success() { return error(instrprof_error::success); }
77
78 public:
79   /// Return true if the reader has finished reading the profile data.
80   bool isEOF() { return LastError == instrprof_error::eof; }
81   /// Return true if the reader encountered an error reading profiling data.
82   bool hasError() { return LastError && !isEOF(); }
83   /// Get the current error code.
84   std::error_code getError() { return LastError; }
85
86   /// Factory method to create an appropriately typed reader for the given
87   /// instrprof file.
88   static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path);
89
90   static ErrorOr<std::unique_ptr<InstrProfReader>>
91   create(std::unique_ptr<MemoryBuffer> Buffer);
92 };
93
94 /// Reader for the simple text based instrprof format.
95 ///
96 /// This format is a simple text format that's suitable for test data. Records
97 /// are separated by one or more blank lines, and record fields are separated by
98 /// new lines.
99 ///
100 /// Each record consists of a function name, a function hash, a number of
101 /// counters, and then each counter value, in that order.
102 class TextInstrProfReader : public InstrProfReader {
103 private:
104   /// The profile data file contents.
105   std::unique_ptr<MemoryBuffer> DataBuffer;
106   /// Iterator over the profile data.
107   line_iterator Line;
108
109   TextInstrProfReader(const TextInstrProfReader &) = delete;
110   TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
111 public:
112   TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
113       : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
114
115   /// Return true if the given buffer is in text instrprof format.
116   static bool hasFormat(const MemoryBuffer &Buffer);
117
118   /// Read the header.
119   std::error_code readHeader() override { return success(); }
120   /// Read a single record.
121   std::error_code readNextRecord(InstrProfRecord &Record) override;
122 };
123
124 /// Reader for the raw instrprof binary format from runtime.
125 ///
126 /// This format is a raw memory dump of the instrumentation-baed profiling data
127 /// from the runtime.  It has no index.
128 ///
129 /// Templated on the unsigned type whose size matches pointers on the platform
130 /// that wrote the profile.
131 template <class IntPtrT>
132 class RawInstrProfReader : public InstrProfReader {
133 private:
134   /// The profile data file contents.
135   std::unique_ptr<MemoryBuffer> DataBuffer;
136   bool ShouldSwapBytes;
137   uint64_t CountersDelta;
138   uint64_t NamesDelta;
139   uint64_t ValueDataDelta;
140   const RawInstrProf::ProfileData<IntPtrT> *Data;
141   const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
142   const uint64_t *CountersStart;
143   const char *NamesStart;
144   const uint8_t *ValueDataStart;
145   const char *ProfileEnd;
146   uint32_t ValueKindLast;
147
148   // String table for holding a unique copy of all the strings in the profile.
149   InstrProfStringTable StringTable;
150   InstrProfRecord::ValueMapType FunctionPtrToNameMap;
151
152   RawInstrProfReader(const RawInstrProfReader &) = delete;
153   RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
154 public:
155   RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
156       : DataBuffer(std::move(DataBuffer)) { }
157
158   static bool hasFormat(const MemoryBuffer &DataBuffer);
159   std::error_code readHeader() override;
160   std::error_code readNextRecord(InstrProfRecord &Record) override;
161
162 private:
163   std::error_code readNextHeader(const char *CurrentPos);
164   std::error_code readHeader(const RawInstrProf::Header &Header);
165   template <class IntT> IntT swap(IntT Int) const {
166     return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
167   }
168   support::endianness getDataEndianness() const {
169     support::endianness HostEndian = getHostEndianness();
170     if (!ShouldSwapBytes)
171       return HostEndian;
172     if (HostEndian == support::little)
173       return support::big;
174     else
175       return support::little;
176   }
177
178   inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
179     return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
180   }
181   std::error_code readName(InstrProfRecord &Record);
182   std::error_code readFuncHash(InstrProfRecord &Record);
183   std::error_code readRawCounts(InstrProfRecord &Record);
184   std::error_code readValueProfilingData(InstrProfRecord &Record);
185   bool atEnd() const { return Data == DataEnd; }
186   void advanceData() { Data++; }
187
188   const uint64_t *getCounter(IntPtrT CounterPtr) const {
189     ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
190     return CountersStart + Offset;
191   }
192   const char *getName(IntPtrT NamePtr) const {
193     ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char);
194     return NamesStart + Offset;
195   }
196   const uint8_t *getValueDataCounts(IntPtrT ValueCountsPtr) const {
197     ptrdiff_t Offset =
198         (swap(ValueCountsPtr) - ValueDataDelta) / sizeof(uint8_t);
199     return ValueDataStart + Offset;
200   }
201   // This accepts an already byte-swapped ValueDataPtr argument.
202   const InstrProfValueData *getValueData(IntPtrT ValueDataPtr) const {
203     ptrdiff_t Offset = (ValueDataPtr - ValueDataDelta) / sizeof(uint8_t);
204     return reinterpret_cast<const InstrProfValueData *>(ValueDataStart +
205                                                         Offset);
206   }
207 };
208
209 typedef RawInstrProfReader<uint32_t> RawInstrProfReader32;
210 typedef RawInstrProfReader<uint64_t> RawInstrProfReader64;
211
212 namespace IndexedInstrProf {
213 enum class HashT : uint32_t;
214 }
215
216 /// Trait for lookups into the on-disk hash table for the binary instrprof
217 /// format.
218 class InstrProfLookupTrait {
219   std::vector<InstrProfRecord> DataBuffer;
220   IndexedInstrProf::HashT HashType;
221   unsigned FormatVersion;
222   // Endianness of the input value profile data.
223   // It should be LE by default, but can be changed
224   // for testing purpose.
225   support::endianness ValueProfDataEndianness;
226   std::vector<std::pair<uint64_t, const char *>> HashKeys;
227
228 public:
229   InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
230       : HashType(HashType), FormatVersion(FormatVersion),
231         ValueProfDataEndianness(support::little) {}
232
233   typedef ArrayRef<InstrProfRecord> data_type;
234
235   typedef StringRef internal_key_type;
236   typedef StringRef external_key_type;
237   typedef uint64_t hash_value_type;
238   typedef uint64_t offset_type;
239
240   static bool EqualKey(StringRef A, StringRef B) { return A == B; }
241   static StringRef GetInternalKey(StringRef K) { return K; }
242   static StringRef GetExternalKey(StringRef K) { return K; }
243
244   hash_value_type ComputeHash(StringRef K);
245
246   void setHashKeys(std::vector<std::pair<uint64_t, const char *>> HashKeys) {
247     this->HashKeys = std::move(HashKeys);
248   }
249   static std::pair<offset_type, offset_type>
250   ReadKeyDataLength(const unsigned char *&D) {
251     using namespace support;
252     offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
253     offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
254     return std::make_pair(KeyLen, DataLen);
255   }
256
257   StringRef ReadKey(const unsigned char *D, offset_type N) {
258     return StringRef((const char *)D, N);
259   }
260
261   bool readValueProfilingData(const unsigned char *&D,
262                               const unsigned char *const End);
263   data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
264
265   // Used for testing purpose only.
266   void setValueProfDataEndianness(support::endianness Endianness) {
267     ValueProfDataEndianness = Endianness;
268   }
269 };
270
271 struct InstrProfReaderIndexBase {
272   // Read all the profile records with the same key pointed to the current
273   // iterator.
274   virtual std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
275   // Read all the profile records with the key equal to FuncName
276   virtual std::error_code getRecords(StringRef FuncName,
277                                      ArrayRef<InstrProfRecord> &Data) = 0;
278   virtual void advanceToNextKey() = 0;
279   virtual bool atEnd() const = 0;
280   virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
281   virtual ~InstrProfReaderIndexBase() {}
282   virtual uint64_t getVersion() const = 0;
283 };
284
285 typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait>
286     OnDiskHashTableImplV3;
287
288 template <typename HashTableImpl>
289 class InstrProfReaderIndex : public InstrProfReaderIndexBase {
290
291 private:
292   std::unique_ptr<HashTableImpl> HashTable;
293   typename HashTableImpl::data_iterator RecordIterator;
294   uint64_t FormatVersion;
295
296   // String table for holding a unique copy of all the strings in the profile.
297   InstrProfStringTable StringTable;
298
299 public:
300   InstrProfReaderIndex(const unsigned char *Buckets,
301                        const unsigned char *const Payload,
302                        const unsigned char *const Base,
303                        IndexedInstrProf::HashT HashType, uint64_t Version);
304
305   std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) override;
306   std::error_code getRecords(StringRef FuncName,
307                              ArrayRef<InstrProfRecord> &Data) override;
308   void advanceToNextKey() override { RecordIterator++; }
309   bool atEnd() const override {
310     return RecordIterator == HashTable->data_end();
311   }
312   void setValueProfDataEndianness(support::endianness Endianness) override {
313     HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
314   }
315   ~InstrProfReaderIndex() override {}
316   uint64_t getVersion() const override { return FormatVersion; }
317 };
318
319 /// Reader for the indexed binary instrprof format.
320 class IndexedInstrProfReader : public InstrProfReader {
321 private:
322   /// The profile data file contents.
323   std::unique_ptr<MemoryBuffer> DataBuffer;
324   /// The index into the profile data.
325   std::unique_ptr<InstrProfReaderIndexBase> Index;
326   /// The maximal execution count among all functions.
327   uint64_t MaxFunctionCount;
328
329   IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
330   IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
331
332 public:
333   uint64_t getVersion() const { return Index->getVersion(); }
334   IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
335       : DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
336
337   /// Return true if the given buffer is in an indexed instrprof format.
338   static bool hasFormat(const MemoryBuffer &DataBuffer);
339
340   /// Read the file header.
341   std::error_code readHeader() override;
342   /// Read a single record.
343   std::error_code readNextRecord(InstrProfRecord &Record) override;
344
345   /// Return the pointer to InstrProfRecord associated with FuncName
346   /// and FuncHash
347   ErrorOr<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
348                                               uint64_t FuncHash);
349
350   /// Fill Counts with the profile data for the given function name.
351   std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
352                                     std::vector<uint64_t> &Counts);
353
354   /// Return the maximum of all known function counts.
355   uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
356
357   /// Factory method to create an indexed reader.
358   static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
359   create(std::string Path);
360
361   static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
362   create(std::unique_ptr<MemoryBuffer> Buffer);
363
364   // Used for testing purpose only.
365   void setValueProfDataEndianness(support::endianness Endianness) {
366     Index->setValueProfDataEndianness(Endianness);
367   }
368 };
369
370 } // end namespace llvm
371
372 #endif