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

Generated by: LCOV version 1.13