LCOV - code coverage report
Current view: top level - lib/ProfileData - InstrProfReader.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 265 284 93.3 %
Date: 2018-06-17 00:07:59 Functions: 44 44 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
       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 contains support for reading profiling data for clang's
      11             : // instrumentation based PGO and coverage.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/ProfileData/InstrProfReader.h"
      16             : #include "llvm/ADT/ArrayRef.h"
      17             : #include "llvm/ADT/STLExtras.h"
      18             : #include "llvm/ADT/StringRef.h"
      19             : #include "llvm/IR/ProfileSummary.h"
      20             : #include "llvm/ProfileData/InstrProf.h"
      21             : #include "llvm/ProfileData/ProfileCommon.h"
      22             : #include "llvm/Support/Endian.h"
      23             : #include "llvm/Support/Error.h"
      24             : #include "llvm/Support/ErrorOr.h"
      25             : #include "llvm/Support/MemoryBuffer.h"
      26             : #include "llvm/Support/SwapByteOrder.h"
      27             : #include <algorithm>
      28             : #include <cctype>
      29             : #include <cstddef>
      30             : #include <cstdint>
      31             : #include <limits>
      32             : #include <memory>
      33             : #include <system_error>
      34             : #include <utility>
      35             : #include <vector>
      36             : 
      37             : using namespace llvm;
      38             : 
      39             : static Expected<std::unique_ptr<MemoryBuffer>>
      40         436 : setupMemoryBuffer(const Twine &Path) {
      41             :   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      42         436 :       MemoryBuffer::getFileOrSTDIN(Path);
      43         436 :   if (std::error_code EC = BufferOrErr.getError())
      44           8 :     return errorCodeToError(EC);
      45             :   return std::move(BufferOrErr.get());
      46             : }
      47             : 
      48             : static Error initializeReader(InstrProfReader &Reader) {
      49         557 :   return Reader.readHeader();
      50             : }
      51             : 
      52             : Expected<std::unique_ptr<InstrProfReader>>
      53         212 : InstrProfReader::create(const Twine &Path) {
      54             :   // Set up the buffer to read.
      55         424 :   auto BufferOrError = setupMemoryBuffer(Path);
      56         212 :   if (Error E = BufferOrError.takeError())
      57             :     return std::move(E);
      58         424 :   return InstrProfReader::create(std::move(BufferOrError.get()));
      59             : }
      60             : 
      61             : Expected<std::unique_ptr<InstrProfReader>>
      62         212 : InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
      63             :   // Sanity check the buffer.
      64         424 :   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<unsigned>::max())
      65             :     return make_error<InstrProfError>(instrprof_error::too_large);
      66             : 
      67         212 :   if (Buffer->getBufferSize() == 0)
      68             :     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
      69             : 
      70             :   std::unique_ptr<InstrProfReader> Result;
      71             :   // Create the reader.
      72         209 :   if (IndexedInstrProfReader::hasFormat(*Buffer))
      73          59 :     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
      74         150 :   else if (RawInstrProfReader64::hasFormat(*Buffer))
      75           8 :     Result.reset(new RawInstrProfReader64(std::move(Buffer)));
      76         142 :   else if (RawInstrProfReader32::hasFormat(*Buffer))
      77           2 :     Result.reset(new RawInstrProfReader32(std::move(Buffer)));
      78         140 :   else if (TextInstrProfReader::hasFormat(*Buffer))
      79         139 :     Result.reset(new TextInstrProfReader(std::move(Buffer)));
      80             :   else
      81             :     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
      82             : 
      83             :   // Initialize the reader and return the result.
      84         208 :   if (Error E = initializeReader(*Result))
      85             :     return std::move(E);
      86             : 
      87             :   return std::move(Result);
      88             : }
      89             : 
      90             : Expected<std::unique_ptr<IndexedInstrProfReader>>
      91         224 : IndexedInstrProfReader::create(const Twine &Path) {
      92             :   // Set up the buffer to read.
      93         448 :   auto BufferOrError = setupMemoryBuffer(Path);
      94         224 :   if (Error E = BufferOrError.takeError())
      95             :     return std::move(E);
      96         440 :   return IndexedInstrProfReader::create(std::move(BufferOrError.get()));
      97             : }
      98             : 
      99             : Expected<std::unique_ptr<IndexedInstrProfReader>>
     100         349 : IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
     101             :   // Sanity check the buffer.
     102         698 :   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<unsigned>::max())
     103             :     return make_error<InstrProfError>(instrprof_error::too_large);
     104             : 
     105             :   // Create the reader.
     106         349 :   if (!IndexedInstrProfReader::hasFormat(*Buffer))
     107             :     return make_error<InstrProfError>(instrprof_error::bad_magic);
     108         349 :   auto Result = llvm::make_unique<IndexedInstrProfReader>(std::move(Buffer));
     109             : 
     110             :   // Initialize the reader and return the result.
     111         698 :   if (Error E = initializeReader(*Result))
     112             :     return std::move(E);
     113             : 
     114             :   return std::move(Result);
     115             : }
     116             : 
     117         760 : void InstrProfIterator::Increment() {
     118        1520 :   if (auto E = Reader->readNextRecord(Record)) {
     119             :     // Handle errors in the reader.
     120         422 :     InstrProfError::take(std::move(E));
     121         422 :     *this = InstrProfIterator();
     122             :   }
     123         760 : }
     124             : 
     125         140 : bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
     126             :   // Verify that this really looks like plain ASCII text by checking a
     127             :   // 'reasonable' number of characters (up to profile magic size).
     128         420 :   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
     129             :   StringRef buffer = Buffer.getBufferStart();
     130         280 :   return count == 0 ||
     131         140 :          std::all_of(buffer.begin(), buffer.begin() + count,
     132        1241 :                      [](char c) { return ::isprint(c) || ::isspace(c); });
     133             : }
     134             : 
     135             : // Read the profile variant flag from the header: ":FE" means this is a FE
     136             : // generated profile. ":IR" means this is an IR level profile. Other strings
     137             : // with a leading ':' will be reported an error format.
     138         139 : Error TextInstrProfReader::readHeader() {
     139         139 :   Symtab.reset(new InstrProfSymtab());
     140             :   bool IsIRInstr = false;
     141             :   if (!Line->startswith(":")) {
     142         106 :     IsIRLevelProfile = false;
     143             :     return success();
     144             :   }
     145          33 :   StringRef Str = (Line)->substr(1);
     146             :   if (Str.equals_lower("ir"))
     147             :     IsIRInstr = true;
     148             :   else if (Str.equals_lower("fe"))
     149             :     IsIRInstr = false;
     150             :   else
     151             :     return error(instrprof_error::bad_header);
     152             : 
     153          33 :   ++Line;
     154          33 :   IsIRLevelProfile = IsIRInstr;
     155             :   return success();
     156             : }
     157             : 
     158             : Error
     159         291 : TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
     160             : 
     161             : #define CHECK_LINE_END(Line)                                                   \
     162             :   if (Line.is_at_end())                                                        \
     163             :     return error(instrprof_error::truncated);
     164             : #define READ_NUM(Str, Dst)                                                     \
     165             :   if ((Str).getAsInteger(10, (Dst)))                                           \
     166             :     return error(instrprof_error::malformed);
     167             : #define VP_READ_ADVANCE(Val)                                                   \
     168             :   CHECK_LINE_END(Line);                                                        \
     169             :   uint32_t Val;                                                                \
     170             :   READ_NUM((*Line), (Val));                                                    \
     171             :   Line++;
     172             : 
     173         291 :   if (Line.is_at_end())
     174             :     return success();
     175             : 
     176             :   uint32_t NumValueKinds;
     177             :   if (Line->getAsInteger(10, NumValueKinds)) {
     178             :     // No value profile data
     179             :     return success();
     180             :   }
     181          15 :   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
     182             :     return error(instrprof_error::malformed);
     183          15 :   Line++;
     184             : 
     185          47 :   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
     186          60 :     VP_READ_ADVANCE(ValueKind);
     187          20 :     if (ValueKind > IPVK_Last)
     188             :       return error(instrprof_error::malformed);
     189          60 :     VP_READ_ADVANCE(NumValueSites);
     190          20 :     if (!NumValueSites)
     191             :       continue;
     192             : 
     193          20 :     Record.reserveSites(VK, NumValueSites);
     194          94 :     for (uint32_t S = 0; S < NumValueSites; S++) {
     195         125 :       VP_READ_ADVANCE(NumValueData);
     196             : 
     197             :       std::vector<InstrProfValueData> CurrentValues;
     198         214 :       for (uint32_t V = 0; V < NumValueData; V++) {
     199          93 :         CHECK_LINE_END(Line);
     200             :         std::pair<StringRef, StringRef> VD = Line->rsplit(':');
     201             :         uint64_t TakenCount, Value;
     202          90 :         if (ValueKind == IPVK_IndirectCallTarget) {
     203             :           if (InstrProfSymtab::isExternalSymbol(VD.first)) {
     204             :             Value = 0;
     205             :           } else {
     206          70 :             if (Error E = Symtab->addFuncName(VD.first))
     207             :               return E;
     208             :             Value = IndexedInstrProf::ComputeHash(VD.first);
     209             :           }
     210             :         } else {
     211             :           READ_NUM(VD.first, Value);
     212             :         }
     213             :         READ_NUM(VD.second, TakenCount);
     214         174 :         CurrentValues.push_back({Value, TakenCount});
     215             :         Line++;
     216             :       }
     217          37 :       Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
     218             :                           nullptr);
     219             :     }
     220             :   }
     221             :   return success();
     222             : 
     223             : #undef CHECK_LINE_END
     224             : #undef READ_NUM
     225             : #undef VP_READ_ADVANCE
     226             : }
     227             : 
     228         426 : Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
     229             :   // Skip empty lines and comments.
     230         722 :   while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
     231           0 :     ++Line;
     232             :   // If we hit EOF while looking for a name, we're done.
     233         426 :   if (Line.is_at_end()) {
     234             :     return error(instrprof_error::eof);
     235             :   }
     236             : 
     237             :   // Read the function name.
     238         592 :   Record.Name = *Line++;
     239         592 :   if (Error E = Symtab->addFuncName(Record.Name))
     240           0 :     return error(std::move(E));
     241             : 
     242             :   // Read the function hash.
     243         296 :   if (Line.is_at_end())
     244             :     return error(instrprof_error::truncated);
     245         296 :   if ((Line++)->getAsInteger(0, Record.Hash))
     246             :     return error(instrprof_error::malformed);
     247             : 
     248             :   // Read the number of counters.
     249             :   uint64_t NumCounters;
     250         294 :   if (Line.is_at_end())
     251             :     return error(instrprof_error::truncated);
     252         294 :   if ((Line++)->getAsInteger(10, NumCounters))
     253             :     return error(instrprof_error::malformed);
     254         294 :   if (NumCounters == 0)
     255             :     return error(instrprof_error::malformed);
     256             : 
     257             :   // Read each counter and fill our internal storage with the values.
     258         293 :   Record.Clear();
     259         293 :   Record.Counts.reserve(NumCounters);
     260        1829 :   for (uint64_t I = 0; I < NumCounters; ++I) {
     261         770 :     if (Line.is_at_end())
     262           2 :       return error(instrprof_error::truncated);
     263             :     uint64_t Count;
     264         770 :     if ((Line++)->getAsInteger(10, Count))
     265             :       return error(instrprof_error::malformed);
     266         768 :     Record.Counts.push_back(Count);
     267             :   }
     268             : 
     269             :   // Check if value profile data exists and read it if so.
     270         582 :   if (Error E = readValueProfileData(Record))
     271           4 :     return error(std::move(E));
     272             : 
     273             :   return success();
     274             : }
     275             : 
     276             : template <class IntPtrT>
     277         302 : bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
     278         604 :   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
     279             :     return false;
     280         296 :   uint64_t Magic =
     281             :     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
     282         296 :   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
     283             :          sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
     284             : }
     285             : 
     286             : template <class IntPtrT>
     287          10 : Error RawInstrProfReader<IntPtrT>::readHeader() {
     288          10 :   if (!hasFormat(*DataBuffer))
     289             :     return error(instrprof_error::bad_magic);
     290          20 :   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
     291             :     return error(instrprof_error::bad_header);
     292             :   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
     293             :       DataBuffer->getBufferStart());
     294           8 :   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
     295           8 :   return readHeader(*Header);
     296             : }
     297             : 
     298             : template <class IntPtrT>
     299           9 : Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
     300           9 :   const char *End = DataBuffer->getBufferEnd();
     301             :   // Skip zero padding between profiles.
     302           9 :   while (CurrentPos != End && *CurrentPos == 0)
     303           0 :     ++CurrentPos;
     304             :   // If there's nothing left, we're done.
     305           9 :   if (CurrentPos == End)
     306             :     return make_error<InstrProfError>(instrprof_error::eof);
     307             :   // If there isn't enough space for another header, this is probably just
     308             :   // garbage at the end of the file.
     309           1 :   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
     310             :     return make_error<InstrProfError>(instrprof_error::malformed);
     311             :   // The writer ensures each profile is padded to start at an aligned address.
     312           1 :   if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
     313             :     return make_error<InstrProfError>(instrprof_error::malformed);
     314             :   // The magic should have the same byte order as in the previous header.
     315           1 :   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
     316           2 :   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
     317             :     return make_error<InstrProfError>(instrprof_error::bad_magic);
     318             : 
     319             :   // There's another profile to read, so we need to process the header.
     320             :   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
     321           1 :   return readHeader(*Header);
     322             : }
     323             : 
     324             : template <class IntPtrT>
     325           9 : Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
     326          18 :   if (Error E = Symtab.create(StringRef(NamesStart, NamesSize)))
     327           0 :     return error(std::move(E));
     328          55 :   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
     329          46 :     const IntPtrT FPtr = swap(I->FunctionPointer);
     330          46 :     if (!FPtr)
     331          10 :       continue;
     332          36 :     Symtab.mapAddress(FPtr, I->NameRef);
     333             :   }
     334             :   return success();
     335             : }
     336             : 
     337             : template <class IntPtrT>
     338           9 : Error RawInstrProfReader<IntPtrT>::readHeader(
     339             :     const RawInstrProf::Header &Header) {
     340          18 :   Version = swap(Header.Version);
     341           9 :   if (GET_VERSION(Version) != RawInstrProf::Version)
     342             :     return error(instrprof_error::unsupported_version);
     343             : 
     344          18 :   CountersDelta = swap(Header.CountersDelta);
     345          18 :   NamesDelta = swap(Header.NamesDelta);
     346           9 :   auto DataSize = swap(Header.DataSize);
     347           9 :   auto CountersSize = swap(Header.CountersSize);
     348          18 :   NamesSize = swap(Header.NamesSize);
     349          18 :   ValueKindLast = swap(Header.ValueKindLast);
     350             : 
     351           9 :   auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
     352             :   auto PaddingSize = getNumPaddingBytes(NamesSize);
     353             : 
     354             :   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header);
     355           9 :   ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes;
     356           9 :   ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
     357           9 :   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
     358             : 
     359             :   auto *Start = reinterpret_cast<const char *>(&Header);
     360          18 :   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
     361             :     return error(instrprof_error::bad_header);
     362             : 
     363           9 :   Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
     364           9 :       Start + DataOffset);
     365           9 :   DataEnd = Data + DataSize;
     366           9 :   CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
     367           9 :   NamesStart = Start + NamesOffset;
     368           9 :   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
     369             : 
     370          18 :   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
     371          18 :   if (Error E = createSymtab(*NewSymtab.get()))
     372             :     return E;
     373             : 
     374           9 :   Symtab = std::move(NewSymtab);
     375             :   return success();
     376             : }
     377             : 
     378             : template <class IntPtrT>
     379          46 : Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
     380          92 :   Record.Name = getName(Data->NameRef);
     381          46 :   return success();
     382             : }
     383             : 
     384             : template <class IntPtrT>
     385          46 : Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
     386          92 :   Record.Hash = swap(Data->FuncHash);
     387          46 :   return success();
     388             : }
     389             : 
     390             : template <class IntPtrT>
     391          46 : Error RawInstrProfReader<IntPtrT>::readRawCounts(
     392             :     InstrProfRecord &Record) {
     393          46 :   uint32_t NumCounters = swap(Data->NumCounters);
     394          46 :   IntPtrT CounterPtr = Data->CounterPtr;
     395          46 :   if (NumCounters == 0)
     396             :     return error(instrprof_error::malformed);
     397             : 
     398          46 :   auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters);
     399          46 :   auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
     400             : 
     401             :   // Check bounds.
     402          92 :   if (RawCounts.data() < CountersStart ||
     403          46 :       RawCounts.data() + RawCounts.size() > NamesStartAsCounter)
     404             :     return error(instrprof_error::malformed);
     405             : 
     406          46 :   if (ShouldSwapBytes) {
     407           4 :     Record.Counts.clear();
     408           4 :     Record.Counts.reserve(RawCounts.size());
     409          16 :     for (uint64_t Count : RawCounts)
     410          18 :       Record.Counts.push_back(swap(Count));
     411             :   } else
     412          84 :     Record.Counts = RawCounts;
     413             : 
     414             :   return success();
     415             : }
     416             : 
     417             : template <class IntPtrT>
     418          46 : Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
     419             :     InstrProfRecord &Record) {
     420             :   Record.clearValueData();
     421          46 :   CurValueDataSize = 0;
     422             :   // Need to match the logic in value profile dumper code in compiler-rt:
     423             :   uint32_t NumValueKinds = 0;
     424         230 :   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
     425          92 :     NumValueKinds += (Data->NumValueSites[I] != 0);
     426             : 
     427          46 :   if (!NumValueKinds)
     428             :     return success();
     429             : 
     430           0 :   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
     431             :       ValueProfData::getValueProfData(
     432           0 :           ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
     433             :           getDataEndianness());
     434             : 
     435           0 :   if (Error E = VDataPtrOrErr.takeError())
     436             :     return E;
     437             : 
     438             :   // Note that besides deserialization, this also performs the conversion for
     439             :   // indirect call targets.  The function pointers from the raw profile are
     440             :   // remapped into function name hashes.
     441           0 :   VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
     442           0 :   CurValueDataSize = VDataPtrOrErr.get()->getSize();
     443             :   return success();
     444             : }
     445             : 
     446             : template <class IntPtrT>
     447          54 : Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
     448          54 :   if (atEnd())
     449             :     // At this point, ValueDataStart field points to the next header.
     450          18 :     if (Error E = readNextHeader(getNextHeaderPos()))
     451           8 :       return error(std::move(E));
     452             : 
     453             :   // Read name ad set it in Record.
     454          92 :   if (Error E = readName(Record))
     455           0 :     return error(std::move(E));
     456             : 
     457             :   // Read FuncHash and set it in Record.
     458          92 :   if (Error E = readFuncHash(Record))
     459           0 :     return error(std::move(E));
     460             : 
     461             :   // Read raw counts and set Record.
     462          92 :   if (Error E = readRawCounts(Record))
     463           0 :     return error(std::move(E));
     464             : 
     465             :   // Read value data and set Record.
     466          92 :   if (Error E = readValueProfilingData(Record))
     467           0 :     return error(std::move(E));
     468             : 
     469             :   // Iterate.
     470             :   advanceData();
     471             :   return success();
     472             : }
     473             : 
     474             : namespace llvm {
     475             : 
     476             : template class RawInstrProfReader<uint32_t>;
     477             : template class RawInstrProfReader<uint64_t>;
     478             : 
     479             : } // end namespace llvm
     480             : 
     481             : InstrProfLookupTrait::hash_value_type
     482         749 : InstrProfLookupTrait::ComputeHash(StringRef K) {
     483        1498 :   return IndexedInstrProf::ComputeHash(HashType, K);
     484             : }
     485             : 
     486             : using data_type = InstrProfLookupTrait::data_type;
     487             : using offset_type = InstrProfLookupTrait::offset_type;
     488             : 
     489         889 : bool InstrProfLookupTrait::readValueProfilingData(
     490             :     const unsigned char *&D, const unsigned char *const End) {
     491             :   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
     492        1778 :       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
     493             : 
     494         889 :   if (VDataPtrOrErr.takeError())
     495             :     return false;
     496             : 
     497         889 :   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
     498         889 :   D += VDataPtrOrErr.get()->TotalSize;
     499             : 
     500         889 :   return true;
     501             : }
     502             : 
     503         906 : data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
     504             :                                          offset_type N) {
     505             :   using namespace support;
     506             : 
     507             :   // Check if the data is corrupt. If so, don't try to read it.
     508         906 :   if (N % sizeof(uint64_t))
     509           0 :     return data_type();
     510             : 
     511         906 :   DataBuffer.clear();
     512             :   std::vector<uint64_t> CounterBuffer;
     513             : 
     514         906 :   const unsigned char *End = D + N;
     515        2878 :   while (D < End) {
     516             :     // Read hash.
     517         986 :     if (D + sizeof(uint64_t) >= End)
     518           0 :       return data_type();
     519         986 :     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
     520             : 
     521             :     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
     522         986 :     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
     523             :     // If format version is different then read the number of counters.
     524         986 :     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
     525         962 :       if (D + sizeof(uint64_t) > End)
     526           0 :         return data_type();
     527             :       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
     528             :     }
     529             :     // Read counter values.
     530         986 :     if (D + CountsSize * sizeof(uint64_t) > End)
     531           0 :       return data_type();
     532             : 
     533             :     CounterBuffer.clear();
     534         986 :     CounterBuffer.reserve(CountsSize);
     535        7216 :     for (uint64_t J = 0; J < CountsSize; ++J)
     536        6230 :       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
     537             : 
     538         986 :     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
     539             : 
     540             :     // Read value profiling data.
     541        1875 :     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
     542         889 :         !readValueProfilingData(D, End)) {
     543             :       DataBuffer.clear();
     544           0 :       return data_type();
     545             :     }
     546             :   }
     547         906 :   return DataBuffer;
     548             : }
     549             : 
     550             : template <typename HashTableImpl>
     551         749 : Error InstrProfReaderIndex<HashTableImpl>::getRecords(
     552             :     StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
     553         749 :   auto Iter = HashTable->find(FuncName);
     554         749 :   if (Iter == HashTable->end())
     555             :     return make_error<InstrProfError>(instrprof_error::unknown_function);
     556             : 
     557         690 :   Data = (*Iter);
     558         690 :   if (Data.empty())
     559             :     return make_error<InstrProfError>(instrprof_error::malformed);
     560             : 
     561             :   return Error::success();
     562             : }
     563             : 
     564             : template <typename HashTableImpl>
     565         280 : Error InstrProfReaderIndex<HashTableImpl>::getRecords(
     566             :     ArrayRef<NamedInstrProfRecord> &Data) {
     567         280 :   if (atEnd())
     568             :     return make_error<InstrProfError>(instrprof_error::eof);
     569             : 
     570         216 :   Data = *RecordIterator;
     571             : 
     572         216 :   if (Data.empty())
     573             :     return make_error<InstrProfError>(instrprof_error::malformed);
     574             : 
     575             :   return Error::success();
     576             : }
     577             : 
     578             : template <typename HashTableImpl>
     579         408 : InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
     580             :     const unsigned char *Buckets, const unsigned char *const Payload,
     581             :     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
     582         408 :     uint64_t Version) {
     583         408 :   FormatVersion = Version;
     584        1224 :   HashTable.reset(HashTableImpl::Create(
     585             :       Buckets, Payload, Base,
     586             :       typename HashTableImpl::InfoType(HashType, Version)));
     587         408 :   RecordIterator = HashTable->data_begin();
     588         408 : }
     589             : 
     590         558 : bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
     591             :   using namespace support;
     592             : 
     593        1116 :   if (DataBuffer.getBufferSize() < 8)
     594             :     return false;
     595             :   uint64_t Magic =
     596             :       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
     597             :   // Verify that it's magical.
     598         555 :   return Magic == IndexedInstrProf::Magic;
     599             : }
     600             : 
     601             : const unsigned char *
     602         408 : IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
     603             :                                     const unsigned char *Cur) {
     604             :   using namespace IndexedInstrProf;
     605             :   using namespace support;
     606             : 
     607         408 :   if (Version >= IndexedInstrProf::Version4) {
     608             :     const IndexedInstrProf::Summary *SummaryInLE =
     609             :         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
     610             :     uint64_t NFields =
     611         371 :         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
     612             :     uint64_t NEntries =
     613         371 :         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
     614             :     uint32_t SummarySize =
     615             :         IndexedInstrProf::Summary::getSize(NFields, NEntries);
     616             :     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
     617         371 :         IndexedInstrProf::allocSummary(SummarySize);
     618             : 
     619             :     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
     620             :     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
     621       42343 :     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
     622       20986 :       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
     623             : 
     624             :     SummaryEntryVector DetailedSummary;
     625       18760 :     for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
     626             :       const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
     627        6006 :       DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
     628             :                                    Ent.NumBlocks);
     629             :     }
     630             :     // initialize InstrProfSummary using the SummaryData from disk.
     631         742 :     this->Summary = llvm::make_unique<ProfileSummary>(
     632             :         ProfileSummary::PSK_Instr, DetailedSummary,
     633         742 :         SummaryData->get(Summary::TotalBlockCount),
     634         742 :         SummaryData->get(Summary::MaxBlockCount),
     635         742 :         SummaryData->get(Summary::MaxInternalBlockCount),
     636         742 :         SummaryData->get(Summary::MaxFunctionCount),
     637         742 :         SummaryData->get(Summary::TotalNumBlocks),
     638         742 :         SummaryData->get(Summary::TotalNumFunctions));
     639         371 :     return Cur + SummarySize;
     640             :   } else {
     641             :     // For older version of profile data, we need to compute on the fly:
     642             :     using namespace IndexedInstrProf;
     643             : 
     644          37 :     InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
     645             :     // FIXME: This only computes an empty summary. Need to call addRecord for
     646             :     // all NamedInstrProfRecords to get the correct summary.
     647          74 :     this->Summary = Builder.getSummary();
     648             :     return Cur;
     649             :   }
     650             : }
     651             : 
     652         408 : Error IndexedInstrProfReader::readHeader() {
     653             :   using namespace support;
     654             : 
     655             :   const unsigned char *Start =
     656         408 :       (const unsigned char *)DataBuffer->getBufferStart();
     657             :   const unsigned char *Cur = Start;
     658         408 :   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
     659             :     return error(instrprof_error::truncated);
     660             : 
     661             :   auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
     662         408 :   Cur += sizeof(IndexedInstrProf::Header);
     663             : 
     664             :   // Check the magic number.
     665         408 :   uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
     666         408 :   if (Magic != IndexedInstrProf::Magic)
     667             :     return error(instrprof_error::bad_magic);
     668             : 
     669             :   // Read the version.
     670         408 :   uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
     671         408 :   if (GET_VERSION(FormatVersion) >
     672             :       IndexedInstrProf::ProfVersion::CurrentVersion)
     673             :     return error(instrprof_error::unsupported_version);
     674             : 
     675         408 :   Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
     676             : 
     677             :   // Read the hash type and start offset.
     678             :   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
     679         408 :       endian::byte_swap<uint64_t, little>(Header->HashType));
     680         408 :   if (HashType > IndexedInstrProf::HashT::Last)
     681             :     return error(instrprof_error::unsupported_hash_type);
     682             : 
     683         408 :   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
     684             : 
     685             :   // The rest of the file is an on disk hash table.
     686             :   InstrProfReaderIndexBase *IndexPtr = nullptr;
     687             :   IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>(
     688         408 :       Start + HashOffset, Cur, Start, HashType, FormatVersion);
     689             :   Index.reset(IndexPtr);
     690             :   return success();
     691             : }
     692             : 
     693           5 : InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
     694           5 :   if (Symtab.get())
     695             :     return *Symtab.get();
     696             : 
     697           4 :   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
     698           6 :   if (Error E = Index->populateSymtab(*NewSymtab.get())) {
     699           0 :     consumeError(error(InstrProfError::take(std::move(E))));
     700             :   }
     701             : 
     702           2 :   Symtab = std::move(NewSymtab);
     703             :   return *Symtab.get();
     704             : }
     705             : 
     706             : Expected<InstrProfRecord>
     707         749 : IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
     708             :                                            uint64_t FuncHash) {
     709         749 :   ArrayRef<NamedInstrProfRecord> Data;
     710         749 :   Error Err = Index->getRecords(FuncName, Data);
     711         749 :   if (Err)
     712             :     return std::move(Err);
     713             :   // Found it. Look for counters with the right hash.
     714         718 :   for (unsigned I = 0, E = Data.size(); I < E; ++I) {
     715             :     // Check for a match and fill the vector if there is one.
     716        1404 :     if (Data[I].Hash == FuncHash) {
     717             :       return std::move(Data[I]);
     718             :     }
     719             :   }
     720             :   return error(instrprof_error::hash_mismatch);
     721             : }
     722             : 
     723         508 : Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
     724             :                                                 uint64_t FuncHash,
     725             :                                                 std::vector<uint64_t> &Counts) {
     726        1016 :   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
     727         508 :   if (Error E = Record.takeError())
     728          48 :     return error(std::move(E));
     729             : 
     730         460 :   Counts = Record.get().Counts;
     731             :   return success();
     732             : }
     733             : 
     734         280 : Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
     735         280 :   ArrayRef<NamedInstrProfRecord> Data;
     736             : 
     737         280 :   Error E = Index->getRecords(Data);
     738         280 :   if (E)
     739          64 :     return error(std::move(E));
     740             : 
     741         216 :   Record = Data[RecordIndex++];
     742         216 :   if (RecordIndex >= Data.size()) {
     743         200 :     Index->advanceToNextKey();
     744         200 :     RecordIndex = 0;
     745             :   }
     746             :   return success();
     747             : }

Generated by: LCOV version 1.13