blob: 6be884b13e0e5511df261923ca680c7cacc998e0 [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) {
Diego Novillod5336ae2014-11-01 00:56:55 +000087 OS << FName;
Diego Novilloc572e922014-10-30 18:00:06 +000088 encodeULEB128(0, OS);
89 encodeULEB128(S.getTotalSamples(), OS);
90 encodeULEB128(S.getHeadSamples(), OS);
91 encodeULEB128(S.getBodySamples().size(), OS);
Diego Novilloa7f1e8e2015-10-09 17:54:24 +000092
93 // Emit all the body samples.
Diego Novillod5336ae2014-11-01 00:56:55 +000094 for (const auto &I : S.getBodySamples()) {
95 LineLocation Loc = I.first;
96 const SampleRecord &Sample = I.second;
Diego Novilloc572e922014-10-30 18:00:06 +000097 encodeULEB128(Loc.LineOffset, OS);
98 encodeULEB128(Loc.Discriminator, OS);
99 encodeULEB128(Sample.getSamples(), OS);
100 encodeULEB128(Sample.getCallTargets().size(), OS);
Diego Novillod5336ae2014-11-01 00:56:55 +0000101 for (const auto &J : Sample.getCallTargets()) {
102 std::string Callee = J.first();
103 unsigned CalleeSamples = J.second;
Diego Novilloc572e922014-10-30 18:00:06 +0000104 OS << Callee;
105 encodeULEB128(0, OS);
106 encodeULEB128(CalleeSamples, OS);
107 }
108 }
109
Diego Novilloa7f1e8e2015-10-09 17:54:24 +0000110 // Recursively emit all the callsite samples.
111 encodeULEB128(S.getCallsiteSamples().size(), OS);
112 for (const auto &J : S.getCallsiteSamples()) {
113 CallsiteLocation Loc = J.first;
114 const FunctionSamples &CalleeSamples = J.second;
115 encodeULEB128(Loc.LineOffset, OS);
116 encodeULEB128(Loc.Discriminator, OS);
117 write(Loc.CalleeName, CalleeSamples);
118 }
119
Diego Novilloc572e922014-10-30 18:00:06 +0000120 return true;
121}
Diego Novillod5336ae2014-11-01 00:56:55 +0000122
123/// \brief Create a sample profile writer based on the specified format.
124///
125/// \param Filename The file to create.
126///
127/// \param Writer The writer to instantiate according to the specified format.
128///
129/// \param Format Encoding format for the profile file.
130///
131/// \returns an error code indicating the status of the created writer.
Diego Novillofcd55602014-11-03 00:51:45 +0000132ErrorOr<std::unique_ptr<SampleProfileWriter>>
133SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
Diego Novillod5336ae2014-11-01 00:56:55 +0000134 std::error_code EC;
Diego Novillofcd55602014-11-03 00:51:45 +0000135 std::unique_ptr<SampleProfileWriter> Writer;
Diego Novillod5336ae2014-11-01 00:56:55 +0000136
137 if (Format == SPF_Binary)
138 Writer.reset(new SampleProfileWriterBinary(Filename, EC));
139 else if (Format == SPF_Text)
140 Writer.reset(new SampleProfileWriterText(Filename, EC));
141 else
142 EC = sampleprof_error::unrecognized_format;
143
Diego Novillofcd55602014-11-03 00:51:45 +0000144 if (EC)
145 return EC;
146
147 return std::move(Writer);
Diego Novillod5336ae2014-11-01 00:56:55 +0000148}