blob: a6e3cabd89ed762c88d9c0c5612aa7b436c5bb0a [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
Diego Novillob93483d2015-10-16 18:54:35 +0000125std::error_code SampleProfileWriterBinary::writeBody(StringRef FName,
126 const FunctionSamples &S) {
Diego Novillo760c5a82015-10-13 22:48:46 +0000127 if (std::error_code EC = writeNameIdx(FName))
128 return EC;
129
Diego Novilloc572e922014-10-30 18:00:06 +0000130 encodeULEB128(S.getTotalSamples(), OS);
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000131
132 // Emit all the body samples.
Diego Novillob93483d2015-10-16 18:54:35 +0000133 encodeULEB128(S.getBodySamples().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +0000134 for (const auto &I : S.getBodySamples()) {
135 LineLocation Loc = I.first;
136 const SampleRecord &Sample = I.second;
Diego Novilloc572e922014-10-30 18:00:06 +0000137 encodeULEB128(Loc.LineOffset, OS);
138 encodeULEB128(Loc.Discriminator, OS);
139 encodeULEB128(Sample.getSamples(), OS);
140 encodeULEB128(Sample.getCallTargets().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +0000141 for (const auto &J : Sample.getCallTargets()) {
Diego Novillo760c5a82015-10-13 22:48:46 +0000142 StringRef Callee = J.first();
Diego Novillo38be3332015-10-15 16:36:21 +0000143 uint64_t CalleeSamples = J.second;
Diego Novillo760c5a82015-10-13 22:48:46 +0000144 if (std::error_code EC = writeNameIdx(Callee))
145 return EC;
Diego Novilloc572e922014-10-30 18:00:06 +0000146 encodeULEB128(CalleeSamples, OS);
147 }
148 }
149
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000150 // Recursively emit all the callsite samples.
151 encodeULEB128(S.getCallsiteSamples().size(), OS);
152 for (const auto &J : S.getCallsiteSamples()) {
153 CallsiteLocation Loc = J.first;
154 const FunctionSamples &CalleeSamples = J.second;
155 encodeULEB128(Loc.LineOffset, OS);
156 encodeULEB128(Loc.Discriminator, OS);
Diego Novillob93483d2015-10-16 18:54:35 +0000157 if (std::error_code EC = writeBody(Loc.CalleeName, CalleeSamples))
Diego Novillo760c5a82015-10-13 22:48:46 +0000158 return EC;
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000159 }
160
Diego Novillo760c5a82015-10-13 22:48:46 +0000161 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +0000162}
Diego Novillod5336ae2014-11-01 00:56:55 +0000163
Diego Novillob93483d2015-10-16 18:54:35 +0000164/// \brief Write samples of a top-level function to a binary file.
165///
166/// \returns true if the samples were written successfully, false otherwise.
167std::error_code SampleProfileWriterBinary::write(StringRef FName,
168 const FunctionSamples &S) {
169 encodeULEB128(S.getHeadSamples(), OS);
170 return writeBody(FName, S);
171}
172
Diego Novillod5336ae2014-11-01 00:56:55 +0000173/// \brief Create a sample profile writer based on the specified format.
174///
175/// \param Filename The file to create.
176///
177/// \param Writer The writer to instantiate according to the specified format.
178///
179/// \param Format Encoding format for the profile file.
180///
181/// \returns an error code indicating the status of the created writer.
Diego Novillofcd55602014-11-03 00:51:45 +0000182ErrorOr<std::unique_ptr<SampleProfileWriter>>
183SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
Diego Novillod5336ae2014-11-01 00:56:55 +0000184 std::error_code EC;
Diego Novillofcd55602014-11-03 00:51:45 +0000185 std::unique_ptr<SampleProfileWriter> Writer;
Diego Novillod5336ae2014-11-01 00:56:55 +0000186
187 if (Format == SPF_Binary)
188 Writer.reset(new SampleProfileWriterBinary(Filename, EC));
189 else if (Format == SPF_Text)
190 Writer.reset(new SampleProfileWriterText(Filename, EC));
Diego Novillo760c5a82015-10-13 22:48:46 +0000191 else if (Format == SPF_GCC)
192 EC = sampleprof_error::unsupported_writing_format;
Diego Novillod5336ae2014-11-01 00:56:55 +0000193 else
194 EC = sampleprof_error::unrecognized_format;
195
Diego Novillofcd55602014-11-03 00:51:45 +0000196 if (EC)
197 return EC;
198
199 return std::move(Writer);
Diego Novillod5336ae2014-11-01 00:56:55 +0000200}