LLVM API Documentation

InstrProfReader.h
Go to the documentation of this file.
00001 //=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains support for reading profiling data for instrumentation
00011 // based PGO and coverage.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
00016 #define LLVM_PROFILEDATA_INSTRPROFREADER_H
00017 
00018 #include "llvm/ADT/ArrayRef.h"
00019 #include "llvm/ADT/StringExtras.h"
00020 #include "llvm/ProfileData/InstrProf.h"
00021 #include "llvm/Support/LineIterator.h"
00022 #include "llvm/Support/MemoryBuffer.h"
00023 #include "llvm/Support/EndianStream.h"
00024 #include "llvm/Support/OnDiskHashTable.h"
00025 
00026 #include <iterator>
00027 
00028 namespace llvm {
00029 
00030 class InstrProfReader;
00031 
00032 /// Profiling information for a single function.
00033 struct InstrProfRecord {
00034   InstrProfRecord() {}
00035   InstrProfRecord(StringRef Name, uint64_t Hash, ArrayRef<uint64_t> Counts)
00036       : Name(Name), Hash(Hash), Counts(Counts) {}
00037   StringRef Name;
00038   uint64_t Hash;
00039   ArrayRef<uint64_t> Counts;
00040 };
00041 
00042 /// A file format agnostic iterator over profiling data.
00043 class InstrProfIterator : public std::iterator<std::input_iterator_tag,
00044                                                InstrProfRecord> {
00045   InstrProfReader *Reader;
00046   InstrProfRecord Record;
00047 
00048   void Increment();
00049 public:
00050   InstrProfIterator() : Reader(nullptr) {}
00051   InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
00052 
00053   InstrProfIterator &operator++() { Increment(); return *this; }
00054   bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
00055   bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
00056   InstrProfRecord &operator*() { return Record; }
00057   InstrProfRecord *operator->() { return &Record; }
00058 };
00059 
00060 /// Base class and interface for reading profiling data of any known instrprof
00061 /// format. Provides an iterator over InstrProfRecords.
00062 class InstrProfReader {
00063   std::error_code LastError;
00064 
00065 public:
00066   InstrProfReader() : LastError(instrprof_error::success) {}
00067   virtual ~InstrProfReader() {}
00068 
00069   /// Read the header.  Required before reading first record.
00070   virtual std::error_code readHeader() = 0;
00071   /// Read a single record.
00072   virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0;
00073   /// Iterator over profile data.
00074   InstrProfIterator begin() { return InstrProfIterator(this); }
00075   InstrProfIterator end() { return InstrProfIterator(); }
00076 
00077 protected:
00078   /// Set the current std::error_code and return same.
00079   std::error_code error(std::error_code EC) {
00080     LastError = EC;
00081     return EC;
00082   }
00083 
00084   /// Clear the current error code and return a successful one.
00085   std::error_code success() { return error(instrprof_error::success); }
00086 
00087 public:
00088   /// Return true if the reader has finished reading the profile data.
00089   bool isEOF() { return LastError == instrprof_error::eof; }
00090   /// Return true if the reader encountered an error reading profiling data.
00091   bool hasError() { return LastError && !isEOF(); }
00092   /// Get the current error code.
00093   std::error_code getError() { return LastError; }
00094 
00095   /// Factory method to create an appropriately typed reader for the given
00096   /// instrprof file.
00097   static std::error_code create(std::string Path,
00098                                 std::unique_ptr<InstrProfReader> &Result);
00099 };
00100 
00101 /// Reader for the simple text based instrprof format.
00102 ///
00103 /// This format is a simple text format that's suitable for test data. Records
00104 /// are separated by one or more blank lines, and record fields are separated by
00105 /// new lines.
00106 ///
00107 /// Each record consists of a function name, a function hash, a number of
00108 /// counters, and then each counter value, in that order.
00109 class TextInstrProfReader : public InstrProfReader {
00110 private:
00111   /// The profile data file contents.
00112   std::unique_ptr<MemoryBuffer> DataBuffer;
00113   /// Iterator over the profile data.
00114   line_iterator Line;
00115   /// The current set of counter values.
00116   std::vector<uint64_t> Counts;
00117 
00118   TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION;
00119   TextInstrProfReader &operator=(const TextInstrProfReader &)
00120     LLVM_DELETED_FUNCTION;
00121 public:
00122   TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
00123       : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
00124 
00125   /// Read the header.
00126   std::error_code readHeader() override { return success(); }
00127   /// Read a single record.
00128   std::error_code readNextRecord(InstrProfRecord &Record) override;
00129 };
00130 
00131 /// Reader for the raw instrprof binary format from runtime.
00132 ///
00133 /// This format is a raw memory dump of the instrumentation-baed profiling data
00134 /// from the runtime.  It has no index.
00135 ///
00136 /// Templated on the unsigned type whose size matches pointers on the platform
00137 /// that wrote the profile.
00138 template <class IntPtrT>
00139 class RawInstrProfReader : public InstrProfReader {
00140 private:
00141   /// The profile data file contents.
00142   std::unique_ptr<MemoryBuffer> DataBuffer;
00143   /// The current set of counter values.
00144   std::vector<uint64_t> Counts;
00145   struct ProfileData {
00146     const uint32_t NameSize;
00147     const uint32_t NumCounters;
00148     const uint64_t FuncHash;
00149     const IntPtrT NamePtr;
00150     const IntPtrT CounterPtr;
00151   };
00152   struct RawHeader {
00153     const uint64_t Magic;
00154     const uint64_t Version;
00155     const uint64_t DataSize;
00156     const uint64_t CountersSize;
00157     const uint64_t NamesSize;
00158     const uint64_t CountersDelta;
00159     const uint64_t NamesDelta;
00160   };
00161 
00162   bool ShouldSwapBytes;
00163   uint64_t CountersDelta;
00164   uint64_t NamesDelta;
00165   const ProfileData *Data;
00166   const ProfileData *DataEnd;
00167   const uint64_t *CountersStart;
00168   const char *NamesStart;
00169   const char *ProfileEnd;
00170 
00171   RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION;
00172   RawInstrProfReader &operator=(const RawInstrProfReader &)
00173     LLVM_DELETED_FUNCTION;
00174 public:
00175   RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
00176       : DataBuffer(std::move(DataBuffer)) { }
00177 
00178   static bool hasFormat(const MemoryBuffer &DataBuffer);
00179   std::error_code readHeader() override;
00180   std::error_code readNextRecord(InstrProfRecord &Record) override;
00181 
00182 private:
00183   std::error_code readNextHeader(const char *CurrentPos);
00184   std::error_code readHeader(const RawHeader &Header);
00185   template <class IntT>
00186   IntT swap(IntT Int) const {
00187     return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
00188   }
00189   const uint64_t *getCounter(IntPtrT CounterPtr) const {
00190     ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
00191     return CountersStart + Offset;
00192   }
00193   const char *getName(IntPtrT NamePtr) const {
00194     ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char);
00195     return NamesStart + Offset;
00196   }
00197 };
00198 
00199 typedef RawInstrProfReader<uint32_t> RawInstrProfReader32;
00200 typedef RawInstrProfReader<uint64_t> RawInstrProfReader64;
00201 
00202 namespace IndexedInstrProf {
00203 enum class HashT : uint32_t;
00204 }
00205 
00206 /// Trait for lookups into the on-disk hash table for the binary instrprof
00207 /// format.
00208 class InstrProfLookupTrait {
00209   std::vector<uint64_t> DataBuffer;
00210   IndexedInstrProf::HashT HashType;
00211 public:
00212   InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {}
00213 
00214   struct data_type {
00215     data_type(StringRef Name, ArrayRef<uint64_t> Data)
00216         : Name(Name), Data(Data) {}
00217     StringRef Name;
00218     ArrayRef<uint64_t> Data;
00219   };
00220   typedef StringRef internal_key_type;
00221   typedef StringRef external_key_type;
00222   typedef uint64_t hash_value_type;
00223   typedef uint64_t offset_type;
00224 
00225   static bool EqualKey(StringRef A, StringRef B) { return A == B; }
00226   static StringRef GetInternalKey(StringRef K) { return K; }
00227 
00228   hash_value_type ComputeHash(StringRef K);
00229 
00230   static std::pair<offset_type, offset_type>
00231   ReadKeyDataLength(const unsigned char *&D) {
00232     using namespace support;
00233     offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
00234     offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
00235     return std::make_pair(KeyLen, DataLen);
00236   }
00237 
00238   StringRef ReadKey(const unsigned char *D, offset_type N) {
00239     return StringRef((const char *)D, N);
00240   }
00241 
00242   data_type ReadData(StringRef K, const unsigned char *D, offset_type N) {
00243     DataBuffer.clear();
00244     if (N % sizeof(uint64_t))
00245       // The data is corrupt, don't try to read it.
00246       return data_type("", DataBuffer);
00247 
00248     using namespace support;
00249     // We just treat the data as opaque here. It's simpler to handle in
00250     // IndexedInstrProfReader.
00251     unsigned NumEntries = N / sizeof(uint64_t);
00252     DataBuffer.reserve(NumEntries);
00253     for (unsigned I = 0; I < NumEntries; ++I)
00254       DataBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
00255     return data_type(K, DataBuffer);
00256   }
00257 };
00258 typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait>
00259     InstrProfReaderIndex;
00260 
00261 /// Reader for the indexed binary instrprof format.
00262 class IndexedInstrProfReader : public InstrProfReader {
00263 private:
00264   /// The profile data file contents.
00265   std::unique_ptr<MemoryBuffer> DataBuffer;
00266   /// The index into the profile data.
00267   std::unique_ptr<InstrProfReaderIndex> Index;
00268   /// Iterator over the profile data.
00269   InstrProfReaderIndex::data_iterator RecordIterator;
00270   /// Offset into our current data set.
00271   size_t CurrentOffset;
00272   /// The file format version of the profile data.
00273   uint64_t FormatVersion;
00274   /// The maximal execution count among all functions.
00275   uint64_t MaxFunctionCount;
00276 
00277   IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION;
00278   IndexedInstrProfReader &operator=(const IndexedInstrProfReader &)
00279     LLVM_DELETED_FUNCTION;
00280 public:
00281   IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
00282       : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {}
00283 
00284   /// Return true if the given buffer is in an indexed instrprof format.
00285   static bool hasFormat(const MemoryBuffer &DataBuffer);
00286 
00287   /// Read the file header.
00288   std::error_code readHeader() override;
00289   /// Read a single record.
00290   std::error_code readNextRecord(InstrProfRecord &Record) override;
00291 
00292   /// Fill Counts with the profile data for the given function name.
00293   std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
00294                                     std::vector<uint64_t> &Counts);
00295   /// Return the maximum of all known function counts.
00296   uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
00297 
00298   /// Factory method to create an indexed reader.
00299   static std::error_code
00300   create(std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result);
00301 };
00302 
00303 } // end namespace llvm
00304 
00305 #endif