LCOV - code coverage report
Current view: top level - lib/ProfileData - SampleProfReader.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 331 409 80.9 %
Date: 2018-06-17 00:07:59 Functions: 36 37 97.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13