blob: e6a4d7d132103aba5c527203e6ea399728851411 [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 Novillod5336ae2014-11-01 00:56:55 +000033bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) {
Diego Novilloaae1ed82015-10-08 19:40:37 +000034 OS << FName << ":" << S.getTotalSamples();
35 if (Indent == 0)
36 OS << ":" << S.getHeadSamples();
37 OS << "\n";
Diego Novilloc572e922014-10-30 18:00:06 +000038
Diego Novillod5336ae2014-11-01 00:56:55 +000039 for (const auto &I : S.getBodySamples()) {
40 LineLocation Loc = I.first;
41 const SampleRecord &Sample = I.second;
Diego Novilloaae1ed82015-10-08 19:40:37 +000042 OS.indent(Indent + 1);
Diego Novilloc572e922014-10-30 18:00:06 +000043 if (Loc.Discriminator == 0)
44 OS << Loc.LineOffset << ": ";
45 else
46 OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
47
48 OS << Sample.getSamples();
49
Diego Novillod5336ae2014-11-01 00:56:55 +000050 for (const auto &J : Sample.getCallTargets())
51 OS << " " << J.first() << ":" << J.second;
Diego Novilloc572e922014-10-30 18:00:06 +000052 OS << "\n";
53 }
54
Diego Novilloaae1ed82015-10-08 19:40:37 +000055 Indent += 1;
56 for (const auto &I : S.getCallsiteSamples()) {
57 CallsiteLocation Loc = I.first;
58 const FunctionSamples &CalleeSamples = I.second;
59 OS.indent(Indent);
60 if (Loc.Discriminator == 0)
61 OS << Loc.LineOffset << ": ";
62 else
63 OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
64 write(Loc.CalleeName, CalleeSamples);
65 }
66 Indent -= 1;
67
Diego Novilloc572e922014-10-30 18:00:06 +000068 return true;
69}
70
71SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F,
72 std::error_code &EC)
73 : SampleProfileWriter(F, EC, sys::fs::F_None) {
74 if (EC)
75 return;
76
77 // Write the file header.
78 encodeULEB128(SPMagic(), OS);
79 encodeULEB128(SPVersion(), OS);
80}
81
82/// \brief Write samples to a binary file.
83///
84/// \returns true if the samples were written successfully, false otherwise.
Diego Novillod5336ae2014-11-01 00:56:55 +000085bool SampleProfileWriterBinary::write(StringRef FName,
Diego Novilloc572e922014-10-30 18:00:06 +000086 const FunctionSamples &S) {
87 if (S.empty())
88 return true;
89
Diego Novillod5336ae2014-11-01 00:56:55 +000090 OS << FName;
Diego Novilloc572e922014-10-30 18:00:06 +000091 encodeULEB128(0, OS);
92 encodeULEB128(S.getTotalSamples(), OS);
93 encodeULEB128(S.getHeadSamples(), OS);
94 encodeULEB128(S.getBodySamples().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +000095 for (const auto &I : S.getBodySamples()) {
96 LineLocation Loc = I.first;
97 const SampleRecord &Sample = I.second;
Diego Novilloc572e922014-10-30 18:00:06 +000098 encodeULEB128(Loc.LineOffset, OS);
99 encodeULEB128(Loc.Discriminator, OS);
100 encodeULEB128(Sample.getSamples(), OS);
101 encodeULEB128(Sample.getCallTargets().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +0000102 for (const auto &J : Sample.getCallTargets()) {
103 std::string Callee = J.first();
104 unsigned CalleeSamples = J.second;
Diego Novilloc572e922014-10-30 18:00:06 +0000105 OS << Callee;
106 encodeULEB128(0, OS);
107 encodeULEB128(CalleeSamples, OS);
108 }
109 }
110
111 return true;
112}
Diego Novillod5336ae2014-11-01 00:56:55 +0000113
114/// \brief Create a sample profile writer based on the specified format.
115///
116/// \param Filename The file to create.
117///
118/// \param Writer The writer to instantiate according to the specified format.
119///
120/// \param Format Encoding format for the profile file.
121///
122/// \returns an error code indicating the status of the created writer.
Diego Novillofcd55602014-11-03 00:51:45 +0000123ErrorOr<std::unique_ptr<SampleProfileWriter>>
124SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
Diego Novillod5336ae2014-11-01 00:56:55 +0000125 std::error_code EC;
Diego Novillofcd55602014-11-03 00:51:45 +0000126 std::unique_ptr<SampleProfileWriter> Writer;
Diego Novillod5336ae2014-11-01 00:56:55 +0000127
128 if (Format == SPF_Binary)
129 Writer.reset(new SampleProfileWriterBinary(Filename, EC));
130 else if (Format == SPF_Text)
131 Writer.reset(new SampleProfileWriterText(Filename, EC));
132 else
133 EC = sampleprof_error::unrecognized_format;
134
Diego Novillofcd55602014-11-03 00:51:45 +0000135 if (EC)
136 return EC;
137
138 return std::move(Writer);
Diego Novillod5336ae2014-11-01 00:56:55 +0000139}