blob: 068ce5bf959cda1ed7ad1cde942918a9f785958e [file] [log] [blame]
Diego Novilloc572e922014-10-30 18:00:06 +00001//===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Diego Novilloc572e922014-10-30 18:00:06 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the class that writes LLVM sample profiles. It
10// supports two file formats: text and binary. The textual representation
11// is useful for debugging and testing purposes. The binary representation
12// is more compact, resulting in smaller file sizes. However, they can
13// both be used interchangeably.
14//
15// See lib/ProfileData/SampleProfReader.cpp for documentation on each of the
16// supported formats.
17//
18//===----------------------------------------------------------------------===//
19
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ProfileData/SampleProfWriter.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000021#include "llvm/ADT/StringRef.h"
22#include "llvm/ProfileData/ProfileCommon.h"
23#include "llvm/ProfileData/SampleProf.h"
Wei Mi6a143252018-09-14 20:52:59 +000024#include "llvm/Support/Endian.h"
25#include "llvm/Support/EndianStream.h"
Diego Novilloc572e922014-10-30 18:00:06 +000026#include "llvm/Support/ErrorOr.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000027#include "llvm/Support/FileSystem.h"
Diego Novilloc572e922014-10-30 18:00:06 +000028#include "llvm/Support/LEB128.h"
Wei Mia0c08572018-06-11 22:40:43 +000029#include "llvm/Support/MD5.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000030#include "llvm/Support/raw_ostream.h"
31#include <algorithm>
32#include <cstdint>
33#include <memory>
Dehao Chen8d1c9832017-05-11 23:43:44 +000034#include <set>
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000035#include <system_error>
36#include <utility>
37#include <vector>
Diego Novilloc572e922014-10-30 18:00:06 +000038
Diego Novilloc572e922014-10-30 18:00:06 +000039using namespace llvm;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000040using namespace sampleprof;
Diego Novilloc572e922014-10-30 18:00:06 +000041
Wei Mibe907322019-08-23 19:05:30 +000042std::error_code SampleProfileWriter::writeFuncProfiles(
43 const StringMap<FunctionSamples> &ProfileMap) {
Dehao Chen8d1c9832017-05-11 23:43:44 +000044 // Sort the ProfileMap by total samples.
45 typedef std::pair<StringRef, const FunctionSamples *> NameFunctionSamples;
46 std::vector<NameFunctionSamples> V;
47 for (const auto &I : ProfileMap)
48 V.push_back(std::make_pair(I.getKey(), &I.second));
49
Fangrui Songefd94c52019-04-23 14:51:27 +000050 llvm::stable_sort(
51 V, [](const NameFunctionSamples &A, const NameFunctionSamples &B) {
Dehao Chen8d1c9832017-05-11 23:43:44 +000052 if (A.second->getTotalSamples() == B.second->getTotalSamples())
53 return A.first > B.first;
54 return A.second->getTotalSamples() > B.second->getTotalSamples();
55 });
56
57 for (const auto &I : V) {
Wei Mibe907322019-08-23 19:05:30 +000058 if (std::error_code EC = writeSample(*I.second))
Dehao Chen8d1c9832017-05-11 23:43:44 +000059 return EC;
60 }
61 return sampleprof_error::success;
62}
63
Wei Mibe907322019-08-23 19:05:30 +000064std::error_code
65SampleProfileWriter::write(const StringMap<FunctionSamples> &ProfileMap) {
66 if (std::error_code EC = writeHeader(ProfileMap))
67 return EC;
68
69 if (std::error_code EC = writeFuncProfiles(ProfileMap))
70 return EC;
71
72 return sampleprof_error::success;
73}
74
75/// Return the current position and prepare to use it as the start
76/// position of a section.
77uint64_t SampleProfileWriterExtBinaryBase::markSectionStart() {
78 return OutputStream->tell();
79}
80
81/// Add a new section into section header table. Return the position
82/// of SectionEnd.
83uint64_t
84SampleProfileWriterExtBinaryBase::addNewSection(SecType Sec,
85 uint64_t SectionStart) {
86 uint64_t SectionEnd = OutputStream->tell();
87 SecHdrTable.push_back(
88 {Sec, 0, SectionStart - FileStart, SectionEnd - SectionStart});
89 return SectionEnd;
90}
91
92std::error_code SampleProfileWriterExtBinaryBase::write(
93 const StringMap<FunctionSamples> &ProfileMap) {
94 if (std::error_code EC = writeHeader(ProfileMap))
95 return EC;
96
97 if (std::error_code EC = writeSections(ProfileMap))
98 return EC;
99
100 if (std::error_code EC = writeSecHdrTable())
101 return EC;
102
103 return sampleprof_error::success;
104}
105
106std::error_code SampleProfileWriterExtBinary::writeSections(
107 const StringMap<FunctionSamples> &ProfileMap) {
108 uint64_t SectionStart = markSectionStart();
109 computeSummary(ProfileMap);
110 if (auto EC = writeSummary())
111 return EC;
112 SectionStart = addNewSection(SecProfSummary, SectionStart);
113
114 // Generate the name table for all the functions referenced in the profile.
115 for (const auto &I : ProfileMap) {
116 addName(I.first());
117 addNames(I.second);
118 }
119 writeNameTable();
120 SectionStart = addNewSection(SecNameTable, SectionStart);
121
122 if (std::error_code EC = writeFuncProfiles(ProfileMap))
123 return EC;
Wei Mi798e59b2019-08-31 02:27:26 +0000124 SectionStart = addNewSection(SecLBRProfile, SectionStart);
125
126 if (ProfSymList && ProfSymList->size() > 0)
127 if (std::error_code EC = ProfSymList->write(*OutputStream))
128 return EC;
129 addNewSection(SecProfileSymbolList, SectionStart);
Wei Mibe907322019-08-23 19:05:30 +0000130
131 return sampleprof_error::success;
132}
133
Wei Mi6a143252018-09-14 20:52:59 +0000134std::error_code SampleProfileWriterCompactBinary::write(
135 const StringMap<FunctionSamples> &ProfileMap) {
136 if (std::error_code EC = SampleProfileWriter::write(ProfileMap))
137 return EC;
138 if (std::error_code EC = writeFuncOffsetTable())
139 return EC;
140 return sampleprof_error::success;
141}
142
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000143/// Write samples to a text file.
Diego Novillo8e415a82015-11-13 20:24:28 +0000144///
145/// Note: it may be tempting to implement this in terms of
Diego Novilloef548d22015-11-19 15:33:08 +0000146/// FunctionSamples::print(). Please don't. The dump functionality is intended
Diego Novillo8e415a82015-11-13 20:24:28 +0000147/// for debugging and has no specified form.
148///
149/// The format used here is more structured and deliberate because
150/// it needs to be parsed by the SampleProfileReaderText class.
Wei Mibe907322019-08-23 19:05:30 +0000151std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
Nathan Slingerland51abea72015-12-10 17:21:42 +0000152 auto &OS = *OutputStream;
Dehao Chen57d1dda2016-03-03 18:09:32 +0000153 OS << S.getName() << ":" << S.getTotalSamples();
Diego Novilloaae1ed82015-10-08 19:40:37 +0000154 if (Indent == 0)
155 OS << ":" << S.getHeadSamples();
156 OS << "\n";
Diego Novilloc572e922014-10-30 18:00:06 +0000157
Diego Novilloef548d22015-11-19 15:33:08 +0000158 SampleSorter<LineLocation, SampleRecord> SortedSamples(S.getBodySamples());
159 for (const auto &I : SortedSamples.get()) {
160 LineLocation Loc = I->first;
161 const SampleRecord &Sample = I->second;
Diego Novilloaae1ed82015-10-08 19:40:37 +0000162 OS.indent(Indent + 1);
Diego Novilloc572e922014-10-30 18:00:06 +0000163 if (Loc.Discriminator == 0)
164 OS << Loc.LineOffset << ": ";
165 else
166 OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
167
168 OS << Sample.getSamples();
169
Wenlei He5adace32019-08-20 20:52:00 +0000170 for (const auto &J : Sample.getSortedCallTargets())
171 OS << " " << J.first << ":" << J.second;
Diego Novilloc572e922014-10-30 18:00:06 +0000172 OS << "\n";
173 }
174
Dehao Chen2c7ca9b2017-04-13 19:52:10 +0000175 SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples(
Diego Novilloef548d22015-11-19 15:33:08 +0000176 S.getCallsiteSamples());
Diego Novilloaae1ed82015-10-08 19:40:37 +0000177 Indent += 1;
Dehao Chen2c7ca9b2017-04-13 19:52:10 +0000178 for (const auto &I : SortedCallsiteSamples.get())
179 for (const auto &FS : I->second) {
180 LineLocation Loc = I->first;
181 const FunctionSamples &CalleeSamples = FS.second;
182 OS.indent(Indent);
183 if (Loc.Discriminator == 0)
184 OS << Loc.LineOffset << ": ";
185 else
186 OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
Wei Mibe907322019-08-23 19:05:30 +0000187 if (std::error_code EC = writeSample(CalleeSamples))
Dehao Chen2c7ca9b2017-04-13 19:52:10 +0000188 return EC;
189 }
Diego Novilloaae1ed82015-10-08 19:40:37 +0000190 Indent -= 1;
191
Diego Novillo760c5a82015-10-13 22:48:46 +0000192 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +0000193}
194
Diego Novillo760c5a82015-10-13 22:48:46 +0000195std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
196 const auto &ret = NameTable.find(FName);
197 if (ret == NameTable.end())
198 return sampleprof_error::truncated_name_table;
Nathan Slingerland51abea72015-12-10 17:21:42 +0000199 encodeULEB128(ret->second, *OutputStream);
Diego Novillo760c5a82015-10-13 22:48:46 +0000200 return sampleprof_error::success;
201}
Diego Novilloc572e922014-10-30 18:00:06 +0000202
Diego Novillo760c5a82015-10-13 22:48:46 +0000203void SampleProfileWriterBinary::addName(StringRef FName) {
Dehao Chen8d1c9832017-05-11 23:43:44 +0000204 NameTable.insert(std::make_pair(FName, 0));
Diego Novillo760c5a82015-10-13 22:48:46 +0000205}
206
207void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
208 // Add all the names in indirect call targets.
209 for (const auto &I : S.getBodySamples()) {
210 const SampleRecord &Sample = I.second;
211 for (const auto &J : Sample.getCallTargets())
212 addName(J.first());
213 }
214
215 // Recursively add all the names for inlined callsites.
Dehao Chen2c7ca9b2017-04-13 19:52:10 +0000216 for (const auto &J : S.getCallsiteSamples())
217 for (const auto &FS : J.second) {
218 const FunctionSamples &CalleeSamples = FS.second;
219 addName(CalleeSamples.getName());
220 addNames(CalleeSamples);
221 }
Diego Novillo760c5a82015-10-13 22:48:46 +0000222}
223
Wei Mia0c08572018-06-11 22:40:43 +0000224void SampleProfileWriterBinary::stablizeNameTable(std::set<StringRef> &V) {
225 // Sort the names to make NameTable deterministic.
226 for (const auto &I : NameTable)
227 V.insert(I.first);
228 int i = 0;
229 for (const StringRef &N : V)
230 NameTable[N] = i++;
231}
Nathan Slingerland51abea72015-12-10 17:21:42 +0000232
Wei Mibe907322019-08-23 19:05:30 +0000233std::error_code SampleProfileWriterBinary::writeNameTable() {
Wei Mia0c08572018-06-11 22:40:43 +0000234 auto &OS = *OutputStream;
235 std::set<StringRef> V;
236 stablizeNameTable(V);
237
238 // Write out the name table.
239 encodeULEB128(NameTable.size(), OS);
240 for (auto N : V) {
241 OS << N;
242 encodeULEB128(0, OS);
243 }
244 return sampleprof_error::success;
245}
246
Wei Mi6a143252018-09-14 20:52:59 +0000247std::error_code SampleProfileWriterCompactBinary::writeFuncOffsetTable() {
248 auto &OS = *OutputStream;
249
250 // Fill the slot remembered by TableOffset with the offset of FuncOffsetTable.
251 auto &OFS = static_cast<raw_fd_ostream &>(OS);
252 uint64_t FuncOffsetTableStart = OS.tell();
253 if (OFS.seek(TableOffset) == (uint64_t)-1)
254 return sampleprof_error::ostream_seek_unsupported;
255 support::endian::Writer Writer(*OutputStream, support::little);
256 Writer.write(FuncOffsetTableStart);
257 if (OFS.seek(FuncOffsetTableStart) == (uint64_t)-1)
258 return sampleprof_error::ostream_seek_unsupported;
259
260 // Write out the table size.
261 encodeULEB128(FuncOffsetTable.size(), OS);
262
263 // Write out FuncOffsetTable.
264 for (auto entry : FuncOffsetTable) {
265 writeNameIdx(entry.first);
266 encodeULEB128(entry.second, OS);
267 }
268 return sampleprof_error::success;
269}
270
Wei Mia0c08572018-06-11 22:40:43 +0000271std::error_code SampleProfileWriterCompactBinary::writeNameTable() {
272 auto &OS = *OutputStream;
273 std::set<StringRef> V;
274 stablizeNameTable(V);
275
276 // Write out the name table.
277 encodeULEB128(NameTable.size(), OS);
278 for (auto N : V) {
279 encodeULEB128(MD5Hash(N), OS);
280 }
281 return sampleprof_error::success;
282}
283
Wei Mibe907322019-08-23 19:05:30 +0000284std::error_code
285SampleProfileWriterBinary::writeMagicIdent(SampleProfileFormat Format) {
Wei Mia0c08572018-06-11 22:40:43 +0000286 auto &OS = *OutputStream;
Diego Novillo760c5a82015-10-13 22:48:46 +0000287 // Write file magic identifier.
Wei Mibe907322019-08-23 19:05:30 +0000288 encodeULEB128(SPMagic(Format), OS);
Wei Mia0c08572018-06-11 22:40:43 +0000289 encodeULEB128(SPVersion(), OS);
290 return sampleprof_error::success;
291}
292
293std::error_code SampleProfileWriterBinary::writeHeader(
294 const StringMap<FunctionSamples> &ProfileMap) {
Wei Mibe907322019-08-23 19:05:30 +0000295 writeMagicIdent(Format);
Diego Novillo760c5a82015-10-13 22:48:46 +0000296
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000297 computeSummary(ProfileMap);
298 if (auto EC = writeSummary())
299 return EC;
300
Diego Novillo760c5a82015-10-13 22:48:46 +0000301 // Generate the name table for all the functions referenced in the profile.
302 for (const auto &I : ProfileMap) {
303 addName(I.first());
304 addNames(I.second);
305 }
306
Wei Mia0c08572018-06-11 22:40:43 +0000307 writeNameTable();
Diego Novillo760c5a82015-10-13 22:48:46 +0000308 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +0000309}
310
Wei Mibe907322019-08-23 19:05:30 +0000311void SampleProfileWriterExtBinaryBase::allocSecHdrTable() {
312 support::endian::Writer Writer(*OutputStream, support::little);
313
314 Writer.write(static_cast<uint64_t>(SectionLayout.size()));
315 SecHdrTableOffset = OutputStream->tell();
316 for (uint32_t i = 0; i < SectionLayout.size(); i++) {
317 Writer.write(static_cast<uint64_t>(-1));
318 Writer.write(static_cast<uint64_t>(-1));
319 Writer.write(static_cast<uint64_t>(-1));
320 Writer.write(static_cast<uint64_t>(-1));
321 }
322}
323
324std::error_code SampleProfileWriterExtBinaryBase::writeSecHdrTable() {
325 auto &OFS = static_cast<raw_fd_ostream &>(*OutputStream);
326 uint64_t Saved = OutputStream->tell();
327
328 // Set OutputStream to the location saved in SecHdrTableOffset.
329 if (OFS.seek(SecHdrTableOffset) == (uint64_t)-1)
330 return sampleprof_error::ostream_seek_unsupported;
331 support::endian::Writer Writer(*OutputStream, support::little);
332
333 DenseMap<uint32_t, uint32_t> IndexMap;
334 for (uint32_t i = 0; i < SecHdrTable.size(); i++) {
335 IndexMap.insert({static_cast<uint32_t>(SecHdrTable[i].Type), i});
336 }
337
338 // Write the sections in the order specified in SectionLayout.
339 // That is the sections order Reader will see. Note that the
340 // sections order in which Reader expects to read may be different
341 // from the order in which Writer is able to write, so we need
342 // to adjust the order in SecHdrTable to be consistent with
343 // SectionLayout when we write SecHdrTable to the memory.
344 for (uint32_t i = 0; i < SectionLayout.size(); i++) {
345 uint32_t idx = IndexMap[static_cast<uint32_t>(SectionLayout[i])];
346 Writer.write(static_cast<uint64_t>(SecHdrTable[idx].Type));
347 Writer.write(static_cast<uint64_t>(SecHdrTable[idx].Flag));
348 Writer.write(static_cast<uint64_t>(SecHdrTable[idx].Offset));
349 Writer.write(static_cast<uint64_t>(SecHdrTable[idx].Size));
350 }
351
352 // Reset OutputStream.
353 if (OFS.seek(Saved) == (uint64_t)-1)
354 return sampleprof_error::ostream_seek_unsupported;
355
356 return sampleprof_error::success;
357}
358
359std::error_code SampleProfileWriterExtBinaryBase::writeHeader(
360 const StringMap<FunctionSamples> &ProfileMap) {
361 auto &OS = *OutputStream;
362 FileStart = OS.tell();
363 writeMagicIdent(Format);
364
365 initSectionLayout();
366 allocSecHdrTable();
367 return sampleprof_error::success;
368}
369
Wei Mi6a143252018-09-14 20:52:59 +0000370std::error_code SampleProfileWriterCompactBinary::writeHeader(
371 const StringMap<FunctionSamples> &ProfileMap) {
372 support::endian::Writer Writer(*OutputStream, support::little);
373 if (auto EC = SampleProfileWriterBinary::writeHeader(ProfileMap))
374 return EC;
375
376 // Reserve a slot for the offset of function offset table. The slot will
377 // be populated with the offset of FuncOffsetTable later.
378 TableOffset = OutputStream->tell();
379 Writer.write(static_cast<uint64_t>(-2));
380 return sampleprof_error::success;
381}
382
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000383std::error_code SampleProfileWriterBinary::writeSummary() {
384 auto &OS = *OutputStream;
Easwaran Raman7cefdb82016-05-19 21:53:28 +0000385 encodeULEB128(Summary->getTotalCount(), OS);
386 encodeULEB128(Summary->getMaxCount(), OS);
Easwaran Raman6f4903d2016-03-28 23:14:29 +0000387 encodeULEB128(Summary->getMaxFunctionCount(), OS);
Easwaran Raman7cefdb82016-05-19 21:53:28 +0000388 encodeULEB128(Summary->getNumCounts(), OS);
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000389 encodeULEB128(Summary->getNumFunctions(), OS);
390 std::vector<ProfileSummaryEntry> &Entries = Summary->getDetailedSummary();
391 encodeULEB128(Entries.size(), OS);
392 for (auto Entry : Entries) {
393 encodeULEB128(Entry.Cutoff, OS);
394 encodeULEB128(Entry.MinCount, OS);
395 encodeULEB128(Entry.NumCounts, OS);
396 }
397 return sampleprof_error::success;
398}
Dehao Chen57d1dda2016-03-03 18:09:32 +0000399std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
Nathan Slingerland51abea72015-12-10 17:21:42 +0000400 auto &OS = *OutputStream;
401
Dehao Chen57d1dda2016-03-03 18:09:32 +0000402 if (std::error_code EC = writeNameIdx(S.getName()))
Diego Novillo760c5a82015-10-13 22:48:46 +0000403 return EC;
404
Diego Novilloc572e922014-10-30 18:00:06 +0000405 encodeULEB128(S.getTotalSamples(), OS);
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000406
407 // Emit all the body samples.
Diego Novillob93483d2015-10-16 18:54:35 +0000408 encodeULEB128(S.getBodySamples().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +0000409 for (const auto &I : S.getBodySamples()) {
410 LineLocation Loc = I.first;
411 const SampleRecord &Sample = I.second;
Diego Novilloc572e922014-10-30 18:00:06 +0000412 encodeULEB128(Loc.LineOffset, OS);
413 encodeULEB128(Loc.Discriminator, OS);
414 encodeULEB128(Sample.getSamples(), OS);
415 encodeULEB128(Sample.getCallTargets().size(), OS);
Wenlei He5adace32019-08-20 20:52:00 +0000416 for (const auto &J : Sample.getSortedCallTargets()) {
417 StringRef Callee = J.first;
Diego Novillo38be3332015-10-15 16:36:21 +0000418 uint64_t CalleeSamples = J.second;
Diego Novillo760c5a82015-10-13 22:48:46 +0000419 if (std::error_code EC = writeNameIdx(Callee))
420 return EC;
Diego Novilloc572e922014-10-30 18:00:06 +0000421 encodeULEB128(CalleeSamples, OS);
422 }
423 }
424
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000425 // Recursively emit all the callsite samples.
Dehao Chen2c27daf2017-08-03 00:09:18 +0000426 uint64_t NumCallsites = 0;
427 for (const auto &J : S.getCallsiteSamples())
428 NumCallsites += J.second.size();
429 encodeULEB128(NumCallsites, OS);
Dehao Chen2c7ca9b2017-04-13 19:52:10 +0000430 for (const auto &J : S.getCallsiteSamples())
431 for (const auto &FS : J.second) {
432 LineLocation Loc = J.first;
433 const FunctionSamples &CalleeSamples = FS.second;
434 encodeULEB128(Loc.LineOffset, OS);
435 encodeULEB128(Loc.Discriminator, OS);
436 if (std::error_code EC = writeBody(CalleeSamples))
437 return EC;
438 }
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000439
Diego Novillo760c5a82015-10-13 22:48:46 +0000440 return sampleprof_error::success;
Diego Novilloc572e922014-10-30 18:00:06 +0000441}
Diego Novillod5336ae2014-11-01 00:56:55 +0000442
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000443/// Write samples of a top-level function to a binary file.
Diego Novillob93483d2015-10-16 18:54:35 +0000444///
445/// \returns true if the samples were written successfully, false otherwise.
Wei Mibe907322019-08-23 19:05:30 +0000446std::error_code
447SampleProfileWriterBinary::writeSample(const FunctionSamples &S) {
Nathan Slingerland51abea72015-12-10 17:21:42 +0000448 encodeULEB128(S.getHeadSamples(), *OutputStream);
Dehao Chen57d1dda2016-03-03 18:09:32 +0000449 return writeBody(S);
Diego Novillob93483d2015-10-16 18:54:35 +0000450}
451
Wei Mi6a143252018-09-14 20:52:59 +0000452std::error_code
Wei Mibe907322019-08-23 19:05:30 +0000453SampleProfileWriterCompactBinary::writeSample(const FunctionSamples &S) {
Wei Mi6a143252018-09-14 20:52:59 +0000454 uint64_t Offset = OutputStream->tell();
455 StringRef Name = S.getName();
456 FuncOffsetTable[Name] = Offset;
457 encodeULEB128(S.getHeadSamples(), *OutputStream);
458 return writeBody(S);
459}
460
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000461/// Create a sample profile file writer based on the specified format.
Diego Novillod5336ae2014-11-01 00:56:55 +0000462///
463/// \param Filename The file to create.
464///
Diego Novillod5336ae2014-11-01 00:56:55 +0000465/// \param Format Encoding format for the profile file.
466///
467/// \returns an error code indicating the status of the created writer.
Diego Novillofcd55602014-11-03 00:51:45 +0000468ErrorOr<std::unique_ptr<SampleProfileWriter>>
469SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
Diego Novillod5336ae2014-11-01 00:56:55 +0000470 std::error_code EC;
Nathan Slingerland51abea72015-12-10 17:21:42 +0000471 std::unique_ptr<raw_ostream> OS;
Wei Mibe907322019-08-23 19:05:30 +0000472 if (Format == SPF_Binary || Format == SPF_Ext_Binary ||
473 Format == SPF_Compact_Binary)
Fangrui Songd9b948b2019-08-05 05:43:48 +0000474 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::OF_None));
Nathan Slingerland51abea72015-12-10 17:21:42 +0000475 else
Fangrui Songd9b948b2019-08-05 05:43:48 +0000476 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::OF_Text));
Nathan Slingerland51abea72015-12-10 17:21:42 +0000477 if (EC)
478 return EC;
479
480 return create(OS, Format);
481}
482
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000483/// Create a sample profile stream writer based on the specified format.
Nathan Slingerland51abea72015-12-10 17:21:42 +0000484///
485/// \param OS The output stream to store the profile data to.
486///
Nathan Slingerland51abea72015-12-10 17:21:42 +0000487/// \param Format Encoding format for the profile file.
488///
489/// \returns an error code indicating the status of the created writer.
490ErrorOr<std::unique_ptr<SampleProfileWriter>>
491SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
492 SampleProfileFormat Format) {
493 std::error_code EC;
Diego Novillofcd55602014-11-03 00:51:45 +0000494 std::unique_ptr<SampleProfileWriter> Writer;
Diego Novillod5336ae2014-11-01 00:56:55 +0000495
Wei Mid9be2c72018-06-12 05:53:49 +0000496 if (Format == SPF_Binary)
Wei Mia0c08572018-06-11 22:40:43 +0000497 Writer.reset(new SampleProfileWriterRawBinary(OS));
Wei Mibe907322019-08-23 19:05:30 +0000498 else if (Format == SPF_Ext_Binary)
499 Writer.reset(new SampleProfileWriterExtBinary(OS));
Wei Mia0c08572018-06-11 22:40:43 +0000500 else if (Format == SPF_Compact_Binary)
501 Writer.reset(new SampleProfileWriterCompactBinary(OS));
Diego Novillod5336ae2014-11-01 00:56:55 +0000502 else if (Format == SPF_Text)
Nathan Slingerland51abea72015-12-10 17:21:42 +0000503 Writer.reset(new SampleProfileWriterText(OS));
Diego Novillo760c5a82015-10-13 22:48:46 +0000504 else if (Format == SPF_GCC)
505 EC = sampleprof_error::unsupported_writing_format;
Diego Novillod5336ae2014-11-01 00:56:55 +0000506 else
507 EC = sampleprof_error::unrecognized_format;
508
Diego Novillofcd55602014-11-03 00:51:45 +0000509 if (EC)
510 return EC;
511
Wei Mibe907322019-08-23 19:05:30 +0000512 Writer->Format = Format;
Diego Novillofcd55602014-11-03 00:51:45 +0000513 return std::move(Writer);
Diego Novillod5336ae2014-11-01 00:56:55 +0000514}
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000515
516void SampleProfileWriter::computeSummary(
517 const StringMap<FunctionSamples> &ProfileMap) {
Easwaran Ramane5a17e32016-05-19 21:07:12 +0000518 SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000519 for (const auto &I : ProfileMap) {
520 const FunctionSamples &Profile = I.second;
Easwaran Ramane5a17e32016-05-19 21:07:12 +0000521 Builder.addRecord(Profile);
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000522 }
Benjamin Kramer38de59e2016-05-20 09:18:37 +0000523 Summary = Builder.getSummary();
Easwaran Raman40ee23d2016-02-19 03:15:33 +0000524}