blob: daf3783aba65bf8dfb52c0a65fb1342ef23906a8 [file] [log] [blame]
Diego Novilloc572e922014-10-30 18:00:06 +00001//===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===//
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 implements the class that writes LLVM sample profiles. It
11// supports two file formats: text and binary. The textual representation
12// is useful for debugging and testing purposes. The binary representation
13// is more compact, resulting in smaller file sizes. However, they can
14// both be used interchangeably.
15//
16// See lib/ProfileData/SampleProfReader.cpp for documentation on each of the
17// supported formats.
18//
19//===----------------------------------------------------------------------===//
20
21#include "llvm/ProfileData/SampleProfWriter.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/ErrorOr.h"
Diego Novilloc572e922014-10-30 18:00:06 +000024#include "llvm/Support/LEB128.h"
25#include "llvm/Support/LineIterator.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000026#include "llvm/Support/MemoryBuffer.h"
Diego Novilloc572e922014-10-30 18:00:06 +000027#include "llvm/Support/Regex.h"
28
29using namespace llvm::sampleprof;
30using namespace llvm;
31
32/// \brief Write samples to a text file.
Diego Novillo760c5a82015-10-13 22:48:46 +000033std::error_code SampleProfileWriterText::write(StringRef FName,
34 const FunctionSamples &S) {
Diego Novilloaae1ed82015-10-08 19:40:37 +000035 OS << FName << ":" << S.getTotalSamples();
36 if (Indent == 0)
37 OS << ":" << S.getHeadSamples();
38 OS << "\n";
Diego Novilloc572e922014-10-30 18:00:06 +000039
Diego Novillod5336ae2014-11-01 00:56:55 +000040 for (const auto &I : S.getBodySamples()) {
41 LineLocation Loc = I.first;
42 const SampleRecord &Sample = I.second;
Diego Novilloaae1ed82015-10-08 19:40:37 +000043 OS.indent(Indent + 1);
Diego Novilloc572e922014-10-30 18:00:06 +000044 if (Loc.Discriminator == 0)
45 OS << Loc.LineOffset << ": ";
46 else
47 OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
48
49 OS << Sample.getSamples();
50
Diego Novillod5336ae2014-11-01 00:56:55 +000051 for (const auto &J : Sample.getCallTargets())
52 OS << " " << J.first() << ":" << J.second;
Diego Novilloc572e922014-10-30 18:00:06 +000053 OS << "\n";
54 }
55
Diego Novilloaae1ed82015-10-08 19:40:37 +000056 Indent += 1;
57 for (const auto &I : S.getCallsiteSamples()) {
58 CallsiteLocation Loc = I.first;
59 const FunctionSamples &CalleeSamples = I.second;
60 OS.indent(Indent);
61 if (Loc.Discriminator == 0)
62 OS << Loc.LineOffset << ": ";
63 else
64 OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
Diego Novillo760c5a82015-10-13 22:48:46 +000065 if (std::error_code EC = write(Loc.CalleeName, CalleeSamples))
66 return EC;
Diego Novilloaae1ed82015-10-08 19:40:37 +000067 }
68 Indent -= 1;
69
Diego Novillo760c5a82015-10-13 22:48:46 +000070 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +000071}
72
Diego Novillo760c5a82015-10-13 22:48:46 +000073std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
74 const auto &ret = NameTable.find(FName);
75 if (ret == NameTable.end())
76 return sampleprof_error::truncated_name_table;
77 encodeULEB128(ret->second, OS);
78 return sampleprof_error::success;
79}
Diego Novilloc572e922014-10-30 18:00:06 +000080
Diego Novillo760c5a82015-10-13 22:48:46 +000081void SampleProfileWriterBinary::addName(StringRef FName) {
82 auto NextIdx = NameTable.size();
83 NameTable.insert(std::make_pair(FName, NextIdx));
84}
85
86void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
87 // Add all the names in indirect call targets.
88 for (const auto &I : S.getBodySamples()) {
89 const SampleRecord &Sample = I.second;
90 for (const auto &J : Sample.getCallTargets())
91 addName(J.first());
92 }
93
94 // Recursively add all the names for inlined callsites.
95 for (const auto &J : S.getCallsiteSamples()) {
96 CallsiteLocation Loc = J.first;
97 const FunctionSamples &CalleeSamples = J.second;
98 addName(Loc.CalleeName);
99 addNames(CalleeSamples);
100 }
101}
102
103std::error_code SampleProfileWriterBinary::writeHeader(
104 const StringMap<FunctionSamples> &ProfileMap) {
105 // Write file magic identifier.
Diego Novilloc572e922014-10-30 18:00:06 +0000106 encodeULEB128(SPMagic(), OS);
107 encodeULEB128(SPVersion(), OS);
Diego Novillo760c5a82015-10-13 22:48:46 +0000108
109 // Generate the name table for all the functions referenced in the profile.
110 for (const auto &I : ProfileMap) {
111 addName(I.first());
112 addNames(I.second);
113 }
114
115 // Write out the name table.
116 encodeULEB128(NameTable.size(), OS);
117 for (auto N : NameTable) {
118 OS << N.first;
119 encodeULEB128(0, OS);
120 }
121
122 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +0000123}
124
125/// \brief Write samples to a binary file.
126///
127/// \returns true if the samples were written successfully, false otherwise.
Diego Novillo760c5a82015-10-13 22:48:46 +0000128std::error_code SampleProfileWriterBinary::write(StringRef FName,
129 const FunctionSamples &S) {
130 if (std::error_code EC = writeNameIdx(FName))
131 return EC;
132
Diego Novilloc572e922014-10-30 18:00:06 +0000133 encodeULEB128(S.getTotalSamples(), OS);
134 encodeULEB128(S.getHeadSamples(), OS);
135 encodeULEB128(S.getBodySamples().size(), OS);
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000136
137 // Emit all the body samples.
Diego Novillod5336ae2014-11-01 00:56:55 +0000138 for (const auto &I : S.getBodySamples()) {
139 LineLocation Loc = I.first;
140 const SampleRecord &Sample = I.second;
Diego Novilloc572e922014-10-30 18:00:06 +0000141 encodeULEB128(Loc.LineOffset, OS);
142 encodeULEB128(Loc.Discriminator, OS);
143 encodeULEB128(Sample.getSamples(), OS);
144 encodeULEB128(Sample.getCallTargets().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +0000145 for (const auto &J : Sample.getCallTargets()) {
Diego Novillo760c5a82015-10-13 22:48:46 +0000146 StringRef Callee = J.first();
Diego Novillo38be3332015-10-15 16:36:21 +0000147 uint64_t CalleeSamples = J.second;
Diego Novillo760c5a82015-10-13 22:48:46 +0000148 if (std::error_code EC = writeNameIdx(Callee))
149 return EC;
Diego Novilloc572e922014-10-30 18:00:06 +0000150 encodeULEB128(CalleeSamples, OS);
151 }
152 }
153
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000154 // Recursively emit all the callsite samples.
155 encodeULEB128(S.getCallsiteSamples().size(), OS);
156 for (const auto &J : S.getCallsiteSamples()) {
157 CallsiteLocation Loc = J.first;
158 const FunctionSamples &CalleeSamples = J.second;
159 encodeULEB128(Loc.LineOffset, OS);
160 encodeULEB128(Loc.Discriminator, OS);
Diego Novillo760c5a82015-10-13 22:48:46 +0000161 if (std::error_code EC = write(Loc.CalleeName, CalleeSamples))
162 return EC;
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000163 }
164
Diego Novillo760c5a82015-10-13 22:48:46 +0000165 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +0000166}
Diego Novillod5336ae2014-11-01 00:56:55 +0000167
168/// \brief Create a sample profile writer based on the specified format.
169///
170/// \param Filename The file to create.
171///
172/// \param Writer The writer to instantiate according to the specified format.
173///
174/// \param Format Encoding format for the profile file.
175///
176/// \returns an error code indicating the status of the created writer.
Diego Novillofcd55602014-11-03 00:51:45 +0000177ErrorOr<std::unique_ptr<SampleProfileWriter>>
178SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
Diego Novillod5336ae2014-11-01 00:56:55 +0000179 std::error_code EC;
Diego Novillofcd55602014-11-03 00:51:45 +0000180 std::unique_ptr<SampleProfileWriter> Writer;
Diego Novillod5336ae2014-11-01 00:56:55 +0000181
182 if (Format == SPF_Binary)
183 Writer.reset(new SampleProfileWriterBinary(Filename, EC));
184 else if (Format == SPF_Text)
185 Writer.reset(new SampleProfileWriterText(Filename, EC));
Diego Novillo760c5a82015-10-13 22:48:46 +0000186 else if (Format == SPF_GCC)
187 EC = sampleprof_error::unsupported_writing_format;
Diego Novillod5336ae2014-11-01 00:56:55 +0000188 else
189 EC = sampleprof_error::unrecognized_format;
190
Diego Novillofcd55602014-11-03 00:51:45 +0000191 if (EC)
192 return EC;
193
194 return std::move(Writer);
Diego Novillod5336ae2014-11-01 00:56:55 +0000195}