forked from llvm-mirror/llvm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSampleProfWriter.cpp
200 lines (174 loc) · 6.36 KB
/
SampleProfWriter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the class that writes LLVM sample profiles. It
// supports two file formats: text and binary. The textual representation
// is useful for debugging and testing purposes. The binary representation
// is more compact, resulting in smaller file sizes. However, they can
// both be used interchangeably.
//
// See lib/ProfileData/SampleProfReader.cpp for documentation on each of the
// supported formats.
//
//===----------------------------------------------------------------------===//
#include "llvm/ProfileData/SampleProfWriter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
using namespace llvm::sampleprof;
using namespace llvm;
/// \brief Write samples to a text file.
std::error_code SampleProfileWriterText::write(StringRef FName,
const FunctionSamples &S) {
OS << FName << ":" << S.getTotalSamples();
if (Indent == 0)
OS << ":" << S.getHeadSamples();
OS << "\n";
for (const auto &I : S.getBodySamples()) {
LineLocation Loc = I.first;
const SampleRecord &Sample = I.second;
OS.indent(Indent + 1);
if (Loc.Discriminator == 0)
OS << Loc.LineOffset << ": ";
else
OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
OS << Sample.getSamples();
for (const auto &J : Sample.getCallTargets())
OS << " " << J.first() << ":" << J.second;
OS << "\n";
}
Indent += 1;
for (const auto &I : S.getCallsiteSamples()) {
CallsiteLocation Loc = I.first;
const FunctionSamples &CalleeSamples = I.second;
OS.indent(Indent);
if (Loc.Discriminator == 0)
OS << Loc.LineOffset << ": ";
else
OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
if (std::error_code EC = write(Loc.CalleeName, CalleeSamples))
return EC;
}
Indent -= 1;
return sampleprof_error::success;
}
std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
const auto &ret = NameTable.find(FName);
if (ret == NameTable.end())
return sampleprof_error::truncated_name_table;
encodeULEB128(ret->second, OS);
return sampleprof_error::success;
}
void SampleProfileWriterBinary::addName(StringRef FName) {
auto NextIdx = NameTable.size();
NameTable.insert(std::make_pair(FName, NextIdx));
}
void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
// Add all the names in indirect call targets.
for (const auto &I : S.getBodySamples()) {
const SampleRecord &Sample = I.second;
for (const auto &J : Sample.getCallTargets())
addName(J.first());
}
// Recursively add all the names for inlined callsites.
for (const auto &J : S.getCallsiteSamples()) {
CallsiteLocation Loc = J.first;
const FunctionSamples &CalleeSamples = J.second;
addName(Loc.CalleeName);
addNames(CalleeSamples);
}
}
std::error_code SampleProfileWriterBinary::writeHeader(
const StringMap<FunctionSamples> &ProfileMap) {
// Write file magic identifier.
encodeULEB128(SPMagic(), OS);
encodeULEB128(SPVersion(), OS);
// Generate the name table for all the functions referenced in the profile.
for (const auto &I : ProfileMap) {
addName(I.first());
addNames(I.second);
}
// Write out the name table.
encodeULEB128(NameTable.size(), OS);
for (auto N : NameTable) {
OS << N.first;
encodeULEB128(0, OS);
}
return sampleprof_error::success;
}
std::error_code SampleProfileWriterBinary::writeBody(StringRef FName,
const FunctionSamples &S) {
if (std::error_code EC = writeNameIdx(FName))
return EC;
encodeULEB128(S.getTotalSamples(), OS);
// Emit all the body samples.
encodeULEB128(S.getBodySamples().size(), OS);
for (const auto &I : S.getBodySamples()) {
LineLocation Loc = I.first;
const SampleRecord &Sample = I.second;
encodeULEB128(Loc.LineOffset, OS);
encodeULEB128(Loc.Discriminator, OS);
encodeULEB128(Sample.getSamples(), OS);
encodeULEB128(Sample.getCallTargets().size(), OS);
for (const auto &J : Sample.getCallTargets()) {
StringRef Callee = J.first();
uint64_t CalleeSamples = J.second;
if (std::error_code EC = writeNameIdx(Callee))
return EC;
encodeULEB128(CalleeSamples, OS);
}
}
// Recursively emit all the callsite samples.
encodeULEB128(S.getCallsiteSamples().size(), OS);
for (const auto &J : S.getCallsiteSamples()) {
CallsiteLocation Loc = J.first;
const FunctionSamples &CalleeSamples = J.second;
encodeULEB128(Loc.LineOffset, OS);
encodeULEB128(Loc.Discriminator, OS);
if (std::error_code EC = writeBody(Loc.CalleeName, CalleeSamples))
return EC;
}
return sampleprof_error::success;
}
/// \brief Write samples of a top-level function to a binary file.
///
/// \returns true if the samples were written successfully, false otherwise.
std::error_code SampleProfileWriterBinary::write(StringRef FName,
const FunctionSamples &S) {
encodeULEB128(S.getHeadSamples(), OS);
return writeBody(FName, S);
}
/// \brief Create a sample profile writer based on the specified format.
///
/// \param Filename The file to create.
///
/// \param Writer The writer to instantiate according to the specified format.
///
/// \param Format Encoding format for the profile file.
///
/// \returns an error code indicating the status of the created writer.
ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
std::error_code EC;
std::unique_ptr<SampleProfileWriter> Writer;
if (Format == SPF_Binary)
Writer.reset(new SampleProfileWriterBinary(Filename, EC));
else if (Format == SPF_Text)
Writer.reset(new SampleProfileWriterText(Filename, EC));
else if (Format == SPF_GCC)
EC = sampleprof_error::unsupported_writing_format;
else
EC = sampleprof_error::unrecognized_format;
if (EC)
return EC;
return std::move(Writer);
}