xref: /aosp_15_r20/external/llvm/lib/ProfileData/SampleProfReader.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- SampleProfReader.cpp - Read LLVM sample profile data ---------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                      The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the class that reads LLVM sample profiles. It
11*9880d681SAndroid Build Coastguard Worker // supports three file formats: text, binary and gcov.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker // The textual representation is useful for debugging and testing purposes. The
14*9880d681SAndroid Build Coastguard Worker // binary representation is more compact, resulting in smaller file sizes.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker // The gcov encoding is the one generated by GCC's AutoFDO profile creation
17*9880d681SAndroid Build Coastguard Worker // tool (https://github.com/google/autofdo)
18*9880d681SAndroid Build Coastguard Worker //
19*9880d681SAndroid Build Coastguard Worker // All three encodings can be used interchangeably as an input sample profile.
20*9880d681SAndroid Build Coastguard Worker //
21*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker #include "llvm/ProfileData/SampleProfReader.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorOr.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LEB128.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LineIterator.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker using namespace llvm::sampleprof;
33*9880d681SAndroid Build Coastguard Worker using namespace llvm;
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker /// \brief Dump the function profile for \p FName.
36*9880d681SAndroid Build Coastguard Worker ///
37*9880d681SAndroid Build Coastguard Worker /// \param FName Name of the function to print.
38*9880d681SAndroid Build Coastguard Worker /// \param OS Stream to emit the output to.
dumpFunctionProfile(StringRef FName,raw_ostream & OS)39*9880d681SAndroid Build Coastguard Worker void SampleProfileReader::dumpFunctionProfile(StringRef FName,
40*9880d681SAndroid Build Coastguard Worker                                               raw_ostream &OS) {
41*9880d681SAndroid Build Coastguard Worker   OS << "Function: " << FName << ": " << Profiles[FName];
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker /// \brief Dump all the function profiles found on stream \p OS.
dump(raw_ostream & OS)45*9880d681SAndroid Build Coastguard Worker void SampleProfileReader::dump(raw_ostream &OS) {
46*9880d681SAndroid Build Coastguard Worker   for (const auto &I : Profiles)
47*9880d681SAndroid Build Coastguard Worker     dumpFunctionProfile(I.getKey(), OS);
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker /// \brief Parse \p Input as function head.
51*9880d681SAndroid Build Coastguard Worker ///
52*9880d681SAndroid Build Coastguard Worker /// Parse one line of \p Input, and update function name in \p FName,
53*9880d681SAndroid Build Coastguard Worker /// function's total sample count in \p NumSamples, function's entry
54*9880d681SAndroid Build Coastguard Worker /// count in \p NumHeadSamples.
55*9880d681SAndroid Build Coastguard Worker ///
56*9880d681SAndroid Build Coastguard Worker /// \returns true if parsing is successful.
ParseHead(const StringRef & Input,StringRef & FName,uint64_t & NumSamples,uint64_t & NumHeadSamples)57*9880d681SAndroid Build Coastguard Worker static bool ParseHead(const StringRef &Input, StringRef &FName,
58*9880d681SAndroid Build Coastguard Worker                       uint64_t &NumSamples, uint64_t &NumHeadSamples) {
59*9880d681SAndroid Build Coastguard Worker   if (Input[0] == ' ')
60*9880d681SAndroid Build Coastguard Worker     return false;
61*9880d681SAndroid Build Coastguard Worker   size_t n2 = Input.rfind(':');
62*9880d681SAndroid Build Coastguard Worker   size_t n1 = Input.rfind(':', n2 - 1);
63*9880d681SAndroid Build Coastguard Worker   FName = Input.substr(0, n1);
64*9880d681SAndroid Build Coastguard Worker   if (Input.substr(n1 + 1, n2 - n1 - 1).getAsInteger(10, NumSamples))
65*9880d681SAndroid Build Coastguard Worker     return false;
66*9880d681SAndroid Build Coastguard Worker   if (Input.substr(n2 + 1).getAsInteger(10, NumHeadSamples))
67*9880d681SAndroid Build Coastguard Worker     return false;
68*9880d681SAndroid Build Coastguard Worker   return true;
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker /// \brief Returns true if line offset \p L is legal (only has 16 bits).
isOffsetLegal(unsigned L)72*9880d681SAndroid Build Coastguard Worker static bool isOffsetLegal(unsigned L) { return (L & 0xffff) == L; }
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker /// \brief Parse \p Input as line sample.
75*9880d681SAndroid Build Coastguard Worker ///
76*9880d681SAndroid Build Coastguard Worker /// \param Input input line.
77*9880d681SAndroid Build Coastguard Worker /// \param IsCallsite true if the line represents an inlined callsite.
78*9880d681SAndroid Build Coastguard Worker /// \param Depth the depth of the inline stack.
79*9880d681SAndroid Build Coastguard Worker /// \param NumSamples total samples of the line/inlined callsite.
80*9880d681SAndroid Build Coastguard Worker /// \param LineOffset line offset to the start of the function.
81*9880d681SAndroid Build Coastguard Worker /// \param Discriminator discriminator of the line.
82*9880d681SAndroid Build Coastguard Worker /// \param TargetCountMap map from indirect call target to count.
83*9880d681SAndroid Build Coastguard Worker ///
84*9880d681SAndroid Build Coastguard Worker /// returns true if parsing is successful.
ParseLine(const StringRef & Input,bool & IsCallsite,uint32_t & Depth,uint64_t & NumSamples,uint32_t & LineOffset,uint32_t & Discriminator,StringRef & CalleeName,DenseMap<StringRef,uint64_t> & TargetCountMap)85*9880d681SAndroid Build Coastguard Worker static bool ParseLine(const StringRef &Input, bool &IsCallsite, uint32_t &Depth,
86*9880d681SAndroid Build Coastguard Worker                       uint64_t &NumSamples, uint32_t &LineOffset,
87*9880d681SAndroid Build Coastguard Worker                       uint32_t &Discriminator, StringRef &CalleeName,
88*9880d681SAndroid Build Coastguard Worker                       DenseMap<StringRef, uint64_t> &TargetCountMap) {
89*9880d681SAndroid Build Coastguard Worker   for (Depth = 0; Input[Depth] == ' '; Depth++)
90*9880d681SAndroid Build Coastguard Worker     ;
91*9880d681SAndroid Build Coastguard Worker   if (Depth == 0)
92*9880d681SAndroid Build Coastguard Worker     return false;
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker   size_t n1 = Input.find(':');
95*9880d681SAndroid Build Coastguard Worker   StringRef Loc = Input.substr(Depth, n1 - Depth);
96*9880d681SAndroid Build Coastguard Worker   size_t n2 = Loc.find('.');
97*9880d681SAndroid Build Coastguard Worker   if (n2 == StringRef::npos) {
98*9880d681SAndroid Build Coastguard Worker     if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset))
99*9880d681SAndroid Build Coastguard Worker       return false;
100*9880d681SAndroid Build Coastguard Worker     Discriminator = 0;
101*9880d681SAndroid Build Coastguard Worker   } else {
102*9880d681SAndroid Build Coastguard Worker     if (Loc.substr(0, n2).getAsInteger(10, LineOffset))
103*9880d681SAndroid Build Coastguard Worker       return false;
104*9880d681SAndroid Build Coastguard Worker     if (Loc.substr(n2 + 1).getAsInteger(10, Discriminator))
105*9880d681SAndroid Build Coastguard Worker       return false;
106*9880d681SAndroid Build Coastguard Worker   }
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker   StringRef Rest = Input.substr(n1 + 2);
109*9880d681SAndroid Build Coastguard Worker   if (Rest[0] >= '0' && Rest[0] <= '9') {
110*9880d681SAndroid Build Coastguard Worker     IsCallsite = false;
111*9880d681SAndroid Build Coastguard Worker     size_t n3 = Rest.find(' ');
112*9880d681SAndroid Build Coastguard Worker     if (n3 == StringRef::npos) {
113*9880d681SAndroid Build Coastguard Worker       if (Rest.getAsInteger(10, NumSamples))
114*9880d681SAndroid Build Coastguard Worker         return false;
115*9880d681SAndroid Build Coastguard Worker     } else {
116*9880d681SAndroid Build Coastguard Worker       if (Rest.substr(0, n3).getAsInteger(10, NumSamples))
117*9880d681SAndroid Build Coastguard Worker         return false;
118*9880d681SAndroid Build Coastguard Worker     }
119*9880d681SAndroid Build Coastguard Worker     while (n3 != StringRef::npos) {
120*9880d681SAndroid Build Coastguard Worker       n3 += Rest.substr(n3).find_first_not_of(' ');
121*9880d681SAndroid Build Coastguard Worker       Rest = Rest.substr(n3);
122*9880d681SAndroid Build Coastguard Worker       n3 = Rest.find(' ');
123*9880d681SAndroid Build Coastguard Worker       StringRef pair = Rest;
124*9880d681SAndroid Build Coastguard Worker       if (n3 != StringRef::npos) {
125*9880d681SAndroid Build Coastguard Worker         pair = Rest.substr(0, n3);
126*9880d681SAndroid Build Coastguard Worker       }
127*9880d681SAndroid Build Coastguard Worker       size_t n4 = pair.find(':');
128*9880d681SAndroid Build Coastguard Worker       uint64_t count;
129*9880d681SAndroid Build Coastguard Worker       if (pair.substr(n4 + 1).getAsInteger(10, count))
130*9880d681SAndroid Build Coastguard Worker         return false;
131*9880d681SAndroid Build Coastguard Worker       TargetCountMap[pair.substr(0, n4)] = count;
132*9880d681SAndroid Build Coastguard Worker     }
133*9880d681SAndroid Build Coastguard Worker   } else {
134*9880d681SAndroid Build Coastguard Worker     IsCallsite = true;
135*9880d681SAndroid Build Coastguard Worker     size_t n3 = Rest.find_last_of(':');
136*9880d681SAndroid Build Coastguard Worker     CalleeName = Rest.substr(0, n3);
137*9880d681SAndroid Build Coastguard Worker     if (Rest.substr(n3 + 1).getAsInteger(10, NumSamples))
138*9880d681SAndroid Build Coastguard Worker       return false;
139*9880d681SAndroid Build Coastguard Worker   }
140*9880d681SAndroid Build Coastguard Worker   return true;
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker /// \brief Load samples from a text file.
144*9880d681SAndroid Build Coastguard Worker ///
145*9880d681SAndroid Build Coastguard Worker /// See the documentation at the top of the file for an explanation of
146*9880d681SAndroid Build Coastguard Worker /// the expected format.
147*9880d681SAndroid Build Coastguard Worker ///
148*9880d681SAndroid Build Coastguard Worker /// \returns true if the file was loaded successfully, false otherwise.
read()149*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderText::read() {
150*9880d681SAndroid Build Coastguard Worker   line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
151*9880d681SAndroid Build Coastguard Worker   sampleprof_error Result = sampleprof_error::success;
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   InlineCallStack InlineStack;
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   for (; !LineIt.is_at_eof(); ++LineIt) {
156*9880d681SAndroid Build Coastguard Worker     if ((*LineIt)[(*LineIt).find_first_not_of(' ')] == '#')
157*9880d681SAndroid Build Coastguard Worker       continue;
158*9880d681SAndroid Build Coastguard Worker     // Read the header of each function.
159*9880d681SAndroid Build Coastguard Worker     //
160*9880d681SAndroid Build Coastguard Worker     // Note that for function identifiers we are actually expecting
161*9880d681SAndroid Build Coastguard Worker     // mangled names, but we may not always get them. This happens when
162*9880d681SAndroid Build Coastguard Worker     // the compiler decides not to emit the function (e.g., it was inlined
163*9880d681SAndroid Build Coastguard Worker     // and removed). In this case, the binary will not have the linkage
164*9880d681SAndroid Build Coastguard Worker     // name for the function, so the profiler will emit the function's
165*9880d681SAndroid Build Coastguard Worker     // unmangled name, which may contain characters like ':' and '>' in its
166*9880d681SAndroid Build Coastguard Worker     // name (member functions, templates, etc).
167*9880d681SAndroid Build Coastguard Worker     //
168*9880d681SAndroid Build Coastguard Worker     // The only requirement we place on the identifier, then, is that it
169*9880d681SAndroid Build Coastguard Worker     // should not begin with a number.
170*9880d681SAndroid Build Coastguard Worker     if ((*LineIt)[0] != ' ') {
171*9880d681SAndroid Build Coastguard Worker       uint64_t NumSamples, NumHeadSamples;
172*9880d681SAndroid Build Coastguard Worker       StringRef FName;
173*9880d681SAndroid Build Coastguard Worker       if (!ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) {
174*9880d681SAndroid Build Coastguard Worker         reportError(LineIt.line_number(),
175*9880d681SAndroid Build Coastguard Worker                     "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
176*9880d681SAndroid Build Coastguard Worker         return sampleprof_error::malformed;
177*9880d681SAndroid Build Coastguard Worker       }
178*9880d681SAndroid Build Coastguard Worker       Profiles[FName] = FunctionSamples();
179*9880d681SAndroid Build Coastguard Worker       FunctionSamples &FProfile = Profiles[FName];
180*9880d681SAndroid Build Coastguard Worker       FProfile.setName(FName);
181*9880d681SAndroid Build Coastguard Worker       MergeResult(Result, FProfile.addTotalSamples(NumSamples));
182*9880d681SAndroid Build Coastguard Worker       MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples));
183*9880d681SAndroid Build Coastguard Worker       InlineStack.clear();
184*9880d681SAndroid Build Coastguard Worker       InlineStack.push_back(&FProfile);
185*9880d681SAndroid Build Coastguard Worker     } else {
186*9880d681SAndroid Build Coastguard Worker       uint64_t NumSamples;
187*9880d681SAndroid Build Coastguard Worker       StringRef FName;
188*9880d681SAndroid Build Coastguard Worker       DenseMap<StringRef, uint64_t> TargetCountMap;
189*9880d681SAndroid Build Coastguard Worker       bool IsCallsite;
190*9880d681SAndroid Build Coastguard Worker       uint32_t Depth, LineOffset, Discriminator;
191*9880d681SAndroid Build Coastguard Worker       if (!ParseLine(*LineIt, IsCallsite, Depth, NumSamples, LineOffset,
192*9880d681SAndroid Build Coastguard Worker                      Discriminator, FName, TargetCountMap)) {
193*9880d681SAndroid Build Coastguard Worker         reportError(LineIt.line_number(),
194*9880d681SAndroid Build Coastguard Worker                     "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
195*9880d681SAndroid Build Coastguard Worker                         *LineIt);
196*9880d681SAndroid Build Coastguard Worker         return sampleprof_error::malformed;
197*9880d681SAndroid Build Coastguard Worker       }
198*9880d681SAndroid Build Coastguard Worker       if (IsCallsite) {
199*9880d681SAndroid Build Coastguard Worker         while (InlineStack.size() > Depth) {
200*9880d681SAndroid Build Coastguard Worker           InlineStack.pop_back();
201*9880d681SAndroid Build Coastguard Worker         }
202*9880d681SAndroid Build Coastguard Worker         FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
203*9880d681SAndroid Build Coastguard Worker             LineLocation(LineOffset, Discriminator));
204*9880d681SAndroid Build Coastguard Worker         FSamples.setName(FName);
205*9880d681SAndroid Build Coastguard Worker         MergeResult(Result, FSamples.addTotalSamples(NumSamples));
206*9880d681SAndroid Build Coastguard Worker         InlineStack.push_back(&FSamples);
207*9880d681SAndroid Build Coastguard Worker       } else {
208*9880d681SAndroid Build Coastguard Worker         while (InlineStack.size() > Depth) {
209*9880d681SAndroid Build Coastguard Worker           InlineStack.pop_back();
210*9880d681SAndroid Build Coastguard Worker         }
211*9880d681SAndroid Build Coastguard Worker         FunctionSamples &FProfile = *InlineStack.back();
212*9880d681SAndroid Build Coastguard Worker         for (const auto &name_count : TargetCountMap) {
213*9880d681SAndroid Build Coastguard Worker           MergeResult(Result, FProfile.addCalledTargetSamples(
214*9880d681SAndroid Build Coastguard Worker                                   LineOffset, Discriminator, name_count.first,
215*9880d681SAndroid Build Coastguard Worker                                   name_count.second));
216*9880d681SAndroid Build Coastguard Worker         }
217*9880d681SAndroid Build Coastguard Worker         MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator,
218*9880d681SAndroid Build Coastguard Worker                                                     NumSamples));
219*9880d681SAndroid Build Coastguard Worker       }
220*9880d681SAndroid Build Coastguard Worker     }
221*9880d681SAndroid Build Coastguard Worker   }
222*9880d681SAndroid Build Coastguard Worker   if (Result == sampleprof_error::success)
223*9880d681SAndroid Build Coastguard Worker     computeSummary();
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker   return Result;
226*9880d681SAndroid Build Coastguard Worker }
227*9880d681SAndroid Build Coastguard Worker 
hasFormat(const MemoryBuffer & Buffer)228*9880d681SAndroid Build Coastguard Worker bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) {
229*9880d681SAndroid Build Coastguard Worker   bool result = false;
230*9880d681SAndroid Build Coastguard Worker 
231*9880d681SAndroid Build Coastguard Worker   // Check that the first non-comment line is a valid function header.
232*9880d681SAndroid Build Coastguard Worker   line_iterator LineIt(Buffer, /*SkipBlanks=*/true, '#');
233*9880d681SAndroid Build Coastguard Worker   if (!LineIt.is_at_eof()) {
234*9880d681SAndroid Build Coastguard Worker     if ((*LineIt)[0] != ' ') {
235*9880d681SAndroid Build Coastguard Worker       uint64_t NumSamples, NumHeadSamples;
236*9880d681SAndroid Build Coastguard Worker       StringRef FName;
237*9880d681SAndroid Build Coastguard Worker       result = ParseHead(*LineIt, FName, NumSamples, NumHeadSamples);
238*9880d681SAndroid Build Coastguard Worker     }
239*9880d681SAndroid Build Coastguard Worker   }
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   return result;
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker 
readNumber()244*9880d681SAndroid Build Coastguard Worker template <typename T> ErrorOr<T> SampleProfileReaderBinary::readNumber() {
245*9880d681SAndroid Build Coastguard Worker   unsigned NumBytesRead = 0;
246*9880d681SAndroid Build Coastguard Worker   std::error_code EC;
247*9880d681SAndroid Build Coastguard Worker   uint64_t Val = decodeULEB128(Data, &NumBytesRead);
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker   if (Val > std::numeric_limits<T>::max())
250*9880d681SAndroid Build Coastguard Worker     EC = sampleprof_error::malformed;
251*9880d681SAndroid Build Coastguard Worker   else if (Data + NumBytesRead > End)
252*9880d681SAndroid Build Coastguard Worker     EC = sampleprof_error::truncated;
253*9880d681SAndroid Build Coastguard Worker   else
254*9880d681SAndroid Build Coastguard Worker     EC = sampleprof_error::success;
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   if (EC) {
257*9880d681SAndroid Build Coastguard Worker     reportError(0, EC.message());
258*9880d681SAndroid Build Coastguard Worker     return EC;
259*9880d681SAndroid Build Coastguard Worker   }
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker   Data += NumBytesRead;
262*9880d681SAndroid Build Coastguard Worker   return static_cast<T>(Val);
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker 
readString()265*9880d681SAndroid Build Coastguard Worker ErrorOr<StringRef> SampleProfileReaderBinary::readString() {
266*9880d681SAndroid Build Coastguard Worker   std::error_code EC;
267*9880d681SAndroid Build Coastguard Worker   StringRef Str(reinterpret_cast<const char *>(Data));
268*9880d681SAndroid Build Coastguard Worker   if (Data + Str.size() + 1 > End) {
269*9880d681SAndroid Build Coastguard Worker     EC = sampleprof_error::truncated;
270*9880d681SAndroid Build Coastguard Worker     reportError(0, EC.message());
271*9880d681SAndroid Build Coastguard Worker     return EC;
272*9880d681SAndroid Build Coastguard Worker   }
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   Data += Str.size() + 1;
275*9880d681SAndroid Build Coastguard Worker   return Str;
276*9880d681SAndroid Build Coastguard Worker }
277*9880d681SAndroid Build Coastguard Worker 
readStringFromTable()278*9880d681SAndroid Build Coastguard Worker ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() {
279*9880d681SAndroid Build Coastguard Worker   std::error_code EC;
280*9880d681SAndroid Build Coastguard Worker   auto Idx = readNumber<uint32_t>();
281*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Idx.getError())
282*9880d681SAndroid Build Coastguard Worker     return EC;
283*9880d681SAndroid Build Coastguard Worker   if (*Idx >= NameTable.size())
284*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated_name_table;
285*9880d681SAndroid Build Coastguard Worker   return NameTable[*Idx];
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker 
288*9880d681SAndroid Build Coastguard Worker std::error_code
readProfile(FunctionSamples & FProfile)289*9880d681SAndroid Build Coastguard Worker SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
290*9880d681SAndroid Build Coastguard Worker   auto NumSamples = readNumber<uint64_t>();
291*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumSamples.getError())
292*9880d681SAndroid Build Coastguard Worker     return EC;
293*9880d681SAndroid Build Coastguard Worker   FProfile.addTotalSamples(*NumSamples);
294*9880d681SAndroid Build Coastguard Worker 
295*9880d681SAndroid Build Coastguard Worker   // Read the samples in the body.
296*9880d681SAndroid Build Coastguard Worker   auto NumRecords = readNumber<uint32_t>();
297*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumRecords.getError())
298*9880d681SAndroid Build Coastguard Worker     return EC;
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < *NumRecords; ++I) {
301*9880d681SAndroid Build Coastguard Worker     auto LineOffset = readNumber<uint64_t>();
302*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = LineOffset.getError())
303*9880d681SAndroid Build Coastguard Worker       return EC;
304*9880d681SAndroid Build Coastguard Worker 
305*9880d681SAndroid Build Coastguard Worker     if (!isOffsetLegal(*LineOffset)) {
306*9880d681SAndroid Build Coastguard Worker       return std::error_code();
307*9880d681SAndroid Build Coastguard Worker     }
308*9880d681SAndroid Build Coastguard Worker 
309*9880d681SAndroid Build Coastguard Worker     auto Discriminator = readNumber<uint64_t>();
310*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = Discriminator.getError())
311*9880d681SAndroid Build Coastguard Worker       return EC;
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker     auto NumSamples = readNumber<uint64_t>();
314*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = NumSamples.getError())
315*9880d681SAndroid Build Coastguard Worker       return EC;
316*9880d681SAndroid Build Coastguard Worker 
317*9880d681SAndroid Build Coastguard Worker     auto NumCalls = readNumber<uint32_t>();
318*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = NumCalls.getError())
319*9880d681SAndroid Build Coastguard Worker       return EC;
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker     for (uint32_t J = 0; J < *NumCalls; ++J) {
322*9880d681SAndroid Build Coastguard Worker       auto CalledFunction(readStringFromTable());
323*9880d681SAndroid Build Coastguard Worker       if (std::error_code EC = CalledFunction.getError())
324*9880d681SAndroid Build Coastguard Worker         return EC;
325*9880d681SAndroid Build Coastguard Worker 
326*9880d681SAndroid Build Coastguard Worker       auto CalledFunctionSamples = readNumber<uint64_t>();
327*9880d681SAndroid Build Coastguard Worker       if (std::error_code EC = CalledFunctionSamples.getError())
328*9880d681SAndroid Build Coastguard Worker         return EC;
329*9880d681SAndroid Build Coastguard Worker 
330*9880d681SAndroid Build Coastguard Worker       FProfile.addCalledTargetSamples(*LineOffset, *Discriminator,
331*9880d681SAndroid Build Coastguard Worker                                       *CalledFunction, *CalledFunctionSamples);
332*9880d681SAndroid Build Coastguard Worker     }
333*9880d681SAndroid Build Coastguard Worker 
334*9880d681SAndroid Build Coastguard Worker     FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples);
335*9880d681SAndroid Build Coastguard Worker   }
336*9880d681SAndroid Build Coastguard Worker 
337*9880d681SAndroid Build Coastguard Worker   // Read all the samples for inlined function calls.
338*9880d681SAndroid Build Coastguard Worker   auto NumCallsites = readNumber<uint32_t>();
339*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumCallsites.getError())
340*9880d681SAndroid Build Coastguard Worker     return EC;
341*9880d681SAndroid Build Coastguard Worker 
342*9880d681SAndroid Build Coastguard Worker   for (uint32_t J = 0; J < *NumCallsites; ++J) {
343*9880d681SAndroid Build Coastguard Worker     auto LineOffset = readNumber<uint64_t>();
344*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = LineOffset.getError())
345*9880d681SAndroid Build Coastguard Worker       return EC;
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker     auto Discriminator = readNumber<uint64_t>();
348*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = Discriminator.getError())
349*9880d681SAndroid Build Coastguard Worker       return EC;
350*9880d681SAndroid Build Coastguard Worker 
351*9880d681SAndroid Build Coastguard Worker     auto FName(readStringFromTable());
352*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = FName.getError())
353*9880d681SAndroid Build Coastguard Worker       return EC;
354*9880d681SAndroid Build Coastguard Worker 
355*9880d681SAndroid Build Coastguard Worker     FunctionSamples &CalleeProfile =
356*9880d681SAndroid Build Coastguard Worker         FProfile.functionSamplesAt(LineLocation(*LineOffset, *Discriminator));
357*9880d681SAndroid Build Coastguard Worker     CalleeProfile.setName(*FName);
358*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = readProfile(CalleeProfile))
359*9880d681SAndroid Build Coastguard Worker       return EC;
360*9880d681SAndroid Build Coastguard Worker   }
361*9880d681SAndroid Build Coastguard Worker 
362*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
363*9880d681SAndroid Build Coastguard Worker }
364*9880d681SAndroid Build Coastguard Worker 
read()365*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderBinary::read() {
366*9880d681SAndroid Build Coastguard Worker   while (!at_eof()) {
367*9880d681SAndroid Build Coastguard Worker     auto NumHeadSamples = readNumber<uint64_t>();
368*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = NumHeadSamples.getError())
369*9880d681SAndroid Build Coastguard Worker       return EC;
370*9880d681SAndroid Build Coastguard Worker 
371*9880d681SAndroid Build Coastguard Worker     auto FName(readStringFromTable());
372*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = FName.getError())
373*9880d681SAndroid Build Coastguard Worker       return EC;
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker     Profiles[*FName] = FunctionSamples();
376*9880d681SAndroid Build Coastguard Worker     FunctionSamples &FProfile = Profiles[*FName];
377*9880d681SAndroid Build Coastguard Worker     FProfile.setName(*FName);
378*9880d681SAndroid Build Coastguard Worker 
379*9880d681SAndroid Build Coastguard Worker     FProfile.addHeadSamples(*NumHeadSamples);
380*9880d681SAndroid Build Coastguard Worker 
381*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = readProfile(FProfile))
382*9880d681SAndroid Build Coastguard Worker       return EC;
383*9880d681SAndroid Build Coastguard Worker   }
384*9880d681SAndroid Build Coastguard Worker 
385*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker 
readHeader()388*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderBinary::readHeader() {
389*9880d681SAndroid Build Coastguard Worker   Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
390*9880d681SAndroid Build Coastguard Worker   End = Data + Buffer->getBufferSize();
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker   // Read and check the magic identifier.
393*9880d681SAndroid Build Coastguard Worker   auto Magic = readNumber<uint64_t>();
394*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Magic.getError())
395*9880d681SAndroid Build Coastguard Worker     return EC;
396*9880d681SAndroid Build Coastguard Worker   else if (*Magic != SPMagic())
397*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::bad_magic;
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker   // Read the version number.
400*9880d681SAndroid Build Coastguard Worker   auto Version = readNumber<uint64_t>();
401*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Version.getError())
402*9880d681SAndroid Build Coastguard Worker     return EC;
403*9880d681SAndroid Build Coastguard Worker   else if (*Version != SPVersion())
404*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::unsupported_version;
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = readSummary())
407*9880d681SAndroid Build Coastguard Worker     return EC;
408*9880d681SAndroid Build Coastguard Worker 
409*9880d681SAndroid Build Coastguard Worker   // Read the name table.
410*9880d681SAndroid Build Coastguard Worker   auto Size = readNumber<uint32_t>();
411*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Size.getError())
412*9880d681SAndroid Build Coastguard Worker     return EC;
413*9880d681SAndroid Build Coastguard Worker   NameTable.reserve(*Size);
414*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < *Size; ++I) {
415*9880d681SAndroid Build Coastguard Worker     auto Name(readString());
416*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = Name.getError())
417*9880d681SAndroid Build Coastguard Worker       return EC;
418*9880d681SAndroid Build Coastguard Worker     NameTable.push_back(*Name);
419*9880d681SAndroid Build Coastguard Worker   }
420*9880d681SAndroid Build Coastguard Worker 
421*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
422*9880d681SAndroid Build Coastguard Worker }
423*9880d681SAndroid Build Coastguard Worker 
readSummaryEntry(std::vector<ProfileSummaryEntry> & Entries)424*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderBinary::readSummaryEntry(
425*9880d681SAndroid Build Coastguard Worker     std::vector<ProfileSummaryEntry> &Entries) {
426*9880d681SAndroid Build Coastguard Worker   auto Cutoff = readNumber<uint64_t>();
427*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Cutoff.getError())
428*9880d681SAndroid Build Coastguard Worker     return EC;
429*9880d681SAndroid Build Coastguard Worker 
430*9880d681SAndroid Build Coastguard Worker   auto MinBlockCount = readNumber<uint64_t>();
431*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = MinBlockCount.getError())
432*9880d681SAndroid Build Coastguard Worker     return EC;
433*9880d681SAndroid Build Coastguard Worker 
434*9880d681SAndroid Build Coastguard Worker   auto NumBlocks = readNumber<uint64_t>();
435*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumBlocks.getError())
436*9880d681SAndroid Build Coastguard Worker     return EC;
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
439*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
440*9880d681SAndroid Build Coastguard Worker }
441*9880d681SAndroid Build Coastguard Worker 
readSummary()442*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderBinary::readSummary() {
443*9880d681SAndroid Build Coastguard Worker   auto TotalCount = readNumber<uint64_t>();
444*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = TotalCount.getError())
445*9880d681SAndroid Build Coastguard Worker     return EC;
446*9880d681SAndroid Build Coastguard Worker 
447*9880d681SAndroid Build Coastguard Worker   auto MaxBlockCount = readNumber<uint64_t>();
448*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = MaxBlockCount.getError())
449*9880d681SAndroid Build Coastguard Worker     return EC;
450*9880d681SAndroid Build Coastguard Worker 
451*9880d681SAndroid Build Coastguard Worker   auto MaxFunctionCount = readNumber<uint64_t>();
452*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = MaxFunctionCount.getError())
453*9880d681SAndroid Build Coastguard Worker     return EC;
454*9880d681SAndroid Build Coastguard Worker 
455*9880d681SAndroid Build Coastguard Worker   auto NumBlocks = readNumber<uint64_t>();
456*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumBlocks.getError())
457*9880d681SAndroid Build Coastguard Worker     return EC;
458*9880d681SAndroid Build Coastguard Worker 
459*9880d681SAndroid Build Coastguard Worker   auto NumFunctions = readNumber<uint64_t>();
460*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumFunctions.getError())
461*9880d681SAndroid Build Coastguard Worker     return EC;
462*9880d681SAndroid Build Coastguard Worker 
463*9880d681SAndroid Build Coastguard Worker   auto NumSummaryEntries = readNumber<uint64_t>();
464*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = NumSummaryEntries.getError())
465*9880d681SAndroid Build Coastguard Worker     return EC;
466*9880d681SAndroid Build Coastguard Worker 
467*9880d681SAndroid Build Coastguard Worker   std::vector<ProfileSummaryEntry> Entries;
468*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < *NumSummaryEntries; i++) {
469*9880d681SAndroid Build Coastguard Worker     std::error_code EC = readSummaryEntry(Entries);
470*9880d681SAndroid Build Coastguard Worker     if (EC != sampleprof_error::success)
471*9880d681SAndroid Build Coastguard Worker       return EC;
472*9880d681SAndroid Build Coastguard Worker   }
473*9880d681SAndroid Build Coastguard Worker   Summary = llvm::make_unique<ProfileSummary>(
474*9880d681SAndroid Build Coastguard Worker       ProfileSummary::PSK_Sample, Entries, *TotalCount, *MaxBlockCount, 0,
475*9880d681SAndroid Build Coastguard Worker       *MaxFunctionCount, *NumBlocks, *NumFunctions);
476*9880d681SAndroid Build Coastguard Worker 
477*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
478*9880d681SAndroid Build Coastguard Worker }
479*9880d681SAndroid Build Coastguard Worker 
hasFormat(const MemoryBuffer & Buffer)480*9880d681SAndroid Build Coastguard Worker bool SampleProfileReaderBinary::hasFormat(const MemoryBuffer &Buffer) {
481*9880d681SAndroid Build Coastguard Worker   const uint8_t *Data =
482*9880d681SAndroid Build Coastguard Worker       reinterpret_cast<const uint8_t *>(Buffer.getBufferStart());
483*9880d681SAndroid Build Coastguard Worker   uint64_t Magic = decodeULEB128(Data);
484*9880d681SAndroid Build Coastguard Worker   return Magic == SPMagic();
485*9880d681SAndroid Build Coastguard Worker }
486*9880d681SAndroid Build Coastguard Worker 
skipNextWord()487*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::skipNextWord() {
488*9880d681SAndroid Build Coastguard Worker   uint32_t dummy;
489*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(dummy))
490*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
491*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker 
readNumber()494*9880d681SAndroid Build Coastguard Worker template <typename T> ErrorOr<T> SampleProfileReaderGCC::readNumber() {
495*9880d681SAndroid Build Coastguard Worker   if (sizeof(T) <= sizeof(uint32_t)) {
496*9880d681SAndroid Build Coastguard Worker     uint32_t Val;
497*9880d681SAndroid Build Coastguard Worker     if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
498*9880d681SAndroid Build Coastguard Worker       return static_cast<T>(Val);
499*9880d681SAndroid Build Coastguard Worker   } else if (sizeof(T) <= sizeof(uint64_t)) {
500*9880d681SAndroid Build Coastguard Worker     uint64_t Val;
501*9880d681SAndroid Build Coastguard Worker     if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max())
502*9880d681SAndroid Build Coastguard Worker       return static_cast<T>(Val);
503*9880d681SAndroid Build Coastguard Worker   }
504*9880d681SAndroid Build Coastguard Worker 
505*9880d681SAndroid Build Coastguard Worker   std::error_code EC = sampleprof_error::malformed;
506*9880d681SAndroid Build Coastguard Worker   reportError(0, EC.message());
507*9880d681SAndroid Build Coastguard Worker   return EC;
508*9880d681SAndroid Build Coastguard Worker }
509*9880d681SAndroid Build Coastguard Worker 
readString()510*9880d681SAndroid Build Coastguard Worker ErrorOr<StringRef> SampleProfileReaderGCC::readString() {
511*9880d681SAndroid Build Coastguard Worker   StringRef Str;
512*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readString(Str))
513*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
514*9880d681SAndroid Build Coastguard Worker   return Str;
515*9880d681SAndroid Build Coastguard Worker }
516*9880d681SAndroid Build Coastguard Worker 
readHeader()517*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::readHeader() {
518*9880d681SAndroid Build Coastguard Worker   // Read the magic identifier.
519*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readGCDAFormat())
520*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::unrecognized_format;
521*9880d681SAndroid Build Coastguard Worker 
522*9880d681SAndroid Build Coastguard Worker   // Read the version number. Note - the GCC reader does not validate this
523*9880d681SAndroid Build Coastguard Worker   // version, but the profile creator generates v704.
524*9880d681SAndroid Build Coastguard Worker   GCOV::GCOVVersion version;
525*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readGCOVVersion(version))
526*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::unrecognized_format;
527*9880d681SAndroid Build Coastguard Worker 
528*9880d681SAndroid Build Coastguard Worker   if (version != GCOV::V704)
529*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::unsupported_version;
530*9880d681SAndroid Build Coastguard Worker 
531*9880d681SAndroid Build Coastguard Worker   // Skip the empty integer.
532*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = skipNextWord())
533*9880d681SAndroid Build Coastguard Worker     return EC;
534*9880d681SAndroid Build Coastguard Worker 
535*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
536*9880d681SAndroid Build Coastguard Worker }
537*9880d681SAndroid Build Coastguard Worker 
readSectionTag(uint32_t Expected)538*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::readSectionTag(uint32_t Expected) {
539*9880d681SAndroid Build Coastguard Worker   uint32_t Tag;
540*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(Tag))
541*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
542*9880d681SAndroid Build Coastguard Worker 
543*9880d681SAndroid Build Coastguard Worker   if (Tag != Expected)
544*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::malformed;
545*9880d681SAndroid Build Coastguard Worker 
546*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = skipNextWord())
547*9880d681SAndroid Build Coastguard Worker     return EC;
548*9880d681SAndroid Build Coastguard Worker 
549*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
550*9880d681SAndroid Build Coastguard Worker }
551*9880d681SAndroid Build Coastguard Worker 
readNameTable()552*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::readNameTable() {
553*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
554*9880d681SAndroid Build Coastguard Worker     return EC;
555*9880d681SAndroid Build Coastguard Worker 
556*9880d681SAndroid Build Coastguard Worker   uint32_t Size;
557*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(Size))
558*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
559*9880d681SAndroid Build Coastguard Worker 
560*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < Size; ++I) {
561*9880d681SAndroid Build Coastguard Worker     StringRef Str;
562*9880d681SAndroid Build Coastguard Worker     if (!GcovBuffer.readString(Str))
563*9880d681SAndroid Build Coastguard Worker       return sampleprof_error::truncated;
564*9880d681SAndroid Build Coastguard Worker     Names.push_back(Str);
565*9880d681SAndroid Build Coastguard Worker   }
566*9880d681SAndroid Build Coastguard Worker 
567*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
568*9880d681SAndroid Build Coastguard Worker }
569*9880d681SAndroid Build Coastguard Worker 
readFunctionProfiles()570*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::readFunctionProfiles() {
571*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
572*9880d681SAndroid Build Coastguard Worker     return EC;
573*9880d681SAndroid Build Coastguard Worker 
574*9880d681SAndroid Build Coastguard Worker   uint32_t NumFunctions;
575*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(NumFunctions))
576*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
577*9880d681SAndroid Build Coastguard Worker 
578*9880d681SAndroid Build Coastguard Worker   InlineCallStack Stack;
579*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < NumFunctions; ++I)
580*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = readOneFunctionProfile(Stack, true, 0))
581*9880d681SAndroid Build Coastguard Worker       return EC;
582*9880d681SAndroid Build Coastguard Worker 
583*9880d681SAndroid Build Coastguard Worker   computeSummary();
584*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
585*9880d681SAndroid Build Coastguard Worker }
586*9880d681SAndroid Build Coastguard Worker 
readOneFunctionProfile(const InlineCallStack & InlineStack,bool Update,uint32_t Offset)587*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
588*9880d681SAndroid Build Coastguard Worker     const InlineCallStack &InlineStack, bool Update, uint32_t Offset) {
589*9880d681SAndroid Build Coastguard Worker   uint64_t HeadCount = 0;
590*9880d681SAndroid Build Coastguard Worker   if (InlineStack.size() == 0)
591*9880d681SAndroid Build Coastguard Worker     if (!GcovBuffer.readInt64(HeadCount))
592*9880d681SAndroid Build Coastguard Worker       return sampleprof_error::truncated;
593*9880d681SAndroid Build Coastguard Worker 
594*9880d681SAndroid Build Coastguard Worker   uint32_t NameIdx;
595*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(NameIdx))
596*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
597*9880d681SAndroid Build Coastguard Worker 
598*9880d681SAndroid Build Coastguard Worker   StringRef Name(Names[NameIdx]);
599*9880d681SAndroid Build Coastguard Worker 
600*9880d681SAndroid Build Coastguard Worker   uint32_t NumPosCounts;
601*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(NumPosCounts))
602*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
603*9880d681SAndroid Build Coastguard Worker 
604*9880d681SAndroid Build Coastguard Worker   uint32_t NumCallsites;
605*9880d681SAndroid Build Coastguard Worker   if (!GcovBuffer.readInt(NumCallsites))
606*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::truncated;
607*9880d681SAndroid Build Coastguard Worker 
608*9880d681SAndroid Build Coastguard Worker   FunctionSamples *FProfile = nullptr;
609*9880d681SAndroid Build Coastguard Worker   if (InlineStack.size() == 0) {
610*9880d681SAndroid Build Coastguard Worker     // If this is a top function that we have already processed, do not
611*9880d681SAndroid Build Coastguard Worker     // update its profile again.  This happens in the presence of
612*9880d681SAndroid Build Coastguard Worker     // function aliases.  Since these aliases share the same function
613*9880d681SAndroid Build Coastguard Worker     // body, there will be identical replicated profiles for the
614*9880d681SAndroid Build Coastguard Worker     // original function.  In this case, we simply not bother updating
615*9880d681SAndroid Build Coastguard Worker     // the profile of the original function.
616*9880d681SAndroid Build Coastguard Worker     FProfile = &Profiles[Name];
617*9880d681SAndroid Build Coastguard Worker     FProfile->addHeadSamples(HeadCount);
618*9880d681SAndroid Build Coastguard Worker     if (FProfile->getTotalSamples() > 0)
619*9880d681SAndroid Build Coastguard Worker       Update = false;
620*9880d681SAndroid Build Coastguard Worker   } else {
621*9880d681SAndroid Build Coastguard Worker     // Otherwise, we are reading an inlined instance. The top of the
622*9880d681SAndroid Build Coastguard Worker     // inline stack contains the profile of the caller. Insert this
623*9880d681SAndroid Build Coastguard Worker     // callee in the caller's CallsiteMap.
624*9880d681SAndroid Build Coastguard Worker     FunctionSamples *CallerProfile = InlineStack.front();
625*9880d681SAndroid Build Coastguard Worker     uint32_t LineOffset = Offset >> 16;
626*9880d681SAndroid Build Coastguard Worker     uint32_t Discriminator = Offset & 0xffff;
627*9880d681SAndroid Build Coastguard Worker     FProfile = &CallerProfile->functionSamplesAt(
628*9880d681SAndroid Build Coastguard Worker         LineLocation(LineOffset, Discriminator));
629*9880d681SAndroid Build Coastguard Worker   }
630*9880d681SAndroid Build Coastguard Worker   FProfile->setName(Name);
631*9880d681SAndroid Build Coastguard Worker 
632*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < NumPosCounts; ++I) {
633*9880d681SAndroid Build Coastguard Worker     uint32_t Offset;
634*9880d681SAndroid Build Coastguard Worker     if (!GcovBuffer.readInt(Offset))
635*9880d681SAndroid Build Coastguard Worker       return sampleprof_error::truncated;
636*9880d681SAndroid Build Coastguard Worker 
637*9880d681SAndroid Build Coastguard Worker     uint32_t NumTargets;
638*9880d681SAndroid Build Coastguard Worker     if (!GcovBuffer.readInt(NumTargets))
639*9880d681SAndroid Build Coastguard Worker       return sampleprof_error::truncated;
640*9880d681SAndroid Build Coastguard Worker 
641*9880d681SAndroid Build Coastguard Worker     uint64_t Count;
642*9880d681SAndroid Build Coastguard Worker     if (!GcovBuffer.readInt64(Count))
643*9880d681SAndroid Build Coastguard Worker       return sampleprof_error::truncated;
644*9880d681SAndroid Build Coastguard Worker 
645*9880d681SAndroid Build Coastguard Worker     // The line location is encoded in the offset as:
646*9880d681SAndroid Build Coastguard Worker     //   high 16 bits: line offset to the start of the function.
647*9880d681SAndroid Build Coastguard Worker     //   low 16 bits: discriminator.
648*9880d681SAndroid Build Coastguard Worker     uint32_t LineOffset = Offset >> 16;
649*9880d681SAndroid Build Coastguard Worker     uint32_t Discriminator = Offset & 0xffff;
650*9880d681SAndroid Build Coastguard Worker 
651*9880d681SAndroid Build Coastguard Worker     InlineCallStack NewStack;
652*9880d681SAndroid Build Coastguard Worker     NewStack.push_back(FProfile);
653*9880d681SAndroid Build Coastguard Worker     NewStack.insert(NewStack.end(), InlineStack.begin(), InlineStack.end());
654*9880d681SAndroid Build Coastguard Worker     if (Update) {
655*9880d681SAndroid Build Coastguard Worker       // Walk up the inline stack, adding the samples on this line to
656*9880d681SAndroid Build Coastguard Worker       // the total sample count of the callers in the chain.
657*9880d681SAndroid Build Coastguard Worker       for (auto CallerProfile : NewStack)
658*9880d681SAndroid Build Coastguard Worker         CallerProfile->addTotalSamples(Count);
659*9880d681SAndroid Build Coastguard Worker 
660*9880d681SAndroid Build Coastguard Worker       // Update the body samples for the current profile.
661*9880d681SAndroid Build Coastguard Worker       FProfile->addBodySamples(LineOffset, Discriminator, Count);
662*9880d681SAndroid Build Coastguard Worker     }
663*9880d681SAndroid Build Coastguard Worker 
664*9880d681SAndroid Build Coastguard Worker     // Process the list of functions called at an indirect call site.
665*9880d681SAndroid Build Coastguard Worker     // These are all the targets that a function pointer (or virtual
666*9880d681SAndroid Build Coastguard Worker     // function) resolved at runtime.
667*9880d681SAndroid Build Coastguard Worker     for (uint32_t J = 0; J < NumTargets; J++) {
668*9880d681SAndroid Build Coastguard Worker       uint32_t HistVal;
669*9880d681SAndroid Build Coastguard Worker       if (!GcovBuffer.readInt(HistVal))
670*9880d681SAndroid Build Coastguard Worker         return sampleprof_error::truncated;
671*9880d681SAndroid Build Coastguard Worker 
672*9880d681SAndroid Build Coastguard Worker       if (HistVal != HIST_TYPE_INDIR_CALL_TOPN)
673*9880d681SAndroid Build Coastguard Worker         return sampleprof_error::malformed;
674*9880d681SAndroid Build Coastguard Worker 
675*9880d681SAndroid Build Coastguard Worker       uint64_t TargetIdx;
676*9880d681SAndroid Build Coastguard Worker       if (!GcovBuffer.readInt64(TargetIdx))
677*9880d681SAndroid Build Coastguard Worker         return sampleprof_error::truncated;
678*9880d681SAndroid Build Coastguard Worker       StringRef TargetName(Names[TargetIdx]);
679*9880d681SAndroid Build Coastguard Worker 
680*9880d681SAndroid Build Coastguard Worker       uint64_t TargetCount;
681*9880d681SAndroid Build Coastguard Worker       if (!GcovBuffer.readInt64(TargetCount))
682*9880d681SAndroid Build Coastguard Worker         return sampleprof_error::truncated;
683*9880d681SAndroid Build Coastguard Worker 
684*9880d681SAndroid Build Coastguard Worker       if (Update) {
685*9880d681SAndroid Build Coastguard Worker         FunctionSamples &TargetProfile = Profiles[TargetName];
686*9880d681SAndroid Build Coastguard Worker         TargetProfile.addCalledTargetSamples(LineOffset, Discriminator,
687*9880d681SAndroid Build Coastguard Worker                                              TargetName, TargetCount);
688*9880d681SAndroid Build Coastguard Worker       }
689*9880d681SAndroid Build Coastguard Worker     }
690*9880d681SAndroid Build Coastguard Worker   }
691*9880d681SAndroid Build Coastguard Worker 
692*9880d681SAndroid Build Coastguard Worker   // Process all the inlined callers into the current function. These
693*9880d681SAndroid Build Coastguard Worker   // are all the callsites that were inlined into this function.
694*9880d681SAndroid Build Coastguard Worker   for (uint32_t I = 0; I < NumCallsites; I++) {
695*9880d681SAndroid Build Coastguard Worker     // The offset is encoded as:
696*9880d681SAndroid Build Coastguard Worker     //   high 16 bits: line offset to the start of the function.
697*9880d681SAndroid Build Coastguard Worker     //   low 16 bits: discriminator.
698*9880d681SAndroid Build Coastguard Worker     uint32_t Offset;
699*9880d681SAndroid Build Coastguard Worker     if (!GcovBuffer.readInt(Offset))
700*9880d681SAndroid Build Coastguard Worker       return sampleprof_error::truncated;
701*9880d681SAndroid Build Coastguard Worker     InlineCallStack NewStack;
702*9880d681SAndroid Build Coastguard Worker     NewStack.push_back(FProfile);
703*9880d681SAndroid Build Coastguard Worker     NewStack.insert(NewStack.end(), InlineStack.begin(), InlineStack.end());
704*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
705*9880d681SAndroid Build Coastguard Worker       return EC;
706*9880d681SAndroid Build Coastguard Worker   }
707*9880d681SAndroid Build Coastguard Worker 
708*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
709*9880d681SAndroid Build Coastguard Worker }
710*9880d681SAndroid Build Coastguard Worker 
711*9880d681SAndroid Build Coastguard Worker /// \brief Read a GCC AutoFDO profile.
712*9880d681SAndroid Build Coastguard Worker ///
713*9880d681SAndroid Build Coastguard Worker /// This format is generated by the Linux Perf conversion tool at
714*9880d681SAndroid Build Coastguard Worker /// https://github.com/google/autofdo.
read()715*9880d681SAndroid Build Coastguard Worker std::error_code SampleProfileReaderGCC::read() {
716*9880d681SAndroid Build Coastguard Worker   // Read the string table.
717*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = readNameTable())
718*9880d681SAndroid Build Coastguard Worker     return EC;
719*9880d681SAndroid Build Coastguard Worker 
720*9880d681SAndroid Build Coastguard Worker   // Read the source profile.
721*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = readFunctionProfiles())
722*9880d681SAndroid Build Coastguard Worker     return EC;
723*9880d681SAndroid Build Coastguard Worker 
724*9880d681SAndroid Build Coastguard Worker   return sampleprof_error::success;
725*9880d681SAndroid Build Coastguard Worker }
726*9880d681SAndroid Build Coastguard Worker 
hasFormat(const MemoryBuffer & Buffer)727*9880d681SAndroid Build Coastguard Worker bool SampleProfileReaderGCC::hasFormat(const MemoryBuffer &Buffer) {
728*9880d681SAndroid Build Coastguard Worker   StringRef Magic(reinterpret_cast<const char *>(Buffer.getBufferStart()));
729*9880d681SAndroid Build Coastguard Worker   return Magic == "adcg*704";
730*9880d681SAndroid Build Coastguard Worker }
731*9880d681SAndroid Build Coastguard Worker 
732*9880d681SAndroid Build Coastguard Worker /// \brief Prepare a memory buffer for the contents of \p Filename.
733*9880d681SAndroid Build Coastguard Worker ///
734*9880d681SAndroid Build Coastguard Worker /// \returns an error code indicating the status of the buffer.
735*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<MemoryBuffer>>
setupMemoryBuffer(const Twine & Filename)736*9880d681SAndroid Build Coastguard Worker setupMemoryBuffer(const Twine &Filename) {
737*9880d681SAndroid Build Coastguard Worker   auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(Filename);
738*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = BufferOrErr.getError())
739*9880d681SAndroid Build Coastguard Worker     return EC;
740*9880d681SAndroid Build Coastguard Worker   auto Buffer = std::move(BufferOrErr.get());
741*9880d681SAndroid Build Coastguard Worker 
742*9880d681SAndroid Build Coastguard Worker   // Sanity check the file.
743*9880d681SAndroid Build Coastguard Worker   if (Buffer->getBufferSize() > std::numeric_limits<uint32_t>::max())
744*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::too_large;
745*9880d681SAndroid Build Coastguard Worker 
746*9880d681SAndroid Build Coastguard Worker   return std::move(Buffer);
747*9880d681SAndroid Build Coastguard Worker }
748*9880d681SAndroid Build Coastguard Worker 
749*9880d681SAndroid Build Coastguard Worker /// \brief Create a sample profile reader based on the format of the input file.
750*9880d681SAndroid Build Coastguard Worker ///
751*9880d681SAndroid Build Coastguard Worker /// \param Filename The file to open.
752*9880d681SAndroid Build Coastguard Worker ///
753*9880d681SAndroid Build Coastguard Worker /// \param Reader The reader to instantiate according to \p Filename's format.
754*9880d681SAndroid Build Coastguard Worker ///
755*9880d681SAndroid Build Coastguard Worker /// \param C The LLVM context to use to emit diagnostics.
756*9880d681SAndroid Build Coastguard Worker ///
757*9880d681SAndroid Build Coastguard Worker /// \returns an error code indicating the status of the created reader.
758*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<SampleProfileReader>>
create(const Twine & Filename,LLVMContext & C)759*9880d681SAndroid Build Coastguard Worker SampleProfileReader::create(const Twine &Filename, LLVMContext &C) {
760*9880d681SAndroid Build Coastguard Worker   auto BufferOrError = setupMemoryBuffer(Filename);
761*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = BufferOrError.getError())
762*9880d681SAndroid Build Coastguard Worker     return EC;
763*9880d681SAndroid Build Coastguard Worker   return create(BufferOrError.get(), C);
764*9880d681SAndroid Build Coastguard Worker }
765*9880d681SAndroid Build Coastguard Worker 
766*9880d681SAndroid Build Coastguard Worker /// \brief Create a sample profile reader based on the format of the input data.
767*9880d681SAndroid Build Coastguard Worker ///
768*9880d681SAndroid Build Coastguard Worker /// \param B The memory buffer to create the reader from (assumes ownership).
769*9880d681SAndroid Build Coastguard Worker ///
770*9880d681SAndroid Build Coastguard Worker /// \param Reader The reader to instantiate according to \p Filename's format.
771*9880d681SAndroid Build Coastguard Worker ///
772*9880d681SAndroid Build Coastguard Worker /// \param C The LLVM context to use to emit diagnostics.
773*9880d681SAndroid Build Coastguard Worker ///
774*9880d681SAndroid Build Coastguard Worker /// \returns an error code indicating the status of the created reader.
775*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<SampleProfileReader>>
create(std::unique_ptr<MemoryBuffer> & B,LLVMContext & C)776*9880d681SAndroid Build Coastguard Worker SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) {
777*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<SampleProfileReader> Reader;
778*9880d681SAndroid Build Coastguard Worker   if (SampleProfileReaderBinary::hasFormat(*B))
779*9880d681SAndroid Build Coastguard Worker     Reader.reset(new SampleProfileReaderBinary(std::move(B), C));
780*9880d681SAndroid Build Coastguard Worker   else if (SampleProfileReaderGCC::hasFormat(*B))
781*9880d681SAndroid Build Coastguard Worker     Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
782*9880d681SAndroid Build Coastguard Worker   else if (SampleProfileReaderText::hasFormat(*B))
783*9880d681SAndroid Build Coastguard Worker     Reader.reset(new SampleProfileReaderText(std::move(B), C));
784*9880d681SAndroid Build Coastguard Worker   else
785*9880d681SAndroid Build Coastguard Worker     return sampleprof_error::unrecognized_format;
786*9880d681SAndroid Build Coastguard Worker 
787*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = Reader->readHeader())
788*9880d681SAndroid Build Coastguard Worker     return EC;
789*9880d681SAndroid Build Coastguard Worker 
790*9880d681SAndroid Build Coastguard Worker   return std::move(Reader);
791*9880d681SAndroid Build Coastguard Worker }
792*9880d681SAndroid Build Coastguard Worker 
793*9880d681SAndroid Build Coastguard Worker // For text and GCC file formats, we compute the summary after reading the
794*9880d681SAndroid Build Coastguard Worker // profile. Binary format has the profile summary in its header.
computeSummary()795*9880d681SAndroid Build Coastguard Worker void SampleProfileReader::computeSummary() {
796*9880d681SAndroid Build Coastguard Worker   SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
797*9880d681SAndroid Build Coastguard Worker   for (const auto &I : Profiles) {
798*9880d681SAndroid Build Coastguard Worker     const FunctionSamples &Profile = I.second;
799*9880d681SAndroid Build Coastguard Worker     Builder.addRecord(Profile);
800*9880d681SAndroid Build Coastguard Worker   }
801*9880d681SAndroid Build Coastguard Worker   Summary = Builder.getSummary();
802*9880d681SAndroid Build Coastguard Worker }
803