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/Config/llvm-config.h" 17 #include "llvm/IR/DebugInfoMetadata.h" 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/ManagedStatic.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <string> 24 #include <system_error> 25 26 using namespace llvm; 27 using namespace sampleprof; 28 29 namespace { 30 31 // FIXME: This class is only here to support the transition to llvm::Error. It 32 // will be removed once this transition is complete. Clients should prefer to 33 // deal with the Error value directly, rather than converting to error_code. 34 class SampleProfErrorCategoryType : public std::error_category { 35 const char *name() const noexcept override { return "llvm.sampleprof"; } 36 37 std::string message(int IE) const override { 38 sampleprof_error E = static_cast<sampleprof_error>(IE); 39 switch (E) { 40 case sampleprof_error::success: 41 return "Success"; 42 case sampleprof_error::bad_magic: 43 return "Invalid sample profile data (bad magic)"; 44 case sampleprof_error::unsupported_version: 45 return "Unsupported sample profile format version"; 46 case sampleprof_error::too_large: 47 return "Too much profile data"; 48 case sampleprof_error::truncated: 49 return "Truncated profile data"; 50 case sampleprof_error::malformed: 51 return "Malformed sample profile data"; 52 case sampleprof_error::unrecognized_format: 53 return "Unrecognized sample profile encoding format"; 54 case sampleprof_error::unsupported_writing_format: 55 return "Profile encoding format unsupported for writing operations"; 56 case sampleprof_error::truncated_name_table: 57 return "Truncated function name table"; 58 case sampleprof_error::not_implemented: 59 return "Unimplemented feature"; 60 case sampleprof_error::counter_overflow: 61 return "Counter overflow"; 62 } 63 llvm_unreachable("A value of sampleprof_error has no message."); 64 } 65 }; 66 67 } // end anonymous namespace 68 69 static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory; 70 71 const std::error_category &llvm::sampleprof_category() { 72 return *ErrorCategory; 73 } 74 75 void LineLocation::print(raw_ostream &OS) const { 76 OS << LineOffset; 77 if (Discriminator > 0) 78 OS << "." << Discriminator; 79 } 80 81 raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, 82 const LineLocation &Loc) { 83 Loc.print(OS); 84 return OS; 85 } 86 87 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 88 LLVM_DUMP_METHOD void LineLocation::dump() const { print(dbgs()); } 89 #endif 90 91 /// Print the sample record to the stream \p OS indented by \p Indent. 92 void SampleRecord::print(raw_ostream &OS, unsigned Indent) const { 93 OS << NumSamples; 94 if (hasCalls()) { 95 OS << ", calls:"; 96 for (const auto &I : getCallTargets()) 97 OS << " " << I.first() << ":" << I.second; 98 } 99 OS << "\n"; 100 } 101 102 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 103 LLVM_DUMP_METHOD void SampleRecord::dump() const { print(dbgs(), 0); } 104 #endif 105 106 raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, 107 const SampleRecord &Sample) { 108 Sample.print(OS, 0); 109 return OS; 110 } 111 112 /// Print the samples collected for a function on stream \p OS. 113 void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const { 114 OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size() 115 << " sampled lines\n"; 116 117 OS.indent(Indent); 118 if (!BodySamples.empty()) { 119 OS << "Samples collected in the function's body {\n"; 120 SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples); 121 for (const auto &SI : SortedBodySamples.get()) { 122 OS.indent(Indent + 2); 123 OS << SI->first << ": " << SI->second; 124 } 125 OS.indent(Indent); 126 OS << "}\n"; 127 } else { 128 OS << "No samples collected in the function's body\n"; 129 } 130 131 OS.indent(Indent); 132 if (!CallsiteSamples.empty()) { 133 OS << "Samples collected in inlined callsites {\n"; 134 SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples( 135 CallsiteSamples); 136 for (const auto &CS : SortedCallsiteSamples.get()) { 137 for (const auto &FS : CS->second) { 138 OS.indent(Indent + 2); 139 OS << CS->first << ": inlined callee: " << FS.second.getName() << ": "; 140 FS.second.print(OS, Indent + 4); 141 } 142 } 143 OS << "}\n"; 144 } else { 145 OS << "No inlined callsites in this function\n"; 146 } 147 } 148 149 raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, 150 const FunctionSamples &FS) { 151 FS.print(OS); 152 return OS; 153 } 154 155 unsigned FunctionSamples::getOffset(const DILocation *DIL) { 156 return (DIL->getLine() - DIL->getScope()->getSubprogram()->getLine()) & 157 0xffff; 158 } 159 160 const FunctionSamples * 161 FunctionSamples::findFunctionSamples(const DILocation *DIL) const { 162 assert(DIL); 163 SmallVector<std::pair<LineLocation, StringRef>, 10> S; 164 165 const DILocation *PrevDIL = DIL; 166 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) { 167 S.push_back(std::make_pair( 168 LineLocation(getOffset(DIL), DIL->getBaseDiscriminator()), 169 PrevDIL->getScope()->getSubprogram()->getLinkageName())); 170 PrevDIL = DIL; 171 } 172 if (S.size() == 0) 173 return this; 174 const FunctionSamples *FS = this; 175 for (int i = S.size() - 1; i >= 0 && FS != nullptr; i--) { 176 FS = FS->findFunctionSamplesAt(S[i].first, S[i].second); 177 } 178 return FS; 179 } 180 181 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 182 LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); } 183 #endif 184