Add inline stack streaming to binary sample profiles.
[oota-llvm.git] / include / llvm / ProfileData / SampleProfReader.h
index e52ecf8e2123dace529fa924ca3233e2882bf28e..e2976e2efab75a7db3bb354ce3ad9598bb68def1 100644 (file)
 #define LLVM_PROFILEDATA_SAMPLEPROFREADER_H
 
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/IR/DiagnosticInfo.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/LLVMContext.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/GCOV.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -56,7 +58,7 @@ namespace sampleprof {
 ///
 /// The reader supports two file formats: text and binary. The text format
 /// is useful for debugging and testing, while the binary format is more
-/// compact. They can both be used interchangeably.
+/// compact and I/O efficient. They can both be used interchangeably.
 class SampleProfileReader {
 public:
   SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
@@ -64,9 +66,6 @@ public:
 
   virtual ~SampleProfileReader() {}
 
-  /// \brief Print all the profiles to dbgs().
-  void dump();
-
   /// \brief Read and validate the file header.
   virtual std::error_code readHeader() = 0;
 
@@ -74,26 +73,28 @@ public:
   virtual std::error_code read() = 0;
 
   /// \brief Print the profile for \p FName on stream \p OS.
-  void printFunctionProfile(raw_ostream &OS, StringRef FName);
+  void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs());
 
-  /// \brief Print the profile for \p FName on dbgs().
-  void dumpFunctionProfile(StringRef FName);
+  /// \brief Print all the profiles on stream \p OS.
+  void dump(raw_ostream &OS = dbgs());
 
   /// \brief Return the samples collected for function \p F.
   FunctionSamples *getSamplesFor(const Function &F) {
     return &Profiles[F.getName()];
   }
 
+  /// \brief Return all the profiles.
+  StringMap<FunctionSamples> &getProfiles() { return Profiles; }
+
   /// \brief Report a parse error message.
-  void reportParseError(int64_t LineNumber, Twine Msg) const {
+  void reportError(int64_t LineNumber, Twine Msg) const {
     Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(),
                                              LineNumber, Msg));
   }
 
   /// \brief Create a sample profile reader appropriate to the file format.
-  static std::error_code create(std::string Filename,
-                                std::unique_ptr<SampleProfileReader> &Reader,
-                                LLVMContext &C);
+  static ErrorOr<std::unique_ptr<SampleProfileReader>>
+  create(StringRef Filename, LLVMContext &C);
 
 protected:
   /// \brief Map every function to its associated profile.
@@ -156,6 +157,9 @@ protected:
   /// \brief Return true if we've reached the end of file.
   bool at_eof() const { return Data >= End; }
 
+  /// Read the contents of the given profile instance.
+  std::error_code readProfile(FunctionSamples &FProfile);
+
   /// \brief Points to the current location in the buffer.
   const uint8_t *Data;
 
@@ -163,6 +167,83 @@ protected:
   const uint8_t *End;
 };
 
+// Represents the source position in GCC sample profiles.
+struct SourceInfo {
+  SourceInfo()
+      : FuncName(), DirName(), FileName(), StartLine(0), Line(0),
+        Discriminator(0) {}
+
+  SourceInfo(StringRef FuncName, StringRef DirName, StringRef FileName,
+             uint32_t StartLine, uint32_t Line, uint32_t Discriminator)
+      : FuncName(FuncName), DirName(DirName), FileName(FileName),
+        StartLine(StartLine), Line(Line), Discriminator(Discriminator) {}
+
+  bool operator<(const SourceInfo &p) const;
+
+  uint32_t Offset() const { return ((Line - StartLine) << 16) | Discriminator; }
+
+  bool Malformed() const { return Line < StartLine; }
+
+  StringRef FuncName;
+  StringRef DirName;
+  StringRef FileName;
+  uint32_t StartLine;
+  uint32_t Line;
+  uint32_t Discriminator;
+};
+
+typedef SmallVector<FunctionSamples *, 10> InlineCallStack;
+
+// Supported histogram types in GCC.  Currently, we only need support for
+// call target histograms.
+enum HistType {
+  HIST_TYPE_INTERVAL,
+  HIST_TYPE_POW2,
+  HIST_TYPE_SINGLE_VALUE,
+  HIST_TYPE_CONST_DELTA,
+  HIST_TYPE_INDIR_CALL,
+  HIST_TYPE_AVERAGE,
+  HIST_TYPE_IOR,
+  HIST_TYPE_INDIR_CALL_TOPN
+};
+
+class SampleProfileReaderGCC : public SampleProfileReader {
+public:
+  SampleProfileReaderGCC(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
+      : SampleProfileReader(std::move(B), C), GcovBuffer(Buffer.get()) {}
+
+  /// \brief Read and validate the file header.
+  std::error_code readHeader() override;
+
+  /// \brief Read sample profiles from the associated file.
+  std::error_code read() override;
+
+  /// \brief Return true if \p Buffer is in the format supported by this class.
+  static bool hasFormat(const MemoryBuffer &Buffer);
+
+protected:
+  std::error_code readNameTable();
+  std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack,
+                                         bool Update, uint32_t Offset);
+  std::error_code readFunctionProfiles();
+  std::error_code skipNextWord();
+  template <typename T> ErrorOr<T> readNumber();
+  ErrorOr<StringRef> readString();
+
+  /// \brief Read the section tag and check that it's the same as \p Expected.
+  std::error_code readSectionTag(uint32_t Expected);
+
+  /// GCOV buffer containing the profile.
+  GCOVBuffer GcovBuffer;
+
+  /// Function names in this profile.
+  std::vector<std::string> Names;
+
+  /// GCOV tags used to separate sections in the profile file.
+  static const uint32_t GCOVTagAFDOFileNames = 0xaa000000;
+  static const uint32_t GCOVTagAFDOFunction = 0xac000000;
+};
+
 } // End namespace sampleprof
 
 } // End namespace llvm