17a7e6055SDimitry Andric //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
291bc56edSDimitry Andric //
391bc56edSDimitry Andric //                     The LLVM Compiler Infrastructure
491bc56edSDimitry Andric //
591bc56edSDimitry Andric // This file is distributed under the University of Illinois Open Source
691bc56edSDimitry Andric // License. See LICENSE.TXT for details.
791bc56edSDimitry Andric //
891bc56edSDimitry Andric //===----------------------------------------------------------------------===//
991bc56edSDimitry Andric //
1091bc56edSDimitry Andric // This file contains support for reading profiling data for clang's
1191bc56edSDimitry Andric // instrumentation based PGO and coverage.
1291bc56edSDimitry Andric //
1391bc56edSDimitry Andric //===----------------------------------------------------------------------===//
1491bc56edSDimitry Andric 
15db17bf38SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
167a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
17*b5893f02SDimitry Andric #include "llvm/ADT/DenseMap.h"
18ff0cc061SDimitry Andric #include "llvm/ADT/STLExtras.h"
197a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
207a7e6055SDimitry Andric #include "llvm/IR/ProfileSummary.h"
217a7e6055SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
227a7e6055SDimitry Andric #include "llvm/ProfileData/ProfileCommon.h"
237a7e6055SDimitry Andric #include "llvm/Support/Endian.h"
247a7e6055SDimitry Andric #include "llvm/Support/Error.h"
257a7e6055SDimitry Andric #include "llvm/Support/ErrorOr.h"
267a7e6055SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
27*b5893f02SDimitry Andric #include "llvm/Support/SymbolRemappingReader.h"
287a7e6055SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
297a7e6055SDimitry Andric #include <algorithm>
307a7e6055SDimitry Andric #include <cctype>
317a7e6055SDimitry Andric #include <cstddef>
327a7e6055SDimitry Andric #include <cstdint>
337a7e6055SDimitry Andric #include <limits>
347a7e6055SDimitry Andric #include <memory>
357a7e6055SDimitry Andric #include <system_error>
367a7e6055SDimitry Andric #include <utility>
377a7e6055SDimitry Andric #include <vector>
3891bc56edSDimitry Andric 
3991bc56edSDimitry Andric using namespace llvm;
4091bc56edSDimitry Andric 
413ca95b02SDimitry Andric static Expected<std::unique_ptr<MemoryBuffer>>
setupMemoryBuffer(const Twine & Path)423ca95b02SDimitry Andric setupMemoryBuffer(const Twine &Path) {
4391bc56edSDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
4491bc56edSDimitry Andric       MemoryBuffer::getFileOrSTDIN(Path);
4591bc56edSDimitry Andric   if (std::error_code EC = BufferOrErr.getError())
463ca95b02SDimitry Andric     return errorCodeToError(EC);
47ff0cc061SDimitry Andric   return std::move(BufferOrErr.get());
4891bc56edSDimitry Andric }
4991bc56edSDimitry Andric 
initializeReader(InstrProfReader & Reader)503ca95b02SDimitry Andric static Error initializeReader(InstrProfReader &Reader) {
5191bc56edSDimitry Andric   return Reader.readHeader();
5291bc56edSDimitry Andric }
5391bc56edSDimitry Andric 
543ca95b02SDimitry Andric Expected<std::unique_ptr<InstrProfReader>>
create(const Twine & Path)553ca95b02SDimitry Andric InstrProfReader::create(const Twine &Path) {
5691bc56edSDimitry Andric   // Set up the buffer to read.
5739d628a0SDimitry Andric   auto BufferOrError = setupMemoryBuffer(Path);
583ca95b02SDimitry Andric   if (Error E = BufferOrError.takeError())
593ca95b02SDimitry Andric     return std::move(E);
60ff0cc061SDimitry Andric   return InstrProfReader::create(std::move(BufferOrError.get()));
61ff0cc061SDimitry Andric }
6291bc56edSDimitry Andric 
633ca95b02SDimitry Andric Expected<std::unique_ptr<InstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer)64ff0cc061SDimitry Andric InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
65ff0cc061SDimitry Andric   // Sanity check the buffer.
662cab237bSDimitry Andric   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<unsigned>::max())
673ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::too_large);
68ff0cc061SDimitry Andric 
69d88c1a5aSDimitry Andric   if (Buffer->getBufferSize() == 0)
70d88c1a5aSDimitry Andric     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
71d88c1a5aSDimitry Andric 
7239d628a0SDimitry Andric   std::unique_ptr<InstrProfReader> Result;
7391bc56edSDimitry Andric   // Create the reader.
7491bc56edSDimitry Andric   if (IndexedInstrProfReader::hasFormat(*Buffer))
7591bc56edSDimitry Andric     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
7691bc56edSDimitry Andric   else if (RawInstrProfReader64::hasFormat(*Buffer))
7791bc56edSDimitry Andric     Result.reset(new RawInstrProfReader64(std::move(Buffer)));
7891bc56edSDimitry Andric   else if (RawInstrProfReader32::hasFormat(*Buffer))
7991bc56edSDimitry Andric     Result.reset(new RawInstrProfReader32(std::move(Buffer)));
807d523365SDimitry Andric   else if (TextInstrProfReader::hasFormat(*Buffer))
8191bc56edSDimitry Andric     Result.reset(new TextInstrProfReader(std::move(Buffer)));
827d523365SDimitry Andric   else
833ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
8491bc56edSDimitry Andric 
8591bc56edSDimitry Andric   // Initialize the reader and return the result.
863ca95b02SDimitry Andric   if (Error E = initializeReader(*Result))
873ca95b02SDimitry Andric     return std::move(E);
8839d628a0SDimitry Andric 
8939d628a0SDimitry Andric   return std::move(Result);
9091bc56edSDimitry Andric }
9191bc56edSDimitry Andric 
923ca95b02SDimitry Andric Expected<std::unique_ptr<IndexedInstrProfReader>>
create(const Twine & Path,const Twine & RemappingPath)93*b5893f02SDimitry Andric IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) {
9491bc56edSDimitry Andric   // Set up the buffer to read.
9539d628a0SDimitry Andric   auto BufferOrError = setupMemoryBuffer(Path);
963ca95b02SDimitry Andric   if (Error E = BufferOrError.takeError())
973ca95b02SDimitry Andric     return std::move(E);
98*b5893f02SDimitry Andric 
99*b5893f02SDimitry Andric   // Set up the remapping buffer if requested.
100*b5893f02SDimitry Andric   std::unique_ptr<MemoryBuffer> RemappingBuffer;
101*b5893f02SDimitry Andric   std::string RemappingPathStr = RemappingPath.str();
102*b5893f02SDimitry Andric   if (!RemappingPathStr.empty()) {
103*b5893f02SDimitry Andric     auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr);
104*b5893f02SDimitry Andric     if (Error E = RemappingBufferOrError.takeError())
105*b5893f02SDimitry Andric       return std::move(E);
106*b5893f02SDimitry Andric     RemappingBuffer = std::move(RemappingBufferOrError.get());
107*b5893f02SDimitry Andric   }
108*b5893f02SDimitry Andric 
109*b5893f02SDimitry Andric   return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
110*b5893f02SDimitry Andric                                         std::move(RemappingBuffer));
111ff0cc061SDimitry Andric }
11291bc56edSDimitry Andric 
1133ca95b02SDimitry Andric Expected<std::unique_ptr<IndexedInstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer,std::unique_ptr<MemoryBuffer> RemappingBuffer)114*b5893f02SDimitry Andric IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
115*b5893f02SDimitry Andric                                std::unique_ptr<MemoryBuffer> RemappingBuffer) {
116ff0cc061SDimitry Andric   // Sanity check the buffer.
1172cab237bSDimitry Andric   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<unsigned>::max())
1183ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::too_large);
119ff0cc061SDimitry Andric 
12091bc56edSDimitry Andric   // Create the reader.
12191bc56edSDimitry Andric   if (!IndexedInstrProfReader::hasFormat(*Buffer))
1223ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::bad_magic);
123*b5893f02SDimitry Andric   auto Result = llvm::make_unique<IndexedInstrProfReader>(
124*b5893f02SDimitry Andric       std::move(Buffer), std::move(RemappingBuffer));
12591bc56edSDimitry Andric 
12691bc56edSDimitry Andric   // Initialize the reader and return the result.
1273ca95b02SDimitry Andric   if (Error E = initializeReader(*Result))
1283ca95b02SDimitry Andric     return std::move(E);
129ff0cc061SDimitry Andric 
130ff0cc061SDimitry Andric   return std::move(Result);
13191bc56edSDimitry Andric }
13291bc56edSDimitry Andric 
Increment()13391bc56edSDimitry Andric void InstrProfIterator::Increment() {
1343ca95b02SDimitry Andric   if (auto E = Reader->readNextRecord(Record)) {
1353ca95b02SDimitry Andric     // Handle errors in the reader.
1363ca95b02SDimitry Andric     InstrProfError::take(std::move(E));
13791bc56edSDimitry Andric     *this = InstrProfIterator();
13891bc56edSDimitry Andric   }
1393ca95b02SDimitry Andric }
14091bc56edSDimitry Andric 
hasFormat(const MemoryBuffer & Buffer)1417d523365SDimitry Andric bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
1427d523365SDimitry Andric   // Verify that this really looks like plain ASCII text by checking a
1437d523365SDimitry Andric   // 'reasonable' number of characters (up to profile magic size).
1447d523365SDimitry Andric   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
1457d523365SDimitry Andric   StringRef buffer = Buffer.getBufferStart();
1467d523365SDimitry Andric   return count == 0 ||
1477d523365SDimitry Andric          std::all_of(buffer.begin(), buffer.begin() + count,
1484ba319b5SDimitry Andric                      [](char c) { return isPrint(c) || ::isspace(c); });
1497d523365SDimitry Andric }
1507d523365SDimitry Andric 
1513ca95b02SDimitry Andric // Read the profile variant flag from the header: ":FE" means this is a FE
1523ca95b02SDimitry Andric // generated profile. ":IR" means this is an IR level profile. Other strings
1533ca95b02SDimitry Andric // with a leading ':' will be reported an error format.
readHeader()1543ca95b02SDimitry Andric Error TextInstrProfReader::readHeader() {
1557d523365SDimitry Andric   Symtab.reset(new InstrProfSymtab());
1563ca95b02SDimitry Andric   bool IsIRInstr = false;
1573ca95b02SDimitry Andric   if (!Line->startswith(":")) {
1583ca95b02SDimitry Andric     IsIRLevelProfile = false;
1593ca95b02SDimitry Andric     return success();
1603ca95b02SDimitry Andric   }
1613ca95b02SDimitry Andric   StringRef Str = (Line)->substr(1);
1623ca95b02SDimitry Andric   if (Str.equals_lower("ir"))
1633ca95b02SDimitry Andric     IsIRInstr = true;
1643ca95b02SDimitry Andric   else if (Str.equals_lower("fe"))
1653ca95b02SDimitry Andric     IsIRInstr = false;
1663ca95b02SDimitry Andric   else
1673ca95b02SDimitry Andric     return error(instrprof_error::bad_header);
1683ca95b02SDimitry Andric 
1693ca95b02SDimitry Andric   ++Line;
1703ca95b02SDimitry Andric   IsIRLevelProfile = IsIRInstr;
1717d523365SDimitry Andric   return success();
1727d523365SDimitry Andric }
1737d523365SDimitry Andric 
1743ca95b02SDimitry Andric Error
readValueProfileData(InstrProfRecord & Record)1757d523365SDimitry Andric TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
1767d523365SDimitry Andric 
1777d523365SDimitry Andric #define CHECK_LINE_END(Line)                                                   \
1787d523365SDimitry Andric   if (Line.is_at_end())                                                        \
1797d523365SDimitry Andric     return error(instrprof_error::truncated);
1807d523365SDimitry Andric #define READ_NUM(Str, Dst)                                                     \
1817d523365SDimitry Andric   if ((Str).getAsInteger(10, (Dst)))                                           \
1827d523365SDimitry Andric     return error(instrprof_error::malformed);
1837d523365SDimitry Andric #define VP_READ_ADVANCE(Val)                                                   \
1847d523365SDimitry Andric   CHECK_LINE_END(Line);                                                        \
1857d523365SDimitry Andric   uint32_t Val;                                                                \
1867d523365SDimitry Andric   READ_NUM((*Line), (Val));                                                    \
1877d523365SDimitry Andric   Line++;
1887d523365SDimitry Andric 
1897d523365SDimitry Andric   if (Line.is_at_end())
1907d523365SDimitry Andric     return success();
1917d523365SDimitry Andric 
1927d523365SDimitry Andric   uint32_t NumValueKinds;
1937d523365SDimitry Andric   if (Line->getAsInteger(10, NumValueKinds)) {
1947d523365SDimitry Andric     // No value profile data
1957d523365SDimitry Andric     return success();
1967d523365SDimitry Andric   }
1977d523365SDimitry Andric   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
1987d523365SDimitry Andric     return error(instrprof_error::malformed);
1997d523365SDimitry Andric   Line++;
2007d523365SDimitry Andric 
2017d523365SDimitry Andric   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
2027d523365SDimitry Andric     VP_READ_ADVANCE(ValueKind);
2037d523365SDimitry Andric     if (ValueKind > IPVK_Last)
2047d523365SDimitry Andric       return error(instrprof_error::malformed);
2057d523365SDimitry Andric     VP_READ_ADVANCE(NumValueSites);
2067d523365SDimitry Andric     if (!NumValueSites)
2077d523365SDimitry Andric       continue;
2087d523365SDimitry Andric 
2097d523365SDimitry Andric     Record.reserveSites(VK, NumValueSites);
2107d523365SDimitry Andric     for (uint32_t S = 0; S < NumValueSites; S++) {
2117d523365SDimitry Andric       VP_READ_ADVANCE(NumValueData);
2127d523365SDimitry Andric 
2137d523365SDimitry Andric       std::vector<InstrProfValueData> CurrentValues;
2147d523365SDimitry Andric       for (uint32_t V = 0; V < NumValueData; V++) {
2157d523365SDimitry Andric         CHECK_LINE_END(Line);
2163ca95b02SDimitry Andric         std::pair<StringRef, StringRef> VD = Line->rsplit(':');
2177d523365SDimitry Andric         uint64_t TakenCount, Value;
2187a7e6055SDimitry Andric         if (ValueKind == IPVK_IndirectCallTarget) {
2194ba319b5SDimitry Andric           if (InstrProfSymtab::isExternalSymbol(VD.first)) {
2204ba319b5SDimitry Andric             Value = 0;
2214ba319b5SDimitry Andric           } else {
222edd7eaddSDimitry Andric             if (Error E = Symtab->addFuncName(VD.first))
223edd7eaddSDimitry Andric               return E;
2247d523365SDimitry Andric             Value = IndexedInstrProf::ComputeHash(VD.first);
2254ba319b5SDimitry Andric           }
2267d523365SDimitry Andric         } else {
2277d523365SDimitry Andric           READ_NUM(VD.first, Value);
2287d523365SDimitry Andric         }
2297d523365SDimitry Andric         READ_NUM(VD.second, TakenCount);
2307d523365SDimitry Andric         CurrentValues.push_back({Value, TakenCount});
2317d523365SDimitry Andric         Line++;
2327d523365SDimitry Andric       }
2337a7e6055SDimitry Andric       Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
2347a7e6055SDimitry Andric                           nullptr);
2357d523365SDimitry Andric     }
2367d523365SDimitry Andric   }
2377d523365SDimitry Andric   return success();
2387d523365SDimitry Andric 
2397d523365SDimitry Andric #undef CHECK_LINE_END
2407d523365SDimitry Andric #undef READ_NUM
2417d523365SDimitry Andric #undef VP_READ_ADVANCE
2427d523365SDimitry Andric }
2437d523365SDimitry Andric 
readNextRecord(NamedInstrProfRecord & Record)244c4394386SDimitry Andric Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
24539d628a0SDimitry Andric   // Skip empty lines and comments.
24639d628a0SDimitry Andric   while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
24791bc56edSDimitry Andric     ++Line;
24891bc56edSDimitry Andric   // If we hit EOF while looking for a name, we're done.
2497d523365SDimitry Andric   if (Line.is_at_end()) {
25091bc56edSDimitry Andric     return error(instrprof_error::eof);
2517d523365SDimitry Andric   }
25291bc56edSDimitry Andric 
25391bc56edSDimitry Andric   // Read the function name.
25491bc56edSDimitry Andric   Record.Name = *Line++;
255edd7eaddSDimitry Andric   if (Error E = Symtab->addFuncName(Record.Name))
2564ba319b5SDimitry Andric     return error(std::move(E));
25791bc56edSDimitry Andric 
25891bc56edSDimitry Andric   // Read the function hash.
25991bc56edSDimitry Andric   if (Line.is_at_end())
26091bc56edSDimitry Andric     return error(instrprof_error::truncated);
261ff0cc061SDimitry Andric   if ((Line++)->getAsInteger(0, Record.Hash))
26291bc56edSDimitry Andric     return error(instrprof_error::malformed);
26391bc56edSDimitry Andric 
26491bc56edSDimitry Andric   // Read the number of counters.
26591bc56edSDimitry Andric   uint64_t NumCounters;
26691bc56edSDimitry Andric   if (Line.is_at_end())
26791bc56edSDimitry Andric     return error(instrprof_error::truncated);
26891bc56edSDimitry Andric   if ((Line++)->getAsInteger(10, NumCounters))
26991bc56edSDimitry Andric     return error(instrprof_error::malformed);
27091bc56edSDimitry Andric   if (NumCounters == 0)
27191bc56edSDimitry Andric     return error(instrprof_error::malformed);
27291bc56edSDimitry Andric 
27391bc56edSDimitry Andric   // Read each counter and fill our internal storage with the values.
2747a7e6055SDimitry Andric   Record.Clear();
2753dac3a9bSDimitry Andric   Record.Counts.reserve(NumCounters);
27691bc56edSDimitry Andric   for (uint64_t I = 0; I < NumCounters; ++I) {
27791bc56edSDimitry Andric     if (Line.is_at_end())
27891bc56edSDimitry Andric       return error(instrprof_error::truncated);
27991bc56edSDimitry Andric     uint64_t Count;
28091bc56edSDimitry Andric     if ((Line++)->getAsInteger(10, Count))
28191bc56edSDimitry Andric       return error(instrprof_error::malformed);
2823dac3a9bSDimitry Andric     Record.Counts.push_back(Count);
28391bc56edSDimitry Andric   }
28491bc56edSDimitry Andric 
2857d523365SDimitry Andric   // Check if value profile data exists and read it if so.
2863ca95b02SDimitry Andric   if (Error E = readValueProfileData(Record))
2874ba319b5SDimitry Andric     return error(std::move(E));
2887d523365SDimitry Andric 
28991bc56edSDimitry Andric   return success();
29091bc56edSDimitry Andric }
29191bc56edSDimitry Andric 
29291bc56edSDimitry Andric template <class IntPtrT>
hasFormat(const MemoryBuffer & DataBuffer)29391bc56edSDimitry Andric bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
29491bc56edSDimitry Andric   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
29591bc56edSDimitry Andric     return false;
29691bc56edSDimitry Andric   uint64_t Magic =
29791bc56edSDimitry Andric     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
2987d523365SDimitry Andric   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
2997d523365SDimitry Andric          sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
30091bc56edSDimitry Andric }
30191bc56edSDimitry Andric 
30291bc56edSDimitry Andric template <class IntPtrT>
readHeader()3033ca95b02SDimitry Andric Error RawInstrProfReader<IntPtrT>::readHeader() {
30491bc56edSDimitry Andric   if (!hasFormat(*DataBuffer))
30591bc56edSDimitry Andric     return error(instrprof_error::bad_magic);
3067d523365SDimitry Andric   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
30791bc56edSDimitry Andric     return error(instrprof_error::bad_header);
3087d523365SDimitry Andric   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
3097d523365SDimitry Andric       DataBuffer->getBufferStart());
3107d523365SDimitry Andric   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
31191bc56edSDimitry Andric   return readHeader(*Header);
31291bc56edSDimitry Andric }
31391bc56edSDimitry Andric 
31491bc56edSDimitry Andric template <class IntPtrT>
readNextHeader(const char * CurrentPos)3153ca95b02SDimitry Andric Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
31691bc56edSDimitry Andric   const char *End = DataBuffer->getBufferEnd();
31791bc56edSDimitry Andric   // Skip zero padding between profiles.
31891bc56edSDimitry Andric   while (CurrentPos != End && *CurrentPos == 0)
31991bc56edSDimitry Andric     ++CurrentPos;
32091bc56edSDimitry Andric   // If there's nothing left, we're done.
32191bc56edSDimitry Andric   if (CurrentPos == End)
3223ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::eof);
32391bc56edSDimitry Andric   // If there isn't enough space for another header, this is probably just
32491bc56edSDimitry Andric   // garbage at the end of the file.
3257d523365SDimitry Andric   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
3263ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
32739d628a0SDimitry Andric   // The writer ensures each profile is padded to start at an aligned address.
328d88c1a5aSDimitry Andric   if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
3293ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
33091bc56edSDimitry Andric   // The magic should have the same byte order as in the previous header.
33191bc56edSDimitry Andric   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
3327d523365SDimitry Andric   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
3333ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::bad_magic);
33491bc56edSDimitry Andric 
33591bc56edSDimitry Andric   // There's another profile to read, so we need to process the header.
3367d523365SDimitry Andric   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
33791bc56edSDimitry Andric   return readHeader(*Header);
33891bc56edSDimitry Andric }
33991bc56edSDimitry Andric 
3407d523365SDimitry Andric template <class IntPtrT>
createSymtab(InstrProfSymtab & Symtab)3413ca95b02SDimitry Andric Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
3423ca95b02SDimitry Andric   if (Error E = Symtab.create(StringRef(NamesStart, NamesSize)))
3433ca95b02SDimitry Andric     return error(std::move(E));
3447d523365SDimitry Andric   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
3457d523365SDimitry Andric     const IntPtrT FPtr = swap(I->FunctionPointer);
3467d523365SDimitry Andric     if (!FPtr)
3477d523365SDimitry Andric       continue;
3483ca95b02SDimitry Andric     Symtab.mapAddress(FPtr, I->NameRef);
3497d523365SDimitry Andric   }
3503ca95b02SDimitry Andric   return success();
35191bc56edSDimitry Andric }
35291bc56edSDimitry Andric 
35391bc56edSDimitry Andric template <class IntPtrT>
readHeader(const RawInstrProf::Header & Header)3543ca95b02SDimitry Andric Error RawInstrProfReader<IntPtrT>::readHeader(
3553ca95b02SDimitry Andric     const RawInstrProf::Header &Header) {
3563ca95b02SDimitry Andric   Version = swap(Header.Version);
3573ca95b02SDimitry Andric   if (GET_VERSION(Version) != RawInstrProf::Version)
35891bc56edSDimitry Andric     return error(instrprof_error::unsupported_version);
35991bc56edSDimitry Andric 
36091bc56edSDimitry Andric   CountersDelta = swap(Header.CountersDelta);
36191bc56edSDimitry Andric   NamesDelta = swap(Header.NamesDelta);
36291bc56edSDimitry Andric   auto DataSize = swap(Header.DataSize);
36391bc56edSDimitry Andric   auto CountersSize = swap(Header.CountersSize);
3643ca95b02SDimitry Andric   NamesSize = swap(Header.NamesSize);
3657d523365SDimitry Andric   ValueKindLast = swap(Header.ValueKindLast);
36691bc56edSDimitry Andric 
3677d523365SDimitry Andric   auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
3687d523365SDimitry Andric   auto PaddingSize = getNumPaddingBytes(NamesSize);
3697d523365SDimitry Andric 
3707d523365SDimitry Andric   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header);
3717d523365SDimitry Andric   ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes;
37291bc56edSDimitry Andric   ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
3737d523365SDimitry Andric   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
37491bc56edSDimitry Andric 
37591bc56edSDimitry Andric   auto *Start = reinterpret_cast<const char *>(&Header);
3763ca95b02SDimitry Andric   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
37791bc56edSDimitry Andric     return error(instrprof_error::bad_header);
37891bc56edSDimitry Andric 
3797d523365SDimitry Andric   Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
3807d523365SDimitry Andric       Start + DataOffset);
38191bc56edSDimitry Andric   DataEnd = Data + DataSize;
38291bc56edSDimitry Andric   CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
38391bc56edSDimitry Andric   NamesStart = Start + NamesOffset;
3847d523365SDimitry Andric   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
38591bc56edSDimitry Andric 
3867d523365SDimitry Andric   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
3873ca95b02SDimitry Andric   if (Error E = createSymtab(*NewSymtab.get()))
3883ca95b02SDimitry Andric     return E;
3893ca95b02SDimitry Andric 
3907d523365SDimitry Andric   Symtab = std::move(NewSymtab);
39191bc56edSDimitry Andric   return success();
39291bc56edSDimitry Andric }
39391bc56edSDimitry Andric 
39491bc56edSDimitry Andric template <class IntPtrT>
readName(NamedInstrProfRecord & Record)395c4394386SDimitry Andric Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
3963ca95b02SDimitry Andric   Record.Name = getName(Data->NameRef);
3977d523365SDimitry Andric   return success();
3987d523365SDimitry Andric }
39991bc56edSDimitry Andric 
4007d523365SDimitry Andric template <class IntPtrT>
readFuncHash(NamedInstrProfRecord & Record)401c4394386SDimitry Andric Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
4027d523365SDimitry Andric   Record.Hash = swap(Data->FuncHash);
4037d523365SDimitry Andric   return success();
4047d523365SDimitry Andric }
4057d523365SDimitry Andric 
4067d523365SDimitry Andric template <class IntPtrT>
readRawCounts(InstrProfRecord & Record)4073ca95b02SDimitry Andric Error RawInstrProfReader<IntPtrT>::readRawCounts(
4087d523365SDimitry Andric     InstrProfRecord &Record) {
40991bc56edSDimitry Andric   uint32_t NumCounters = swap(Data->NumCounters);
4107d523365SDimitry Andric   IntPtrT CounterPtr = Data->CounterPtr;
41191bc56edSDimitry Andric   if (NumCounters == 0)
41291bc56edSDimitry Andric     return error(instrprof_error::malformed);
4137d523365SDimitry Andric 
4147d523365SDimitry Andric   auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters);
4157d523365SDimitry Andric   auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
41691bc56edSDimitry Andric 
41791bc56edSDimitry Andric   // Check bounds.
4187d523365SDimitry Andric   if (RawCounts.data() < CountersStart ||
41991bc56edSDimitry Andric       RawCounts.data() + RawCounts.size() > NamesStartAsCounter)
42091bc56edSDimitry Andric     return error(instrprof_error::malformed);
42191bc56edSDimitry Andric 
42291bc56edSDimitry Andric   if (ShouldSwapBytes) {
4233dac3a9bSDimitry Andric     Record.Counts.clear();
4243dac3a9bSDimitry Andric     Record.Counts.reserve(RawCounts.size());
42591bc56edSDimitry Andric     for (uint64_t Count : RawCounts)
4263dac3a9bSDimitry Andric       Record.Counts.push_back(swap(Count));
42791bc56edSDimitry Andric   } else
42891bc56edSDimitry Andric     Record.Counts = RawCounts;
42991bc56edSDimitry Andric 
4307d523365SDimitry Andric   return success();
4317d523365SDimitry Andric }
4327d523365SDimitry Andric 
4337d523365SDimitry Andric template <class IntPtrT>
readValueProfilingData(InstrProfRecord & Record)4343ca95b02SDimitry Andric Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
4353ca95b02SDimitry Andric     InstrProfRecord &Record) {
4367d523365SDimitry Andric   Record.clearValueData();
4377d523365SDimitry Andric   CurValueDataSize = 0;
4387d523365SDimitry Andric   // Need to match the logic in value profile dumper code in compiler-rt:
4397d523365SDimitry Andric   uint32_t NumValueKinds = 0;
4407d523365SDimitry Andric   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
4417d523365SDimitry Andric     NumValueKinds += (Data->NumValueSites[I] != 0);
4427d523365SDimitry Andric 
4437d523365SDimitry Andric   if (!NumValueKinds)
4447d523365SDimitry Andric     return success();
4457d523365SDimitry Andric 
4463ca95b02SDimitry Andric   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
4473ca95b02SDimitry Andric       ValueProfData::getValueProfData(
4483ca95b02SDimitry Andric           ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
4497d523365SDimitry Andric           getDataEndianness());
4507d523365SDimitry Andric 
4513ca95b02SDimitry Andric   if (Error E = VDataPtrOrErr.takeError())
4523ca95b02SDimitry Andric     return E;
4537d523365SDimitry Andric 
4543ca95b02SDimitry Andric   // Note that besides deserialization, this also performs the conversion for
4553ca95b02SDimitry Andric   // indirect call targets.  The function pointers from the raw profile are
4563ca95b02SDimitry Andric   // remapped into function name hashes.
4574ba319b5SDimitry Andric   VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
4587d523365SDimitry Andric   CurValueDataSize = VDataPtrOrErr.get()->getSize();
4597d523365SDimitry Andric   return success();
4607d523365SDimitry Andric }
4617d523365SDimitry Andric 
4627d523365SDimitry Andric template <class IntPtrT>
readNextRecord(NamedInstrProfRecord & Record)463c4394386SDimitry Andric Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
4647d523365SDimitry Andric   if (atEnd())
4653ca95b02SDimitry Andric     // At this point, ValueDataStart field points to the next header.
4663ca95b02SDimitry Andric     if (Error E = readNextHeader(getNextHeaderPos()))
4674ba319b5SDimitry Andric       return error(std::move(E));
4687d523365SDimitry Andric 
4697d523365SDimitry Andric   // Read name ad set it in Record.
4703ca95b02SDimitry Andric   if (Error E = readName(Record))
4714ba319b5SDimitry Andric     return error(std::move(E));
4727d523365SDimitry Andric 
4737d523365SDimitry Andric   // Read FuncHash and set it in Record.
4743ca95b02SDimitry Andric   if (Error E = readFuncHash(Record))
4754ba319b5SDimitry Andric     return error(std::move(E));
4767d523365SDimitry Andric 
4777d523365SDimitry Andric   // Read raw counts and set Record.
4783ca95b02SDimitry Andric   if (Error E = readRawCounts(Record))
4794ba319b5SDimitry Andric     return error(std::move(E));
4807d523365SDimitry Andric 
4817d523365SDimitry Andric   // Read value data and set Record.
4823ca95b02SDimitry Andric   if (Error E = readValueProfilingData(Record))
4834ba319b5SDimitry Andric     return error(std::move(E));
4847d523365SDimitry Andric 
48591bc56edSDimitry Andric   // Iterate.
4867d523365SDimitry Andric   advanceData();
48791bc56edSDimitry Andric   return success();
48891bc56edSDimitry Andric }
48991bc56edSDimitry Andric 
49091bc56edSDimitry Andric namespace llvm {
4917a7e6055SDimitry Andric 
49291bc56edSDimitry Andric template class RawInstrProfReader<uint32_t>;
49391bc56edSDimitry Andric template class RawInstrProfReader<uint64_t>;
4947a7e6055SDimitry Andric 
4957a7e6055SDimitry Andric } // end namespace llvm
49691bc56edSDimitry Andric 
49791bc56edSDimitry Andric InstrProfLookupTrait::hash_value_type
ComputeHash(StringRef K)49891bc56edSDimitry Andric InstrProfLookupTrait::ComputeHash(StringRef K) {
49991bc56edSDimitry Andric   return IndexedInstrProf::ComputeHash(HashType, K);
50091bc56edSDimitry Andric }
50191bc56edSDimitry Andric 
502edd7eaddSDimitry Andric using data_type = InstrProfLookupTrait::data_type;
503edd7eaddSDimitry Andric using offset_type = InstrProfLookupTrait::offset_type;
5043dac3a9bSDimitry Andric 
readValueProfilingData(const unsigned char * & D,const unsigned char * const End)5057d523365SDimitry Andric bool InstrProfLookupTrait::readValueProfilingData(
5067d523365SDimitry Andric     const unsigned char *&D, const unsigned char *const End) {
5073ca95b02SDimitry Andric   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
5087d523365SDimitry Andric       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
5097d523365SDimitry Andric 
5103ca95b02SDimitry Andric   if (VDataPtrOrErr.takeError())
5117d523365SDimitry Andric     return false;
5127d523365SDimitry Andric 
5137d523365SDimitry Andric   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
5147d523365SDimitry Andric   D += VDataPtrOrErr.get()->TotalSize;
5157d523365SDimitry Andric 
5167d523365SDimitry Andric   return true;
5177d523365SDimitry Andric }
5187d523365SDimitry Andric 
ReadData(StringRef K,const unsigned char * D,offset_type N)5193dac3a9bSDimitry Andric data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
5203dac3a9bSDimitry Andric                                          offset_type N) {
5217a7e6055SDimitry Andric   using namespace support;
5227a7e6055SDimitry Andric 
5233dac3a9bSDimitry Andric   // Check if the data is corrupt. If so, don't try to read it.
5243dac3a9bSDimitry Andric   if (N % sizeof(uint64_t))
5253dac3a9bSDimitry Andric     return data_type();
5263dac3a9bSDimitry Andric 
5273dac3a9bSDimitry Andric   DataBuffer.clear();
5283dac3a9bSDimitry Andric   std::vector<uint64_t> CounterBuffer;
5297d523365SDimitry Andric 
5307d523365SDimitry Andric   const unsigned char *End = D + N;
5317d523365SDimitry Andric   while (D < End) {
5327d523365SDimitry Andric     // Read hash.
5337d523365SDimitry Andric     if (D + sizeof(uint64_t) >= End)
5347d523365SDimitry Andric       return data_type();
5353dac3a9bSDimitry Andric     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
5363dac3a9bSDimitry Andric 
5373ca95b02SDimitry Andric     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
5387d523365SDimitry Andric     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
5397d523365SDimitry Andric     // If format version is different then read the number of counters.
5403ca95b02SDimitry Andric     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
5417d523365SDimitry Andric       if (D + sizeof(uint64_t) > End)
5423dac3a9bSDimitry Andric         return data_type();
5437d523365SDimitry Andric       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
5447d523365SDimitry Andric     }
5457d523365SDimitry Andric     // Read counter values.
5467d523365SDimitry Andric     if (D + CountsSize * sizeof(uint64_t) > End)
5473dac3a9bSDimitry Andric       return data_type();
5483dac3a9bSDimitry Andric 
5493dac3a9bSDimitry Andric     CounterBuffer.clear();
5507d523365SDimitry Andric     CounterBuffer.reserve(CountsSize);
5517d523365SDimitry Andric     for (uint64_t J = 0; J < CountsSize; ++J)
5523dac3a9bSDimitry Andric       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
5533dac3a9bSDimitry Andric 
5547d523365SDimitry Andric     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
5557d523365SDimitry Andric 
5567d523365SDimitry Andric     // Read value profiling data.
5573ca95b02SDimitry Andric     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
5583ca95b02SDimitry Andric         !readValueProfilingData(D, End)) {
5597d523365SDimitry Andric       DataBuffer.clear();
5607d523365SDimitry Andric       return data_type();
5617d523365SDimitry Andric     }
5623dac3a9bSDimitry Andric   }
5633dac3a9bSDimitry Andric   return DataBuffer;
5643dac3a9bSDimitry Andric }
5653dac3a9bSDimitry Andric 
5667d523365SDimitry Andric template <typename HashTableImpl>
getRecords(StringRef FuncName,ArrayRef<NamedInstrProfRecord> & Data)5673ca95b02SDimitry Andric Error InstrProfReaderIndex<HashTableImpl>::getRecords(
568c4394386SDimitry Andric     StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
5697d523365SDimitry Andric   auto Iter = HashTable->find(FuncName);
5707d523365SDimitry Andric   if (Iter == HashTable->end())
5713ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::unknown_function);
5727d523365SDimitry Andric 
5737d523365SDimitry Andric   Data = (*Iter);
5747d523365SDimitry Andric   if (Data.empty())
5753ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
5767d523365SDimitry Andric 
5773ca95b02SDimitry Andric   return Error::success();
5787d523365SDimitry Andric }
5797d523365SDimitry Andric 
5807d523365SDimitry Andric template <typename HashTableImpl>
getRecords(ArrayRef<NamedInstrProfRecord> & Data)5813ca95b02SDimitry Andric Error InstrProfReaderIndex<HashTableImpl>::getRecords(
582c4394386SDimitry Andric     ArrayRef<NamedInstrProfRecord> &Data) {
5837d523365SDimitry Andric   if (atEnd())
5843ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::eof);
5857d523365SDimitry Andric 
5867d523365SDimitry Andric   Data = *RecordIterator;
5877d523365SDimitry Andric 
5887d523365SDimitry Andric   if (Data.empty())
5893ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
5907d523365SDimitry Andric 
5913ca95b02SDimitry Andric   return Error::success();
5927d523365SDimitry Andric }
5937d523365SDimitry Andric 
5947d523365SDimitry Andric template <typename HashTableImpl>
InstrProfReaderIndex(const unsigned char * Buckets,const unsigned char * const Payload,const unsigned char * const Base,IndexedInstrProf::HashT HashType,uint64_t Version)5957d523365SDimitry Andric InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
5967d523365SDimitry Andric     const unsigned char *Buckets, const unsigned char *const Payload,
5977d523365SDimitry Andric     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
5987d523365SDimitry Andric     uint64_t Version) {
5997d523365SDimitry Andric   FormatVersion = Version;
6007d523365SDimitry Andric   HashTable.reset(HashTableImpl::Create(
6017d523365SDimitry Andric       Buckets, Payload, Base,
6027d523365SDimitry Andric       typename HashTableImpl::InfoType(HashType, Version)));
6037d523365SDimitry Andric   RecordIterator = HashTable->data_begin();
6047d523365SDimitry Andric }
6057d523365SDimitry Andric 
606*b5893f02SDimitry Andric namespace {
607*b5893f02SDimitry Andric /// A remapper that does not apply any remappings.
608*b5893f02SDimitry Andric class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
609*b5893f02SDimitry Andric   InstrProfReaderIndexBase &Underlying;
610*b5893f02SDimitry Andric 
611*b5893f02SDimitry Andric public:
InstrProfReaderNullRemapper(InstrProfReaderIndexBase & Underlying)612*b5893f02SDimitry Andric   InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
613*b5893f02SDimitry Andric       : Underlying(Underlying) {}
614*b5893f02SDimitry Andric 
getRecords(StringRef FuncName,ArrayRef<NamedInstrProfRecord> & Data)615*b5893f02SDimitry Andric   Error getRecords(StringRef FuncName,
616*b5893f02SDimitry Andric                    ArrayRef<NamedInstrProfRecord> &Data) override {
617*b5893f02SDimitry Andric     return Underlying.getRecords(FuncName, Data);
618*b5893f02SDimitry Andric   }
619*b5893f02SDimitry Andric };
620*b5893f02SDimitry Andric }
621*b5893f02SDimitry Andric 
622*b5893f02SDimitry Andric /// A remapper that applies remappings based on a symbol remapping file.
623*b5893f02SDimitry Andric template <typename HashTableImpl>
624*b5893f02SDimitry Andric class llvm::InstrProfReaderItaniumRemapper
625*b5893f02SDimitry Andric     : public InstrProfReaderRemapper {
626*b5893f02SDimitry Andric public:
InstrProfReaderItaniumRemapper(std::unique_ptr<MemoryBuffer> RemapBuffer,InstrProfReaderIndex<HashTableImpl> & Underlying)627*b5893f02SDimitry Andric   InstrProfReaderItaniumRemapper(
628*b5893f02SDimitry Andric       std::unique_ptr<MemoryBuffer> RemapBuffer,
629*b5893f02SDimitry Andric       InstrProfReaderIndex<HashTableImpl> &Underlying)
630*b5893f02SDimitry Andric       : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
631*b5893f02SDimitry Andric   }
632*b5893f02SDimitry Andric 
633*b5893f02SDimitry Andric   /// Extract the original function name from a PGO function name.
extractName(StringRef Name)634*b5893f02SDimitry Andric   static StringRef extractName(StringRef Name) {
635*b5893f02SDimitry Andric     // We can have multiple :-separated pieces; there can be pieces both
636*b5893f02SDimitry Andric     // before and after the mangled name. Find the first part that starts
637*b5893f02SDimitry Andric     // with '_Z'; we'll assume that's the mangled name we want.
638*b5893f02SDimitry Andric     std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
639*b5893f02SDimitry Andric     while (true) {
640*b5893f02SDimitry Andric       Parts = Parts.second.split(':');
641*b5893f02SDimitry Andric       if (Parts.first.startswith("_Z"))
642*b5893f02SDimitry Andric         return Parts.first;
643*b5893f02SDimitry Andric       if (Parts.second.empty())
644*b5893f02SDimitry Andric         return Name;
645*b5893f02SDimitry Andric     }
646*b5893f02SDimitry Andric   }
647*b5893f02SDimitry Andric 
648*b5893f02SDimitry Andric   /// Given a mangled name extracted from a PGO function name, and a new
649*b5893f02SDimitry Andric   /// form for that mangled name, reconstitute the name.
reconstituteName(StringRef OrigName,StringRef ExtractedName,StringRef Replacement,SmallVectorImpl<char> & Out)650*b5893f02SDimitry Andric   static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
651*b5893f02SDimitry Andric                                StringRef Replacement,
652*b5893f02SDimitry Andric                                SmallVectorImpl<char> &Out) {
653*b5893f02SDimitry Andric     Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
654*b5893f02SDimitry Andric     Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
655*b5893f02SDimitry Andric     Out.insert(Out.end(), Replacement.begin(), Replacement.end());
656*b5893f02SDimitry Andric     Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
657*b5893f02SDimitry Andric   }
658*b5893f02SDimitry Andric 
populateRemappings()659*b5893f02SDimitry Andric   Error populateRemappings() override {
660*b5893f02SDimitry Andric     if (Error E = Remappings.read(*RemapBuffer))
661*b5893f02SDimitry Andric       return E;
662*b5893f02SDimitry Andric     for (StringRef Name : Underlying.HashTable->keys()) {
663*b5893f02SDimitry Andric       StringRef RealName = extractName(Name);
664*b5893f02SDimitry Andric       if (auto Key = Remappings.insert(RealName)) {
665*b5893f02SDimitry Andric         // FIXME: We could theoretically map the same equivalence class to
666*b5893f02SDimitry Andric         // multiple names in the profile data. If that happens, we should
667*b5893f02SDimitry Andric         // return NamedInstrProfRecords from all of them.
668*b5893f02SDimitry Andric         MappedNames.insert({Key, RealName});
669*b5893f02SDimitry Andric       }
670*b5893f02SDimitry Andric     }
671*b5893f02SDimitry Andric     return Error::success();
672*b5893f02SDimitry Andric   }
673*b5893f02SDimitry Andric 
getRecords(StringRef FuncName,ArrayRef<NamedInstrProfRecord> & Data)674*b5893f02SDimitry Andric   Error getRecords(StringRef FuncName,
675*b5893f02SDimitry Andric                    ArrayRef<NamedInstrProfRecord> &Data) override {
676*b5893f02SDimitry Andric     StringRef RealName = extractName(FuncName);
677*b5893f02SDimitry Andric     if (auto Key = Remappings.lookup(RealName)) {
678*b5893f02SDimitry Andric       StringRef Remapped = MappedNames.lookup(Key);
679*b5893f02SDimitry Andric       if (!Remapped.empty()) {
680*b5893f02SDimitry Andric         if (RealName.begin() == FuncName.begin() &&
681*b5893f02SDimitry Andric             RealName.end() == FuncName.end())
682*b5893f02SDimitry Andric           FuncName = Remapped;
683*b5893f02SDimitry Andric         else {
684*b5893f02SDimitry Andric           // Try rebuilding the name from the given remapping.
685*b5893f02SDimitry Andric           SmallString<256> Reconstituted;
686*b5893f02SDimitry Andric           reconstituteName(FuncName, RealName, Remapped, Reconstituted);
687*b5893f02SDimitry Andric           Error E = Underlying.getRecords(Reconstituted, Data);
688*b5893f02SDimitry Andric           if (!E)
689*b5893f02SDimitry Andric             return E;
690*b5893f02SDimitry Andric 
691*b5893f02SDimitry Andric           // If we failed because the name doesn't exist, fall back to asking
692*b5893f02SDimitry Andric           // about the original name.
693*b5893f02SDimitry Andric           if (Error Unhandled = handleErrors(
694*b5893f02SDimitry Andric                   std::move(E), [](std::unique_ptr<InstrProfError> Err) {
695*b5893f02SDimitry Andric                     return Err->get() == instrprof_error::unknown_function
696*b5893f02SDimitry Andric                                ? Error::success()
697*b5893f02SDimitry Andric                                : Error(std::move(Err));
698*b5893f02SDimitry Andric                   }))
699*b5893f02SDimitry Andric             return Unhandled;
700*b5893f02SDimitry Andric         }
701*b5893f02SDimitry Andric       }
702*b5893f02SDimitry Andric     }
703*b5893f02SDimitry Andric     return Underlying.getRecords(FuncName, Data);
704*b5893f02SDimitry Andric   }
705*b5893f02SDimitry Andric 
706*b5893f02SDimitry Andric private:
707*b5893f02SDimitry Andric   /// The memory buffer containing the remapping configuration. Remappings
708*b5893f02SDimitry Andric   /// holds pointers into this buffer.
709*b5893f02SDimitry Andric   std::unique_ptr<MemoryBuffer> RemapBuffer;
710*b5893f02SDimitry Andric 
711*b5893f02SDimitry Andric   /// The mangling remapper.
712*b5893f02SDimitry Andric   SymbolRemappingReader Remappings;
713*b5893f02SDimitry Andric 
714*b5893f02SDimitry Andric   /// Mapping from mangled name keys to the name used for the key in the
715*b5893f02SDimitry Andric   /// profile data.
716*b5893f02SDimitry Andric   /// FIXME: Can we store a location within the on-disk hash table instead of
717*b5893f02SDimitry Andric   /// redoing lookup?
718*b5893f02SDimitry Andric   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
719*b5893f02SDimitry Andric 
720*b5893f02SDimitry Andric   /// The real profile data reader.
721*b5893f02SDimitry Andric   InstrProfReaderIndex<HashTableImpl> &Underlying;
722*b5893f02SDimitry Andric };
723*b5893f02SDimitry Andric 
hasFormat(const MemoryBuffer & DataBuffer)72491bc56edSDimitry Andric bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
7257a7e6055SDimitry Andric   using namespace support;
7267a7e6055SDimitry Andric 
72791bc56edSDimitry Andric   if (DataBuffer.getBufferSize() < 8)
72891bc56edSDimitry Andric     return false;
72991bc56edSDimitry Andric   uint64_t Magic =
73091bc56edSDimitry Andric       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
7317d523365SDimitry Andric   // Verify that it's magical.
73291bc56edSDimitry Andric   return Magic == IndexedInstrProf::Magic;
73391bc56edSDimitry Andric }
73491bc56edSDimitry Andric 
7353ca95b02SDimitry Andric const unsigned char *
readSummary(IndexedInstrProf::ProfVersion Version,const unsigned char * Cur)7363ca95b02SDimitry Andric IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
7373ca95b02SDimitry Andric                                     const unsigned char *Cur) {
7383ca95b02SDimitry Andric   using namespace IndexedInstrProf;
7393ca95b02SDimitry Andric   using namespace support;
7407a7e6055SDimitry Andric 
7413ca95b02SDimitry Andric   if (Version >= IndexedInstrProf::Version4) {
7423ca95b02SDimitry Andric     const IndexedInstrProf::Summary *SummaryInLE =
7433ca95b02SDimitry Andric         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
7443ca95b02SDimitry Andric     uint64_t NFields =
7453ca95b02SDimitry Andric         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
7463ca95b02SDimitry Andric     uint64_t NEntries =
7473ca95b02SDimitry Andric         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
7483ca95b02SDimitry Andric     uint32_t SummarySize =
7493ca95b02SDimitry Andric         IndexedInstrProf::Summary::getSize(NFields, NEntries);
7503ca95b02SDimitry Andric     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
7513ca95b02SDimitry Andric         IndexedInstrProf::allocSummary(SummarySize);
7523ca95b02SDimitry Andric 
7533ca95b02SDimitry Andric     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
7543ca95b02SDimitry Andric     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
7553ca95b02SDimitry Andric     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
7563ca95b02SDimitry Andric       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
7573ca95b02SDimitry Andric 
758edd7eaddSDimitry Andric     SummaryEntryVector DetailedSummary;
7593ca95b02SDimitry Andric     for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
7603ca95b02SDimitry Andric       const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
7613ca95b02SDimitry Andric       DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
7623ca95b02SDimitry Andric                                    Ent.NumBlocks);
7633ca95b02SDimitry Andric     }
7643ca95b02SDimitry Andric     // initialize InstrProfSummary using the SummaryData from disk.
7653ca95b02SDimitry Andric     this->Summary = llvm::make_unique<ProfileSummary>(
7663ca95b02SDimitry Andric         ProfileSummary::PSK_Instr, DetailedSummary,
7673ca95b02SDimitry Andric         SummaryData->get(Summary::TotalBlockCount),
7683ca95b02SDimitry Andric         SummaryData->get(Summary::MaxBlockCount),
7693ca95b02SDimitry Andric         SummaryData->get(Summary::MaxInternalBlockCount),
7703ca95b02SDimitry Andric         SummaryData->get(Summary::MaxFunctionCount),
7713ca95b02SDimitry Andric         SummaryData->get(Summary::TotalNumBlocks),
7723ca95b02SDimitry Andric         SummaryData->get(Summary::TotalNumFunctions));
7733ca95b02SDimitry Andric     return Cur + SummarySize;
7743ca95b02SDimitry Andric   } else {
7753ca95b02SDimitry Andric     // For older version of profile data, we need to compute on the fly:
7763ca95b02SDimitry Andric     using namespace IndexedInstrProf;
7777a7e6055SDimitry Andric 
7783ca95b02SDimitry Andric     InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
7793ca95b02SDimitry Andric     // FIXME: This only computes an empty summary. Need to call addRecord for
780c4394386SDimitry Andric     // all NamedInstrProfRecords to get the correct summary.
7813ca95b02SDimitry Andric     this->Summary = Builder.getSummary();
7823ca95b02SDimitry Andric     return Cur;
7833ca95b02SDimitry Andric   }
7843ca95b02SDimitry Andric }
7853ca95b02SDimitry Andric 
readHeader()7863ca95b02SDimitry Andric Error IndexedInstrProfReader::readHeader() {
7877a7e6055SDimitry Andric   using namespace support;
7887a7e6055SDimitry Andric 
78991bc56edSDimitry Andric   const unsigned char *Start =
79091bc56edSDimitry Andric       (const unsigned char *)DataBuffer->getBufferStart();
79191bc56edSDimitry Andric   const unsigned char *Cur = Start;
79291bc56edSDimitry Andric   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
79391bc56edSDimitry Andric     return error(instrprof_error::truncated);
79491bc56edSDimitry Andric 
7957d523365SDimitry Andric   auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
7967d523365SDimitry Andric   Cur += sizeof(IndexedInstrProf::Header);
7977d523365SDimitry Andric 
79891bc56edSDimitry Andric   // Check the magic number.
7997d523365SDimitry Andric   uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
80091bc56edSDimitry Andric   if (Magic != IndexedInstrProf::Magic)
80191bc56edSDimitry Andric     return error(instrprof_error::bad_magic);
80291bc56edSDimitry Andric 
80391bc56edSDimitry Andric   // Read the version.
8047d523365SDimitry Andric   uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
8053ca95b02SDimitry Andric   if (GET_VERSION(FormatVersion) >
8063ca95b02SDimitry Andric       IndexedInstrProf::ProfVersion::CurrentVersion)
80791bc56edSDimitry Andric     return error(instrprof_error::unsupported_version);
80891bc56edSDimitry Andric 
8093ca95b02SDimitry Andric   Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
81091bc56edSDimitry Andric 
81191bc56edSDimitry Andric   // Read the hash type and start offset.
81291bc56edSDimitry Andric   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
8137d523365SDimitry Andric       endian::byte_swap<uint64_t, little>(Header->HashType));
81491bc56edSDimitry Andric   if (HashType > IndexedInstrProf::HashT::Last)
81591bc56edSDimitry Andric     return error(instrprof_error::unsupported_hash_type);
8167d523365SDimitry Andric 
8177d523365SDimitry Andric   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
81891bc56edSDimitry Andric 
81991bc56edSDimitry Andric   // The rest of the file is an on disk hash table.
820*b5893f02SDimitry Andric   auto IndexPtr =
821*b5893f02SDimitry Andric       llvm::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
8227d523365SDimitry Andric           Start + HashOffset, Cur, Start, HashType, FormatVersion);
823*b5893f02SDimitry Andric 
824*b5893f02SDimitry Andric   // Load the remapping table now if requested.
825*b5893f02SDimitry Andric   if (RemappingBuffer) {
826*b5893f02SDimitry Andric     Remapper = llvm::make_unique<
827*b5893f02SDimitry Andric         InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
828*b5893f02SDimitry Andric         std::move(RemappingBuffer), *IndexPtr);
829*b5893f02SDimitry Andric     if (Error E = Remapper->populateRemappings())
830*b5893f02SDimitry Andric       return E;
831*b5893f02SDimitry Andric   } else {
832*b5893f02SDimitry Andric     Remapper = llvm::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
833*b5893f02SDimitry Andric   }
834*b5893f02SDimitry Andric   Index = std::move(IndexPtr);
835*b5893f02SDimitry Andric 
83691bc56edSDimitry Andric   return success();
83791bc56edSDimitry Andric }
83891bc56edSDimitry Andric 
getSymtab()8397d523365SDimitry Andric InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
8407d523365SDimitry Andric   if (Symtab.get())
8417d523365SDimitry Andric     return *Symtab.get();
84291bc56edSDimitry Andric 
8437d523365SDimitry Andric   std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>();
844edd7eaddSDimitry Andric   if (Error E = Index->populateSymtab(*NewSymtab.get())) {
845edd7eaddSDimitry Andric     consumeError(error(InstrProfError::take(std::move(E))));
846edd7eaddSDimitry Andric   }
8477d523365SDimitry Andric 
8487d523365SDimitry Andric   Symtab = std::move(NewSymtab);
8497d523365SDimitry Andric   return *Symtab.get();
8507d523365SDimitry Andric }
8517d523365SDimitry Andric 
8523ca95b02SDimitry Andric Expected<InstrProfRecord>
getInstrProfRecord(StringRef FuncName,uint64_t FuncHash)8537d523365SDimitry Andric IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
8547d523365SDimitry Andric                                            uint64_t FuncHash) {
855c4394386SDimitry Andric   ArrayRef<NamedInstrProfRecord> Data;
856*b5893f02SDimitry Andric   Error Err = Remapper->getRecords(FuncName, Data);
8573ca95b02SDimitry Andric   if (Err)
8583ca95b02SDimitry Andric     return std::move(Err);
85939d628a0SDimitry Andric   // Found it. Look for counters with the right hash.
8603dac3a9bSDimitry Andric   for (unsigned I = 0, E = Data.size(); I < E; ++I) {
86139d628a0SDimitry Andric     // Check for a match and fill the vector if there is one.
8623dac3a9bSDimitry Andric     if (Data[I].Hash == FuncHash) {
8637d523365SDimitry Andric       return std::move(Data[I]);
86491bc56edSDimitry Andric     }
86539d628a0SDimitry Andric   }
86639d628a0SDimitry Andric   return error(instrprof_error::hash_mismatch);
86739d628a0SDimitry Andric }
86891bc56edSDimitry Andric 
getFunctionCounts(StringRef FuncName,uint64_t FuncHash,std::vector<uint64_t> & Counts)8693ca95b02SDimitry Andric Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
8703ca95b02SDimitry Andric                                                 uint64_t FuncHash,
8717d523365SDimitry Andric                                                 std::vector<uint64_t> &Counts) {
8723ca95b02SDimitry Andric   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
8733ca95b02SDimitry Andric   if (Error E = Record.takeError())
8743ca95b02SDimitry Andric     return error(std::move(E));
87591bc56edSDimitry Andric 
8767d523365SDimitry Andric   Counts = Record.get().Counts;
8777d523365SDimitry Andric   return success();
8787d523365SDimitry Andric }
87939d628a0SDimitry Andric 
readNextRecord(NamedInstrProfRecord & Record)880c4394386SDimitry Andric Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
881c4394386SDimitry Andric   ArrayRef<NamedInstrProfRecord> Data;
8827d523365SDimitry Andric 
8833ca95b02SDimitry Andric   Error E = Index->getRecords(Data);
8843ca95b02SDimitry Andric   if (E)
8853ca95b02SDimitry Andric     return error(std::move(E));
8867d523365SDimitry Andric 
8873dac3a9bSDimitry Andric   Record = Data[RecordIndex++];
8883dac3a9bSDimitry Andric   if (RecordIndex >= Data.size()) {
8897d523365SDimitry Andric     Index->advanceToNextKey();
8903dac3a9bSDimitry Andric     RecordIndex = 0;
89139d628a0SDimitry Andric   }
89291bc56edSDimitry Andric   return success();
89391bc56edSDimitry Andric }
894