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

Generated by: LCOV version 1.13