1*0a6a1f1dSLionel Sambuc //===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc // The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // This file implements the class that writes LLVM sample profiles. It
11*0a6a1f1dSLionel Sambuc // supports two file formats: text and binary. The textual representation
12*0a6a1f1dSLionel Sambuc // is useful for debugging and testing purposes. The binary representation
13*0a6a1f1dSLionel Sambuc // is more compact, resulting in smaller file sizes. However, they can
14*0a6a1f1dSLionel Sambuc // both be used interchangeably.
15*0a6a1f1dSLionel Sambuc //
16*0a6a1f1dSLionel Sambuc // See lib/ProfileData/SampleProfReader.cpp for documentation on each of the
17*0a6a1f1dSLionel Sambuc // supported formats.
18*0a6a1f1dSLionel Sambuc //
19*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
20*0a6a1f1dSLionel Sambuc
21*0a6a1f1dSLionel Sambuc #include "llvm/ProfileData/SampleProfWriter.h"
22*0a6a1f1dSLionel Sambuc #include "llvm/Support/Debug.h"
23*0a6a1f1dSLionel Sambuc #include "llvm/Support/ErrorOr.h"
24*0a6a1f1dSLionel Sambuc #include "llvm/Support/LEB128.h"
25*0a6a1f1dSLionel Sambuc #include "llvm/Support/LineIterator.h"
26*0a6a1f1dSLionel Sambuc #include "llvm/Support/MemoryBuffer.h"
27*0a6a1f1dSLionel Sambuc #include "llvm/Support/Regex.h"
28*0a6a1f1dSLionel Sambuc
29*0a6a1f1dSLionel Sambuc using namespace llvm::sampleprof;
30*0a6a1f1dSLionel Sambuc using namespace llvm;
31*0a6a1f1dSLionel Sambuc
32*0a6a1f1dSLionel Sambuc /// \brief Write samples to a text file.
write(StringRef FName,const FunctionSamples & S)33*0a6a1f1dSLionel Sambuc bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) {
34*0a6a1f1dSLionel Sambuc if (S.empty())
35*0a6a1f1dSLionel Sambuc return true;
36*0a6a1f1dSLionel Sambuc
37*0a6a1f1dSLionel Sambuc OS << FName << ":" << S.getTotalSamples() << ":" << S.getHeadSamples()
38*0a6a1f1dSLionel Sambuc << "\n";
39*0a6a1f1dSLionel Sambuc
40*0a6a1f1dSLionel Sambuc for (const auto &I : S.getBodySamples()) {
41*0a6a1f1dSLionel Sambuc LineLocation Loc = I.first;
42*0a6a1f1dSLionel Sambuc const SampleRecord &Sample = I.second;
43*0a6a1f1dSLionel Sambuc if (Loc.Discriminator == 0)
44*0a6a1f1dSLionel Sambuc OS << Loc.LineOffset << ": ";
45*0a6a1f1dSLionel Sambuc else
46*0a6a1f1dSLionel Sambuc OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
47*0a6a1f1dSLionel Sambuc
48*0a6a1f1dSLionel Sambuc OS << Sample.getSamples();
49*0a6a1f1dSLionel Sambuc
50*0a6a1f1dSLionel Sambuc for (const auto &J : Sample.getCallTargets())
51*0a6a1f1dSLionel Sambuc OS << " " << J.first() << ":" << J.second;
52*0a6a1f1dSLionel Sambuc OS << "\n";
53*0a6a1f1dSLionel Sambuc }
54*0a6a1f1dSLionel Sambuc
55*0a6a1f1dSLionel Sambuc return true;
56*0a6a1f1dSLionel Sambuc }
57*0a6a1f1dSLionel Sambuc
SampleProfileWriterBinary(StringRef F,std::error_code & EC)58*0a6a1f1dSLionel Sambuc SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F,
59*0a6a1f1dSLionel Sambuc std::error_code &EC)
60*0a6a1f1dSLionel Sambuc : SampleProfileWriter(F, EC, sys::fs::F_None) {
61*0a6a1f1dSLionel Sambuc if (EC)
62*0a6a1f1dSLionel Sambuc return;
63*0a6a1f1dSLionel Sambuc
64*0a6a1f1dSLionel Sambuc // Write the file header.
65*0a6a1f1dSLionel Sambuc encodeULEB128(SPMagic(), OS);
66*0a6a1f1dSLionel Sambuc encodeULEB128(SPVersion(), OS);
67*0a6a1f1dSLionel Sambuc }
68*0a6a1f1dSLionel Sambuc
69*0a6a1f1dSLionel Sambuc /// \brief Write samples to a binary file.
70*0a6a1f1dSLionel Sambuc ///
71*0a6a1f1dSLionel Sambuc /// \returns true if the samples were written successfully, false otherwise.
write(StringRef FName,const FunctionSamples & S)72*0a6a1f1dSLionel Sambuc bool SampleProfileWriterBinary::write(StringRef FName,
73*0a6a1f1dSLionel Sambuc const FunctionSamples &S) {
74*0a6a1f1dSLionel Sambuc if (S.empty())
75*0a6a1f1dSLionel Sambuc return true;
76*0a6a1f1dSLionel Sambuc
77*0a6a1f1dSLionel Sambuc OS << FName;
78*0a6a1f1dSLionel Sambuc encodeULEB128(0, OS);
79*0a6a1f1dSLionel Sambuc encodeULEB128(S.getTotalSamples(), OS);
80*0a6a1f1dSLionel Sambuc encodeULEB128(S.getHeadSamples(), OS);
81*0a6a1f1dSLionel Sambuc encodeULEB128(S.getBodySamples().size(), OS);
82*0a6a1f1dSLionel Sambuc for (const auto &I : S.getBodySamples()) {
83*0a6a1f1dSLionel Sambuc LineLocation Loc = I.first;
84*0a6a1f1dSLionel Sambuc const SampleRecord &Sample = I.second;
85*0a6a1f1dSLionel Sambuc encodeULEB128(Loc.LineOffset, OS);
86*0a6a1f1dSLionel Sambuc encodeULEB128(Loc.Discriminator, OS);
87*0a6a1f1dSLionel Sambuc encodeULEB128(Sample.getSamples(), OS);
88*0a6a1f1dSLionel Sambuc encodeULEB128(Sample.getCallTargets().size(), OS);
89*0a6a1f1dSLionel Sambuc for (const auto &J : Sample.getCallTargets()) {
90*0a6a1f1dSLionel Sambuc std::string Callee = J.first();
91*0a6a1f1dSLionel Sambuc unsigned CalleeSamples = J.second;
92*0a6a1f1dSLionel Sambuc OS << Callee;
93*0a6a1f1dSLionel Sambuc encodeULEB128(0, OS);
94*0a6a1f1dSLionel Sambuc encodeULEB128(CalleeSamples, OS);
95*0a6a1f1dSLionel Sambuc }
96*0a6a1f1dSLionel Sambuc }
97*0a6a1f1dSLionel Sambuc
98*0a6a1f1dSLionel Sambuc return true;
99*0a6a1f1dSLionel Sambuc }
100*0a6a1f1dSLionel Sambuc
101*0a6a1f1dSLionel Sambuc /// \brief Create a sample profile writer based on the specified format.
102*0a6a1f1dSLionel Sambuc ///
103*0a6a1f1dSLionel Sambuc /// \param Filename The file to create.
104*0a6a1f1dSLionel Sambuc ///
105*0a6a1f1dSLionel Sambuc /// \param Writer The writer to instantiate according to the specified format.
106*0a6a1f1dSLionel Sambuc ///
107*0a6a1f1dSLionel Sambuc /// \param Format Encoding format for the profile file.
108*0a6a1f1dSLionel Sambuc ///
109*0a6a1f1dSLionel Sambuc /// \returns an error code indicating the status of the created writer.
110*0a6a1f1dSLionel Sambuc ErrorOr<std::unique_ptr<SampleProfileWriter>>
create(StringRef Filename,SampleProfileFormat Format)111*0a6a1f1dSLionel Sambuc SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
112*0a6a1f1dSLionel Sambuc std::error_code EC;
113*0a6a1f1dSLionel Sambuc std::unique_ptr<SampleProfileWriter> Writer;
114*0a6a1f1dSLionel Sambuc
115*0a6a1f1dSLionel Sambuc if (Format == SPF_Binary)
116*0a6a1f1dSLionel Sambuc Writer.reset(new SampleProfileWriterBinary(Filename, EC));
117*0a6a1f1dSLionel Sambuc else if (Format == SPF_Text)
118*0a6a1f1dSLionel Sambuc Writer.reset(new SampleProfileWriterText(Filename, EC));
119*0a6a1f1dSLionel Sambuc else
120*0a6a1f1dSLionel Sambuc EC = sampleprof_error::unrecognized_format;
121*0a6a1f1dSLionel Sambuc
122*0a6a1f1dSLionel Sambuc if (EC)
123*0a6a1f1dSLionel Sambuc return EC;
124*0a6a1f1dSLionel Sambuc
125*0a6a1f1dSLionel Sambuc return std::move(Writer);
126*0a6a1f1dSLionel Sambuc }
127