1//=-- SampleProf.cpp - Sample profiling format support --------------------===//
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 common definitions used in the reading and writing of
11// sample profile data.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ProfileData/SampleProf.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/ManagedStatic.h"
18
19using namespace llvm::sampleprof;
20using namespace llvm;
21
22namespace {
23class SampleProfErrorCategoryType : public std::error_category {
24  const char *name() const LLVM_NOEXCEPT override { return "llvm.sampleprof"; }
25  std::string message(int IE) const override {
26    sampleprof_error E = static_cast<sampleprof_error>(IE);
27    switch (E) {
28    case sampleprof_error::success:
29      return "Success";
30    case sampleprof_error::bad_magic:
31      return "Invalid sample profile data (bad magic)";
32    case sampleprof_error::unsupported_version:
33      return "Unsupported sample profile format version";
34    case sampleprof_error::too_large:
35      return "Too much profile data";
36    case sampleprof_error::truncated:
37      return "Truncated profile data";
38    case sampleprof_error::malformed:
39      return "Malformed sample profile data";
40    case sampleprof_error::unrecognized_format:
41      return "Unrecognized sample profile encoding format";
42    case sampleprof_error::unsupported_writing_format:
43      return "Profile encoding format unsupported for writing operations";
44    case sampleprof_error::truncated_name_table:
45      return "Truncated function name table";
46    case sampleprof_error::not_implemented:
47      return "Unimplemented feature";
48    case sampleprof_error::counter_overflow:
49      return "Counter overflow";
50    }
51    llvm_unreachable("A value of sampleprof_error has no message.");
52  }
53};
54}
55
56static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory;
57
58const std::error_category &llvm::sampleprof_category() {
59  return *ErrorCategory;
60}
61
62void LineLocation::print(raw_ostream &OS) const {
63  OS << LineOffset;
64  if (Discriminator > 0)
65    OS << "." << Discriminator;
66}
67
68raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
69                                          const LineLocation &Loc) {
70  Loc.print(OS);
71  return OS;
72}
73
74void LineLocation::dump() const { print(dbgs()); }
75
76void CallsiteLocation::print(raw_ostream &OS) const {
77  LineLocation::print(OS);
78  OS << ": inlined callee: " << CalleeName;
79}
80
81void CallsiteLocation::dump() const { print(dbgs()); }
82
83inline raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
84                                                 const CallsiteLocation &Loc) {
85  Loc.print(OS);
86  return OS;
87}
88
89/// \brief Print the sample record to the stream \p OS indented by \p Indent.
90void SampleRecord::print(raw_ostream &OS, unsigned Indent) const {
91  OS << NumSamples;
92  if (hasCalls()) {
93    OS << ", calls:";
94    for (const auto &I : getCallTargets())
95      OS << " " << I.first() << ":" << I.second;
96  }
97  OS << "\n";
98}
99
100void SampleRecord::dump() const { print(dbgs(), 0); }
101
102raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
103                                          const SampleRecord &Sample) {
104  Sample.print(OS, 0);
105  return OS;
106}
107
108/// \brief Print the samples collected for a function on stream \p OS.
109void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
110  OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
111     << " sampled lines\n";
112
113  OS.indent(Indent);
114  if (BodySamples.size() > 0) {
115    OS << "Samples collected in the function's body {\n";
116    SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples);
117    for (const auto &SI : SortedBodySamples.get()) {
118      OS.indent(Indent + 2);
119      OS << SI->first << ": " << SI->second;
120    }
121    OS.indent(Indent);
122    OS << "}\n";
123  } else {
124    OS << "No samples collected in the function's body\n";
125  }
126
127  OS.indent(Indent);
128  if (CallsiteSamples.size() > 0) {
129    OS << "Samples collected in inlined callsites {\n";
130    SampleSorter<CallsiteLocation, FunctionSamples> SortedCallsiteSamples(
131        CallsiteSamples);
132    for (const auto &CS : SortedCallsiteSamples.get()) {
133      OS.indent(Indent + 2);
134      OS << CS->first << ": ";
135      CS->second.print(OS, Indent + 4);
136    }
137    OS << "}\n";
138  } else {
139    OS << "No inlined callsites in this function\n";
140  }
141}
142
143raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
144                                          const FunctionSamples &FS) {
145  FS.print(OS);
146  return OS;
147}
148
149void FunctionSamples::dump(void) const { print(dbgs(), 0); }
150