1*0b57cec5SDimitry Andric //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains support for reading profiling data for clang's
10*0b57cec5SDimitry Andric // instrumentation based PGO and coverage.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
185ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
20*0b57cec5SDimitry Andric #include "llvm/IR/ProfileSummary.h"
21*0b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
22*0b57cec5SDimitry Andric #include "llvm/ProfileData/ProfileCommon.h"
23*0b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
24*0b57cec5SDimitry Andric #include "llvm/Support/Error.h"
25*0b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
27*0b57cec5SDimitry Andric #include "llvm/Support/SymbolRemappingReader.h"
28*0b57cec5SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
29*0b57cec5SDimitry Andric #include <algorithm>
30*0b57cec5SDimitry Andric #include <cctype>
31*0b57cec5SDimitry Andric #include <cstddef>
32*0b57cec5SDimitry Andric #include <cstdint>
33*0b57cec5SDimitry Andric #include <limits>
34*0b57cec5SDimitry Andric #include <memory>
35*0b57cec5SDimitry Andric #include <system_error>
36*0b57cec5SDimitry Andric #include <utility>
37*0b57cec5SDimitry Andric #include <vector>
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric using namespace llvm;
40*0b57cec5SDimitry Andric 
41*0b57cec5SDimitry Andric static Expected<std::unique_ptr<MemoryBuffer>>
42*0b57cec5SDimitry Andric setupMemoryBuffer(const Twine &Path) {
43*0b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
44*0b57cec5SDimitry Andric       MemoryBuffer::getFileOrSTDIN(Path);
45*0b57cec5SDimitry Andric   if (std::error_code EC = BufferOrErr.getError())
46*0b57cec5SDimitry Andric     return errorCodeToError(EC);
47*0b57cec5SDimitry Andric   return std::move(BufferOrErr.get());
48*0b57cec5SDimitry Andric }
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric static Error initializeReader(InstrProfReader &Reader) {
51*0b57cec5SDimitry Andric   return Reader.readHeader();
52*0b57cec5SDimitry Andric }
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric Expected<std::unique_ptr<InstrProfReader>>
55*0b57cec5SDimitry Andric InstrProfReader::create(const Twine &Path) {
56*0b57cec5SDimitry Andric   // Set up the buffer to read.
57*0b57cec5SDimitry Andric   auto BufferOrError = setupMemoryBuffer(Path);
58*0b57cec5SDimitry Andric   if (Error E = BufferOrError.takeError())
59*0b57cec5SDimitry Andric     return std::move(E);
60*0b57cec5SDimitry Andric   return InstrProfReader::create(std::move(BufferOrError.get()));
61*0b57cec5SDimitry Andric }
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric Expected<std::unique_ptr<InstrProfReader>>
64*0b57cec5SDimitry Andric InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
65*0b57cec5SDimitry Andric   // Sanity check the buffer.
66*0b57cec5SDimitry Andric   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
67*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::too_large);
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric   if (Buffer->getBufferSize() == 0)
70*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric   std::unique_ptr<InstrProfReader> Result;
73*0b57cec5SDimitry Andric   // Create the reader.
74*0b57cec5SDimitry Andric   if (IndexedInstrProfReader::hasFormat(*Buffer))
75*0b57cec5SDimitry Andric     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
76*0b57cec5SDimitry Andric   else if (RawInstrProfReader64::hasFormat(*Buffer))
77*0b57cec5SDimitry Andric     Result.reset(new RawInstrProfReader64(std::move(Buffer)));
78*0b57cec5SDimitry Andric   else if (RawInstrProfReader32::hasFormat(*Buffer))
79*0b57cec5SDimitry Andric     Result.reset(new RawInstrProfReader32(std::move(Buffer)));
80*0b57cec5SDimitry Andric   else if (TextInstrProfReader::hasFormat(*Buffer))
81*0b57cec5SDimitry Andric     Result.reset(new TextInstrProfReader(std::move(Buffer)));
82*0b57cec5SDimitry Andric   else
83*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric   // Initialize the reader and return the result.
86*0b57cec5SDimitry Andric   if (Error E = initializeReader(*Result))
87*0b57cec5SDimitry Andric     return std::move(E);
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric   return std::move(Result);
90*0b57cec5SDimitry Andric }
91*0b57cec5SDimitry Andric 
92*0b57cec5SDimitry Andric Expected<std::unique_ptr<IndexedInstrProfReader>>
93*0b57cec5SDimitry Andric IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) {
94*0b57cec5SDimitry Andric   // Set up the buffer to read.
95*0b57cec5SDimitry Andric   auto BufferOrError = setupMemoryBuffer(Path);
96*0b57cec5SDimitry Andric   if (Error E = BufferOrError.takeError())
97*0b57cec5SDimitry Andric     return std::move(E);
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric   // Set up the remapping buffer if requested.
100*0b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> RemappingBuffer;
101*0b57cec5SDimitry Andric   std::string RemappingPathStr = RemappingPath.str();
102*0b57cec5SDimitry Andric   if (!RemappingPathStr.empty()) {
103*0b57cec5SDimitry Andric     auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr);
104*0b57cec5SDimitry Andric     if (Error E = RemappingBufferOrError.takeError())
105*0b57cec5SDimitry Andric       return std::move(E);
106*0b57cec5SDimitry Andric     RemappingBuffer = std::move(RemappingBufferOrError.get());
107*0b57cec5SDimitry Andric   }
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric   return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
110*0b57cec5SDimitry Andric                                         std::move(RemappingBuffer));
111*0b57cec5SDimitry Andric }
112*0b57cec5SDimitry Andric 
113*0b57cec5SDimitry Andric Expected<std::unique_ptr<IndexedInstrProfReader>>
114*0b57cec5SDimitry Andric IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
115*0b57cec5SDimitry Andric                                std::unique_ptr<MemoryBuffer> RemappingBuffer) {
116*0b57cec5SDimitry Andric   // Sanity check the buffer.
117*0b57cec5SDimitry Andric   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
118*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::too_large);
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric   // Create the reader.
121*0b57cec5SDimitry Andric   if (!IndexedInstrProfReader::hasFormat(*Buffer))
122*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::bad_magic);
1238bcb0991SDimitry Andric   auto Result = std::make_unique<IndexedInstrProfReader>(
124*0b57cec5SDimitry Andric       std::move(Buffer), std::move(RemappingBuffer));
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric   // Initialize the reader and return the result.
127*0b57cec5SDimitry Andric   if (Error E = initializeReader(*Result))
128*0b57cec5SDimitry Andric     return std::move(E);
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric   return std::move(Result);
131*0b57cec5SDimitry Andric }
132*0b57cec5SDimitry Andric 
133*0b57cec5SDimitry Andric void InstrProfIterator::Increment() {
134*0b57cec5SDimitry Andric   if (auto E = Reader->readNextRecord(Record)) {
135*0b57cec5SDimitry Andric     // Handle errors in the reader.
136*0b57cec5SDimitry Andric     InstrProfError::take(std::move(E));
137*0b57cec5SDimitry Andric     *this = InstrProfIterator();
138*0b57cec5SDimitry Andric   }
139*0b57cec5SDimitry Andric }
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
142*0b57cec5SDimitry Andric   // Verify that this really looks like plain ASCII text by checking a
143*0b57cec5SDimitry Andric   // 'reasonable' number of characters (up to profile magic size).
144*0b57cec5SDimitry Andric   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
145*0b57cec5SDimitry Andric   StringRef buffer = Buffer.getBufferStart();
146*0b57cec5SDimitry Andric   return count == 0 ||
147*0b57cec5SDimitry Andric          std::all_of(buffer.begin(), buffer.begin() + count,
1485ffd83dbSDimitry Andric                      [](char c) { return isPrint(c) || isSpace(c); });
149*0b57cec5SDimitry Andric }
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric // Read the profile variant flag from the header: ":FE" means this is a FE
152*0b57cec5SDimitry Andric // generated profile. ":IR" means this is an IR level profile. Other strings
153*0b57cec5SDimitry Andric // with a leading ':' will be reported an error format.
154*0b57cec5SDimitry Andric Error TextInstrProfReader::readHeader() {
155*0b57cec5SDimitry Andric   Symtab.reset(new InstrProfSymtab());
156*0b57cec5SDimitry Andric   bool IsIRInstr = false;
157*0b57cec5SDimitry Andric   if (!Line->startswith(":")) {
158*0b57cec5SDimitry Andric     IsIRLevelProfile = false;
159*0b57cec5SDimitry Andric     return success();
160*0b57cec5SDimitry Andric   }
161*0b57cec5SDimitry Andric   StringRef Str = (Line)->substr(1);
162*0b57cec5SDimitry Andric   if (Str.equals_lower("ir"))
163*0b57cec5SDimitry Andric     IsIRInstr = true;
164*0b57cec5SDimitry Andric   else if (Str.equals_lower("fe"))
165*0b57cec5SDimitry Andric     IsIRInstr = false;
166*0b57cec5SDimitry Andric   else if (Str.equals_lower("csir")) {
167*0b57cec5SDimitry Andric     IsIRInstr = true;
168*0b57cec5SDimitry Andric     HasCSIRLevelProfile = true;
169*0b57cec5SDimitry Andric   } else
170*0b57cec5SDimitry Andric     return error(instrprof_error::bad_header);
171*0b57cec5SDimitry Andric 
172*0b57cec5SDimitry Andric   ++Line;
173*0b57cec5SDimitry Andric   IsIRLevelProfile = IsIRInstr;
174*0b57cec5SDimitry Andric   return success();
175*0b57cec5SDimitry Andric }
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric Error
178*0b57cec5SDimitry Andric TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
179*0b57cec5SDimitry Andric 
180*0b57cec5SDimitry Andric #define CHECK_LINE_END(Line)                                                   \
181*0b57cec5SDimitry Andric   if (Line.is_at_end())                                                        \
182*0b57cec5SDimitry Andric     return error(instrprof_error::truncated);
183*0b57cec5SDimitry Andric #define READ_NUM(Str, Dst)                                                     \
184*0b57cec5SDimitry Andric   if ((Str).getAsInteger(10, (Dst)))                                           \
185*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
186*0b57cec5SDimitry Andric #define VP_READ_ADVANCE(Val)                                                   \
187*0b57cec5SDimitry Andric   CHECK_LINE_END(Line);                                                        \
188*0b57cec5SDimitry Andric   uint32_t Val;                                                                \
189*0b57cec5SDimitry Andric   READ_NUM((*Line), (Val));                                                    \
190*0b57cec5SDimitry Andric   Line++;
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric   if (Line.is_at_end())
193*0b57cec5SDimitry Andric     return success();
194*0b57cec5SDimitry Andric 
195*0b57cec5SDimitry Andric   uint32_t NumValueKinds;
196*0b57cec5SDimitry Andric   if (Line->getAsInteger(10, NumValueKinds)) {
197*0b57cec5SDimitry Andric     // No value profile data
198*0b57cec5SDimitry Andric     return success();
199*0b57cec5SDimitry Andric   }
200*0b57cec5SDimitry Andric   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
201*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
202*0b57cec5SDimitry Andric   Line++;
203*0b57cec5SDimitry Andric 
204*0b57cec5SDimitry Andric   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
205*0b57cec5SDimitry Andric     VP_READ_ADVANCE(ValueKind);
206*0b57cec5SDimitry Andric     if (ValueKind > IPVK_Last)
207*0b57cec5SDimitry Andric       return error(instrprof_error::malformed);
208*0b57cec5SDimitry Andric     VP_READ_ADVANCE(NumValueSites);
209*0b57cec5SDimitry Andric     if (!NumValueSites)
210*0b57cec5SDimitry Andric       continue;
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric     Record.reserveSites(VK, NumValueSites);
213*0b57cec5SDimitry Andric     for (uint32_t S = 0; S < NumValueSites; S++) {
214*0b57cec5SDimitry Andric       VP_READ_ADVANCE(NumValueData);
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric       std::vector<InstrProfValueData> CurrentValues;
217*0b57cec5SDimitry Andric       for (uint32_t V = 0; V < NumValueData; V++) {
218*0b57cec5SDimitry Andric         CHECK_LINE_END(Line);
219*0b57cec5SDimitry Andric         std::pair<StringRef, StringRef> VD = Line->rsplit(':');
220*0b57cec5SDimitry Andric         uint64_t TakenCount, Value;
221*0b57cec5SDimitry Andric         if (ValueKind == IPVK_IndirectCallTarget) {
222*0b57cec5SDimitry Andric           if (InstrProfSymtab::isExternalSymbol(VD.first)) {
223*0b57cec5SDimitry Andric             Value = 0;
224*0b57cec5SDimitry Andric           } else {
225*0b57cec5SDimitry Andric             if (Error E = Symtab->addFuncName(VD.first))
226*0b57cec5SDimitry Andric               return E;
227*0b57cec5SDimitry Andric             Value = IndexedInstrProf::ComputeHash(VD.first);
228*0b57cec5SDimitry Andric           }
229*0b57cec5SDimitry Andric         } else {
230*0b57cec5SDimitry Andric           READ_NUM(VD.first, Value);
231*0b57cec5SDimitry Andric         }
232*0b57cec5SDimitry Andric         READ_NUM(VD.second, TakenCount);
233*0b57cec5SDimitry Andric         CurrentValues.push_back({Value, TakenCount});
234*0b57cec5SDimitry Andric         Line++;
235*0b57cec5SDimitry Andric       }
236*0b57cec5SDimitry Andric       Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
237*0b57cec5SDimitry Andric                           nullptr);
238*0b57cec5SDimitry Andric     }
239*0b57cec5SDimitry Andric   }
240*0b57cec5SDimitry Andric   return success();
241*0b57cec5SDimitry Andric 
242*0b57cec5SDimitry Andric #undef CHECK_LINE_END
243*0b57cec5SDimitry Andric #undef READ_NUM
244*0b57cec5SDimitry Andric #undef VP_READ_ADVANCE
245*0b57cec5SDimitry Andric }
246*0b57cec5SDimitry Andric 
247*0b57cec5SDimitry Andric Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
248*0b57cec5SDimitry Andric   // Skip empty lines and comments.
249*0b57cec5SDimitry Andric   while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
250*0b57cec5SDimitry Andric     ++Line;
251*0b57cec5SDimitry Andric   // If we hit EOF while looking for a name, we're done.
252*0b57cec5SDimitry Andric   if (Line.is_at_end()) {
253*0b57cec5SDimitry Andric     return error(instrprof_error::eof);
254*0b57cec5SDimitry Andric   }
255*0b57cec5SDimitry Andric 
256*0b57cec5SDimitry Andric   // Read the function name.
257*0b57cec5SDimitry Andric   Record.Name = *Line++;
258*0b57cec5SDimitry Andric   if (Error E = Symtab->addFuncName(Record.Name))
259*0b57cec5SDimitry Andric     return error(std::move(E));
260*0b57cec5SDimitry Andric 
261*0b57cec5SDimitry Andric   // Read the function hash.
262*0b57cec5SDimitry Andric   if (Line.is_at_end())
263*0b57cec5SDimitry Andric     return error(instrprof_error::truncated);
264*0b57cec5SDimitry Andric   if ((Line++)->getAsInteger(0, Record.Hash))
265*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
266*0b57cec5SDimitry Andric 
267*0b57cec5SDimitry Andric   // Read the number of counters.
268*0b57cec5SDimitry Andric   uint64_t NumCounters;
269*0b57cec5SDimitry Andric   if (Line.is_at_end())
270*0b57cec5SDimitry Andric     return error(instrprof_error::truncated);
271*0b57cec5SDimitry Andric   if ((Line++)->getAsInteger(10, NumCounters))
272*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
273*0b57cec5SDimitry Andric   if (NumCounters == 0)
274*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
275*0b57cec5SDimitry Andric 
276*0b57cec5SDimitry Andric   // Read each counter and fill our internal storage with the values.
277*0b57cec5SDimitry Andric   Record.Clear();
278*0b57cec5SDimitry Andric   Record.Counts.reserve(NumCounters);
279*0b57cec5SDimitry Andric   for (uint64_t I = 0; I < NumCounters; ++I) {
280*0b57cec5SDimitry Andric     if (Line.is_at_end())
281*0b57cec5SDimitry Andric       return error(instrprof_error::truncated);
282*0b57cec5SDimitry Andric     uint64_t Count;
283*0b57cec5SDimitry Andric     if ((Line++)->getAsInteger(10, Count))
284*0b57cec5SDimitry Andric       return error(instrprof_error::malformed);
285*0b57cec5SDimitry Andric     Record.Counts.push_back(Count);
286*0b57cec5SDimitry Andric   }
287*0b57cec5SDimitry Andric 
288*0b57cec5SDimitry Andric   // Check if value profile data exists and read it if so.
289*0b57cec5SDimitry Andric   if (Error E = readValueProfileData(Record))
290*0b57cec5SDimitry Andric     return error(std::move(E));
291*0b57cec5SDimitry Andric 
292*0b57cec5SDimitry Andric   return success();
293*0b57cec5SDimitry Andric }
294*0b57cec5SDimitry Andric 
295*0b57cec5SDimitry Andric template <class IntPtrT>
296*0b57cec5SDimitry Andric bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
297*0b57cec5SDimitry Andric   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
298*0b57cec5SDimitry Andric     return false;
299*0b57cec5SDimitry Andric   uint64_t Magic =
300*0b57cec5SDimitry Andric     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
301*0b57cec5SDimitry Andric   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
302*0b57cec5SDimitry Andric          sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
303*0b57cec5SDimitry Andric }
304*0b57cec5SDimitry Andric 
305*0b57cec5SDimitry Andric template <class IntPtrT>
306*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readHeader() {
307*0b57cec5SDimitry Andric   if (!hasFormat(*DataBuffer))
308*0b57cec5SDimitry Andric     return error(instrprof_error::bad_magic);
309*0b57cec5SDimitry Andric   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
310*0b57cec5SDimitry Andric     return error(instrprof_error::bad_header);
311*0b57cec5SDimitry Andric   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
312*0b57cec5SDimitry Andric       DataBuffer->getBufferStart());
313*0b57cec5SDimitry Andric   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
314*0b57cec5SDimitry Andric   return readHeader(*Header);
315*0b57cec5SDimitry Andric }
316*0b57cec5SDimitry Andric 
317*0b57cec5SDimitry Andric template <class IntPtrT>
318*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
319*0b57cec5SDimitry Andric   const char *End = DataBuffer->getBufferEnd();
320*0b57cec5SDimitry Andric   // Skip zero padding between profiles.
321*0b57cec5SDimitry Andric   while (CurrentPos != End && *CurrentPos == 0)
322*0b57cec5SDimitry Andric     ++CurrentPos;
323*0b57cec5SDimitry Andric   // If there's nothing left, we're done.
324*0b57cec5SDimitry Andric   if (CurrentPos == End)
325*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::eof);
326*0b57cec5SDimitry Andric   // If there isn't enough space for another header, this is probably just
327*0b57cec5SDimitry Andric   // garbage at the end of the file.
328*0b57cec5SDimitry Andric   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
329*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
330*0b57cec5SDimitry Andric   // The writer ensures each profile is padded to start at an aligned address.
331*0b57cec5SDimitry Andric   if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
332*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
333*0b57cec5SDimitry Andric   // The magic should have the same byte order as in the previous header.
334*0b57cec5SDimitry Andric   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
335*0b57cec5SDimitry Andric   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
336*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::bad_magic);
337*0b57cec5SDimitry Andric 
338*0b57cec5SDimitry Andric   // There's another profile to read, so we need to process the header.
339*0b57cec5SDimitry Andric   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
340*0b57cec5SDimitry Andric   return readHeader(*Header);
341*0b57cec5SDimitry Andric }
342*0b57cec5SDimitry Andric 
343*0b57cec5SDimitry Andric template <class IntPtrT>
344*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
345*0b57cec5SDimitry Andric   if (Error E = Symtab.create(StringRef(NamesStart, NamesSize)))
346*0b57cec5SDimitry Andric     return error(std::move(E));
347*0b57cec5SDimitry Andric   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
348*0b57cec5SDimitry Andric     const IntPtrT FPtr = swap(I->FunctionPointer);
349*0b57cec5SDimitry Andric     if (!FPtr)
350*0b57cec5SDimitry Andric       continue;
351*0b57cec5SDimitry Andric     Symtab.mapAddress(FPtr, I->NameRef);
352*0b57cec5SDimitry Andric   }
353*0b57cec5SDimitry Andric   return success();
354*0b57cec5SDimitry Andric }
355*0b57cec5SDimitry Andric 
356*0b57cec5SDimitry Andric template <class IntPtrT>
357*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readHeader(
358*0b57cec5SDimitry Andric     const RawInstrProf::Header &Header) {
359*0b57cec5SDimitry Andric   Version = swap(Header.Version);
360*0b57cec5SDimitry Andric   if (GET_VERSION(Version) != RawInstrProf::Version)
361*0b57cec5SDimitry Andric     return error(instrprof_error::unsupported_version);
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric   CountersDelta = swap(Header.CountersDelta);
364*0b57cec5SDimitry Andric   NamesDelta = swap(Header.NamesDelta);
365*0b57cec5SDimitry Andric   auto DataSize = swap(Header.DataSize);
366480093f4SDimitry Andric   auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
367*0b57cec5SDimitry Andric   auto CountersSize = swap(Header.CountersSize);
368480093f4SDimitry Andric   auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
369*0b57cec5SDimitry Andric   NamesSize = swap(Header.NamesSize);
370*0b57cec5SDimitry Andric   ValueKindLast = swap(Header.ValueKindLast);
371*0b57cec5SDimitry Andric 
372*0b57cec5SDimitry Andric   auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
373*0b57cec5SDimitry Andric   auto PaddingSize = getNumPaddingBytes(NamesSize);
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header);
376480093f4SDimitry Andric   ptrdiff_t CountersOffset =
377480093f4SDimitry Andric       DataOffset + DataSizeInBytes + PaddingBytesBeforeCounters;
378480093f4SDimitry Andric   ptrdiff_t NamesOffset = CountersOffset + (sizeof(uint64_t) * CountersSize) +
379480093f4SDimitry Andric                           PaddingBytesAfterCounters;
380*0b57cec5SDimitry Andric   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
381*0b57cec5SDimitry Andric 
382*0b57cec5SDimitry Andric   auto *Start = reinterpret_cast<const char *>(&Header);
383*0b57cec5SDimitry Andric   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
384*0b57cec5SDimitry Andric     return error(instrprof_error::bad_header);
385*0b57cec5SDimitry Andric 
386*0b57cec5SDimitry Andric   Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
387*0b57cec5SDimitry Andric       Start + DataOffset);
388*0b57cec5SDimitry Andric   DataEnd = Data + DataSize;
389*0b57cec5SDimitry Andric   CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
390*0b57cec5SDimitry Andric   NamesStart = Start + NamesOffset;
391*0b57cec5SDimitry Andric   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
392*0b57cec5SDimitry Andric 
3938bcb0991SDimitry Andric   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
394*0b57cec5SDimitry Andric   if (Error E = createSymtab(*NewSymtab.get()))
395*0b57cec5SDimitry Andric     return E;
396*0b57cec5SDimitry Andric 
397*0b57cec5SDimitry Andric   Symtab = std::move(NewSymtab);
398*0b57cec5SDimitry Andric   return success();
399*0b57cec5SDimitry Andric }
400*0b57cec5SDimitry Andric 
401*0b57cec5SDimitry Andric template <class IntPtrT>
402*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
403*0b57cec5SDimitry Andric   Record.Name = getName(Data->NameRef);
404*0b57cec5SDimitry Andric   return success();
405*0b57cec5SDimitry Andric }
406*0b57cec5SDimitry Andric 
407*0b57cec5SDimitry Andric template <class IntPtrT>
408*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
409*0b57cec5SDimitry Andric   Record.Hash = swap(Data->FuncHash);
410*0b57cec5SDimitry Andric   return success();
411*0b57cec5SDimitry Andric }
412*0b57cec5SDimitry Andric 
413*0b57cec5SDimitry Andric template <class IntPtrT>
414*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readRawCounts(
415*0b57cec5SDimitry Andric     InstrProfRecord &Record) {
416*0b57cec5SDimitry Andric   uint32_t NumCounters = swap(Data->NumCounters);
417*0b57cec5SDimitry Andric   IntPtrT CounterPtr = Data->CounterPtr;
418*0b57cec5SDimitry Andric   if (NumCounters == 0)
419*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
420*0b57cec5SDimitry Andric 
421*0b57cec5SDimitry Andric   auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
4228bcb0991SDimitry Andric   ptrdiff_t MaxNumCounters = NamesStartAsCounter - CountersStart;
423*0b57cec5SDimitry Andric 
4248bcb0991SDimitry Andric   // Check bounds. Note that the counter pointer embedded in the data record
4258bcb0991SDimitry Andric   // may itself be corrupt.
4265ffd83dbSDimitry Andric   if (MaxNumCounters < 0 || NumCounters > (uint32_t)MaxNumCounters)
427*0b57cec5SDimitry Andric     return error(instrprof_error::malformed);
4288bcb0991SDimitry Andric   ptrdiff_t CounterOffset = getCounterOffset(CounterPtr);
4298bcb0991SDimitry Andric   if (CounterOffset < 0 || CounterOffset > MaxNumCounters ||
4305ffd83dbSDimitry Andric       ((uint32_t)CounterOffset + NumCounters) > (uint32_t)MaxNumCounters)
4318bcb0991SDimitry Andric     return error(instrprof_error::malformed);
4328bcb0991SDimitry Andric 
4338bcb0991SDimitry Andric   auto RawCounts = makeArrayRef(getCounter(CounterOffset), NumCounters);
434*0b57cec5SDimitry Andric 
435*0b57cec5SDimitry Andric   if (ShouldSwapBytes) {
436*0b57cec5SDimitry Andric     Record.Counts.clear();
437*0b57cec5SDimitry Andric     Record.Counts.reserve(RawCounts.size());
438*0b57cec5SDimitry Andric     for (uint64_t Count : RawCounts)
439*0b57cec5SDimitry Andric       Record.Counts.push_back(swap(Count));
440*0b57cec5SDimitry Andric   } else
441*0b57cec5SDimitry Andric     Record.Counts = RawCounts;
442*0b57cec5SDimitry Andric 
443*0b57cec5SDimitry Andric   return success();
444*0b57cec5SDimitry Andric }
445*0b57cec5SDimitry Andric 
446*0b57cec5SDimitry Andric template <class IntPtrT>
447*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
448*0b57cec5SDimitry Andric     InstrProfRecord &Record) {
449*0b57cec5SDimitry Andric   Record.clearValueData();
450*0b57cec5SDimitry Andric   CurValueDataSize = 0;
451*0b57cec5SDimitry Andric   // Need to match the logic in value profile dumper code in compiler-rt:
452*0b57cec5SDimitry Andric   uint32_t NumValueKinds = 0;
453*0b57cec5SDimitry Andric   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
454*0b57cec5SDimitry Andric     NumValueKinds += (Data->NumValueSites[I] != 0);
455*0b57cec5SDimitry Andric 
456*0b57cec5SDimitry Andric   if (!NumValueKinds)
457*0b57cec5SDimitry Andric     return success();
458*0b57cec5SDimitry Andric 
459*0b57cec5SDimitry Andric   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
460*0b57cec5SDimitry Andric       ValueProfData::getValueProfData(
461*0b57cec5SDimitry Andric           ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
462*0b57cec5SDimitry Andric           getDataEndianness());
463*0b57cec5SDimitry Andric 
464*0b57cec5SDimitry Andric   if (Error E = VDataPtrOrErr.takeError())
465*0b57cec5SDimitry Andric     return E;
466*0b57cec5SDimitry Andric 
467*0b57cec5SDimitry Andric   // Note that besides deserialization, this also performs the conversion for
468*0b57cec5SDimitry Andric   // indirect call targets.  The function pointers from the raw profile are
469*0b57cec5SDimitry Andric   // remapped into function name hashes.
470*0b57cec5SDimitry Andric   VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
471*0b57cec5SDimitry Andric   CurValueDataSize = VDataPtrOrErr.get()->getSize();
472*0b57cec5SDimitry Andric   return success();
473*0b57cec5SDimitry Andric }
474*0b57cec5SDimitry Andric 
475*0b57cec5SDimitry Andric template <class IntPtrT>
476*0b57cec5SDimitry Andric Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
477*0b57cec5SDimitry Andric   if (atEnd())
478*0b57cec5SDimitry Andric     // At this point, ValueDataStart field points to the next header.
479*0b57cec5SDimitry Andric     if (Error E = readNextHeader(getNextHeaderPos()))
480*0b57cec5SDimitry Andric       return error(std::move(E));
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric   // Read name ad set it in Record.
483*0b57cec5SDimitry Andric   if (Error E = readName(Record))
484*0b57cec5SDimitry Andric     return error(std::move(E));
485*0b57cec5SDimitry Andric 
486*0b57cec5SDimitry Andric   // Read FuncHash and set it in Record.
487*0b57cec5SDimitry Andric   if (Error E = readFuncHash(Record))
488*0b57cec5SDimitry Andric     return error(std::move(E));
489*0b57cec5SDimitry Andric 
490*0b57cec5SDimitry Andric   // Read raw counts and set Record.
491*0b57cec5SDimitry Andric   if (Error E = readRawCounts(Record))
492*0b57cec5SDimitry Andric     return error(std::move(E));
493*0b57cec5SDimitry Andric 
494*0b57cec5SDimitry Andric   // Read value data and set Record.
495*0b57cec5SDimitry Andric   if (Error E = readValueProfilingData(Record))
496*0b57cec5SDimitry Andric     return error(std::move(E));
497*0b57cec5SDimitry Andric 
498*0b57cec5SDimitry Andric   // Iterate.
499*0b57cec5SDimitry Andric   advanceData();
500*0b57cec5SDimitry Andric   return success();
501*0b57cec5SDimitry Andric }
502*0b57cec5SDimitry Andric 
503*0b57cec5SDimitry Andric namespace llvm {
504*0b57cec5SDimitry Andric 
505*0b57cec5SDimitry Andric template class RawInstrProfReader<uint32_t>;
506*0b57cec5SDimitry Andric template class RawInstrProfReader<uint64_t>;
507*0b57cec5SDimitry Andric 
508*0b57cec5SDimitry Andric } // end namespace llvm
509*0b57cec5SDimitry Andric 
510*0b57cec5SDimitry Andric InstrProfLookupTrait::hash_value_type
511*0b57cec5SDimitry Andric InstrProfLookupTrait::ComputeHash(StringRef K) {
512*0b57cec5SDimitry Andric   return IndexedInstrProf::ComputeHash(HashType, K);
513*0b57cec5SDimitry Andric }
514*0b57cec5SDimitry Andric 
515*0b57cec5SDimitry Andric using data_type = InstrProfLookupTrait::data_type;
516*0b57cec5SDimitry Andric using offset_type = InstrProfLookupTrait::offset_type;
517*0b57cec5SDimitry Andric 
518*0b57cec5SDimitry Andric bool InstrProfLookupTrait::readValueProfilingData(
519*0b57cec5SDimitry Andric     const unsigned char *&D, const unsigned char *const End) {
520*0b57cec5SDimitry Andric   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
521*0b57cec5SDimitry Andric       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
522*0b57cec5SDimitry Andric 
523*0b57cec5SDimitry Andric   if (VDataPtrOrErr.takeError())
524*0b57cec5SDimitry Andric     return false;
525*0b57cec5SDimitry Andric 
526*0b57cec5SDimitry Andric   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
527*0b57cec5SDimitry Andric   D += VDataPtrOrErr.get()->TotalSize;
528*0b57cec5SDimitry Andric 
529*0b57cec5SDimitry Andric   return true;
530*0b57cec5SDimitry Andric }
531*0b57cec5SDimitry Andric 
532*0b57cec5SDimitry Andric data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
533*0b57cec5SDimitry Andric                                          offset_type N) {
534*0b57cec5SDimitry Andric   using namespace support;
535*0b57cec5SDimitry Andric 
536*0b57cec5SDimitry Andric   // Check if the data is corrupt. If so, don't try to read it.
537*0b57cec5SDimitry Andric   if (N % sizeof(uint64_t))
538*0b57cec5SDimitry Andric     return data_type();
539*0b57cec5SDimitry Andric 
540*0b57cec5SDimitry Andric   DataBuffer.clear();
541*0b57cec5SDimitry Andric   std::vector<uint64_t> CounterBuffer;
542*0b57cec5SDimitry Andric 
543*0b57cec5SDimitry Andric   const unsigned char *End = D + N;
544*0b57cec5SDimitry Andric   while (D < End) {
545*0b57cec5SDimitry Andric     // Read hash.
546*0b57cec5SDimitry Andric     if (D + sizeof(uint64_t) >= End)
547*0b57cec5SDimitry Andric       return data_type();
548*0b57cec5SDimitry Andric     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
549*0b57cec5SDimitry Andric 
550*0b57cec5SDimitry Andric     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
551*0b57cec5SDimitry Andric     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
552*0b57cec5SDimitry Andric     // If format version is different then read the number of counters.
553*0b57cec5SDimitry Andric     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
554*0b57cec5SDimitry Andric       if (D + sizeof(uint64_t) > End)
555*0b57cec5SDimitry Andric         return data_type();
556*0b57cec5SDimitry Andric       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
557*0b57cec5SDimitry Andric     }
558*0b57cec5SDimitry Andric     // Read counter values.
559*0b57cec5SDimitry Andric     if (D + CountsSize * sizeof(uint64_t) > End)
560*0b57cec5SDimitry Andric       return data_type();
561*0b57cec5SDimitry Andric 
562*0b57cec5SDimitry Andric     CounterBuffer.clear();
563*0b57cec5SDimitry Andric     CounterBuffer.reserve(CountsSize);
564*0b57cec5SDimitry Andric     for (uint64_t J = 0; J < CountsSize; ++J)
565*0b57cec5SDimitry Andric       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
566*0b57cec5SDimitry Andric 
567*0b57cec5SDimitry Andric     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
568*0b57cec5SDimitry Andric 
569*0b57cec5SDimitry Andric     // Read value profiling data.
570*0b57cec5SDimitry Andric     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
571*0b57cec5SDimitry Andric         !readValueProfilingData(D, End)) {
572*0b57cec5SDimitry Andric       DataBuffer.clear();
573*0b57cec5SDimitry Andric       return data_type();
574*0b57cec5SDimitry Andric     }
575*0b57cec5SDimitry Andric   }
576*0b57cec5SDimitry Andric   return DataBuffer;
577*0b57cec5SDimitry Andric }
578*0b57cec5SDimitry Andric 
579*0b57cec5SDimitry Andric template <typename HashTableImpl>
580*0b57cec5SDimitry Andric Error InstrProfReaderIndex<HashTableImpl>::getRecords(
581*0b57cec5SDimitry Andric     StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
582*0b57cec5SDimitry Andric   auto Iter = HashTable->find(FuncName);
583*0b57cec5SDimitry Andric   if (Iter == HashTable->end())
584*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::unknown_function);
585*0b57cec5SDimitry Andric 
586*0b57cec5SDimitry Andric   Data = (*Iter);
587*0b57cec5SDimitry Andric   if (Data.empty())
588*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
589*0b57cec5SDimitry Andric 
590*0b57cec5SDimitry Andric   return Error::success();
591*0b57cec5SDimitry Andric }
592*0b57cec5SDimitry Andric 
593*0b57cec5SDimitry Andric template <typename HashTableImpl>
594*0b57cec5SDimitry Andric Error InstrProfReaderIndex<HashTableImpl>::getRecords(
595*0b57cec5SDimitry Andric     ArrayRef<NamedInstrProfRecord> &Data) {
596*0b57cec5SDimitry Andric   if (atEnd())
597*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::eof);
598*0b57cec5SDimitry Andric 
599*0b57cec5SDimitry Andric   Data = *RecordIterator;
600*0b57cec5SDimitry Andric 
601*0b57cec5SDimitry Andric   if (Data.empty())
602*0b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
603*0b57cec5SDimitry Andric 
604*0b57cec5SDimitry Andric   return Error::success();
605*0b57cec5SDimitry Andric }
606*0b57cec5SDimitry Andric 
607*0b57cec5SDimitry Andric template <typename HashTableImpl>
608*0b57cec5SDimitry Andric InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
609*0b57cec5SDimitry Andric     const unsigned char *Buckets, const unsigned char *const Payload,
610*0b57cec5SDimitry Andric     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
611*0b57cec5SDimitry Andric     uint64_t Version) {
612*0b57cec5SDimitry Andric   FormatVersion = Version;
613*0b57cec5SDimitry Andric   HashTable.reset(HashTableImpl::Create(
614*0b57cec5SDimitry Andric       Buckets, Payload, Base,
615*0b57cec5SDimitry Andric       typename HashTableImpl::InfoType(HashType, Version)));
616*0b57cec5SDimitry Andric   RecordIterator = HashTable->data_begin();
617*0b57cec5SDimitry Andric }
618*0b57cec5SDimitry Andric 
619*0b57cec5SDimitry Andric namespace {
620*0b57cec5SDimitry Andric /// A remapper that does not apply any remappings.
621*0b57cec5SDimitry Andric class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
622*0b57cec5SDimitry Andric   InstrProfReaderIndexBase &Underlying;
623*0b57cec5SDimitry Andric 
624*0b57cec5SDimitry Andric public:
625*0b57cec5SDimitry Andric   InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
626*0b57cec5SDimitry Andric       : Underlying(Underlying) {}
627*0b57cec5SDimitry Andric 
628*0b57cec5SDimitry Andric   Error getRecords(StringRef FuncName,
629*0b57cec5SDimitry Andric                    ArrayRef<NamedInstrProfRecord> &Data) override {
630*0b57cec5SDimitry Andric     return Underlying.getRecords(FuncName, Data);
631*0b57cec5SDimitry Andric   }
632*0b57cec5SDimitry Andric };
633*0b57cec5SDimitry Andric }
634*0b57cec5SDimitry Andric 
635*0b57cec5SDimitry Andric /// A remapper that applies remappings based on a symbol remapping file.
636*0b57cec5SDimitry Andric template <typename HashTableImpl>
637*0b57cec5SDimitry Andric class llvm::InstrProfReaderItaniumRemapper
638*0b57cec5SDimitry Andric     : public InstrProfReaderRemapper {
639*0b57cec5SDimitry Andric public:
640*0b57cec5SDimitry Andric   InstrProfReaderItaniumRemapper(
641*0b57cec5SDimitry Andric       std::unique_ptr<MemoryBuffer> RemapBuffer,
642*0b57cec5SDimitry Andric       InstrProfReaderIndex<HashTableImpl> &Underlying)
643*0b57cec5SDimitry Andric       : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
644*0b57cec5SDimitry Andric   }
645*0b57cec5SDimitry Andric 
646*0b57cec5SDimitry Andric   /// Extract the original function name from a PGO function name.
647*0b57cec5SDimitry Andric   static StringRef extractName(StringRef Name) {
648*0b57cec5SDimitry Andric     // We can have multiple :-separated pieces; there can be pieces both
649*0b57cec5SDimitry Andric     // before and after the mangled name. Find the first part that starts
650*0b57cec5SDimitry Andric     // with '_Z'; we'll assume that's the mangled name we want.
651*0b57cec5SDimitry Andric     std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
652*0b57cec5SDimitry Andric     while (true) {
653*0b57cec5SDimitry Andric       Parts = Parts.second.split(':');
654*0b57cec5SDimitry Andric       if (Parts.first.startswith("_Z"))
655*0b57cec5SDimitry Andric         return Parts.first;
656*0b57cec5SDimitry Andric       if (Parts.second.empty())
657*0b57cec5SDimitry Andric         return Name;
658*0b57cec5SDimitry Andric     }
659*0b57cec5SDimitry Andric   }
660*0b57cec5SDimitry Andric 
661*0b57cec5SDimitry Andric   /// Given a mangled name extracted from a PGO function name, and a new
662*0b57cec5SDimitry Andric   /// form for that mangled name, reconstitute the name.
663*0b57cec5SDimitry Andric   static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
664*0b57cec5SDimitry Andric                                StringRef Replacement,
665*0b57cec5SDimitry Andric                                SmallVectorImpl<char> &Out) {
666*0b57cec5SDimitry Andric     Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
667*0b57cec5SDimitry Andric     Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
668*0b57cec5SDimitry Andric     Out.insert(Out.end(), Replacement.begin(), Replacement.end());
669*0b57cec5SDimitry Andric     Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
670*0b57cec5SDimitry Andric   }
671*0b57cec5SDimitry Andric 
672*0b57cec5SDimitry Andric   Error populateRemappings() override {
673*0b57cec5SDimitry Andric     if (Error E = Remappings.read(*RemapBuffer))
674*0b57cec5SDimitry Andric       return E;
675*0b57cec5SDimitry Andric     for (StringRef Name : Underlying.HashTable->keys()) {
676*0b57cec5SDimitry Andric       StringRef RealName = extractName(Name);
677*0b57cec5SDimitry Andric       if (auto Key = Remappings.insert(RealName)) {
678*0b57cec5SDimitry Andric         // FIXME: We could theoretically map the same equivalence class to
679*0b57cec5SDimitry Andric         // multiple names in the profile data. If that happens, we should
680*0b57cec5SDimitry Andric         // return NamedInstrProfRecords from all of them.
681*0b57cec5SDimitry Andric         MappedNames.insert({Key, RealName});
682*0b57cec5SDimitry Andric       }
683*0b57cec5SDimitry Andric     }
684*0b57cec5SDimitry Andric     return Error::success();
685*0b57cec5SDimitry Andric   }
686*0b57cec5SDimitry Andric 
687*0b57cec5SDimitry Andric   Error getRecords(StringRef FuncName,
688*0b57cec5SDimitry Andric                    ArrayRef<NamedInstrProfRecord> &Data) override {
689*0b57cec5SDimitry Andric     StringRef RealName = extractName(FuncName);
690*0b57cec5SDimitry Andric     if (auto Key = Remappings.lookup(RealName)) {
691*0b57cec5SDimitry Andric       StringRef Remapped = MappedNames.lookup(Key);
692*0b57cec5SDimitry Andric       if (!Remapped.empty()) {
693*0b57cec5SDimitry Andric         if (RealName.begin() == FuncName.begin() &&
694*0b57cec5SDimitry Andric             RealName.end() == FuncName.end())
695*0b57cec5SDimitry Andric           FuncName = Remapped;
696*0b57cec5SDimitry Andric         else {
697*0b57cec5SDimitry Andric           // Try rebuilding the name from the given remapping.
698*0b57cec5SDimitry Andric           SmallString<256> Reconstituted;
699*0b57cec5SDimitry Andric           reconstituteName(FuncName, RealName, Remapped, Reconstituted);
700*0b57cec5SDimitry Andric           Error E = Underlying.getRecords(Reconstituted, Data);
701*0b57cec5SDimitry Andric           if (!E)
702*0b57cec5SDimitry Andric             return E;
703*0b57cec5SDimitry Andric 
704*0b57cec5SDimitry Andric           // If we failed because the name doesn't exist, fall back to asking
705*0b57cec5SDimitry Andric           // about the original name.
706*0b57cec5SDimitry Andric           if (Error Unhandled = handleErrors(
707*0b57cec5SDimitry Andric                   std::move(E), [](std::unique_ptr<InstrProfError> Err) {
708*0b57cec5SDimitry Andric                     return Err->get() == instrprof_error::unknown_function
709*0b57cec5SDimitry Andric                                ? Error::success()
710*0b57cec5SDimitry Andric                                : Error(std::move(Err));
711*0b57cec5SDimitry Andric                   }))
712*0b57cec5SDimitry Andric             return Unhandled;
713*0b57cec5SDimitry Andric         }
714*0b57cec5SDimitry Andric       }
715*0b57cec5SDimitry Andric     }
716*0b57cec5SDimitry Andric     return Underlying.getRecords(FuncName, Data);
717*0b57cec5SDimitry Andric   }
718*0b57cec5SDimitry Andric 
719*0b57cec5SDimitry Andric private:
720*0b57cec5SDimitry Andric   /// The memory buffer containing the remapping configuration. Remappings
721*0b57cec5SDimitry Andric   /// holds pointers into this buffer.
722*0b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> RemapBuffer;
723*0b57cec5SDimitry Andric 
724*0b57cec5SDimitry Andric   /// The mangling remapper.
725*0b57cec5SDimitry Andric   SymbolRemappingReader Remappings;
726*0b57cec5SDimitry Andric 
727*0b57cec5SDimitry Andric   /// Mapping from mangled name keys to the name used for the key in the
728*0b57cec5SDimitry Andric   /// profile data.
729*0b57cec5SDimitry Andric   /// FIXME: Can we store a location within the on-disk hash table instead of
730*0b57cec5SDimitry Andric   /// redoing lookup?
731*0b57cec5SDimitry Andric   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
732*0b57cec5SDimitry Andric 
733*0b57cec5SDimitry Andric   /// The real profile data reader.
734*0b57cec5SDimitry Andric   InstrProfReaderIndex<HashTableImpl> &Underlying;
735*0b57cec5SDimitry Andric };
736*0b57cec5SDimitry Andric 
737*0b57cec5SDimitry Andric bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
738*0b57cec5SDimitry Andric   using namespace support;
739*0b57cec5SDimitry Andric 
740*0b57cec5SDimitry Andric   if (DataBuffer.getBufferSize() < 8)
741*0b57cec5SDimitry Andric     return false;
742*0b57cec5SDimitry Andric   uint64_t Magic =
743*0b57cec5SDimitry Andric       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
744*0b57cec5SDimitry Andric   // Verify that it's magical.
745*0b57cec5SDimitry Andric   return Magic == IndexedInstrProf::Magic;
746*0b57cec5SDimitry Andric }
747*0b57cec5SDimitry Andric 
748*0b57cec5SDimitry Andric const unsigned char *
749*0b57cec5SDimitry Andric IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
750*0b57cec5SDimitry Andric                                     const unsigned char *Cur, bool UseCS) {
751*0b57cec5SDimitry Andric   using namespace IndexedInstrProf;
752*0b57cec5SDimitry Andric   using namespace support;
753*0b57cec5SDimitry Andric 
754*0b57cec5SDimitry Andric   if (Version >= IndexedInstrProf::Version4) {
755*0b57cec5SDimitry Andric     const IndexedInstrProf::Summary *SummaryInLE =
756*0b57cec5SDimitry Andric         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
757*0b57cec5SDimitry Andric     uint64_t NFields =
758*0b57cec5SDimitry Andric         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
759*0b57cec5SDimitry Andric     uint64_t NEntries =
760*0b57cec5SDimitry Andric         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
761*0b57cec5SDimitry Andric     uint32_t SummarySize =
762*0b57cec5SDimitry Andric         IndexedInstrProf::Summary::getSize(NFields, NEntries);
763*0b57cec5SDimitry Andric     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
764*0b57cec5SDimitry Andric         IndexedInstrProf::allocSummary(SummarySize);
765*0b57cec5SDimitry Andric 
766*0b57cec5SDimitry Andric     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
767*0b57cec5SDimitry Andric     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
768*0b57cec5SDimitry Andric     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
769*0b57cec5SDimitry Andric       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
770*0b57cec5SDimitry Andric 
771*0b57cec5SDimitry Andric     SummaryEntryVector DetailedSummary;
772*0b57cec5SDimitry Andric     for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
773*0b57cec5SDimitry Andric       const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
774*0b57cec5SDimitry Andric       DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
775*0b57cec5SDimitry Andric                                    Ent.NumBlocks);
776*0b57cec5SDimitry Andric     }
777*0b57cec5SDimitry Andric     std::unique_ptr<llvm::ProfileSummary> &Summary =
778*0b57cec5SDimitry Andric         UseCS ? this->CS_Summary : this->Summary;
779*0b57cec5SDimitry Andric 
780*0b57cec5SDimitry Andric     // initialize InstrProfSummary using the SummaryData from disk.
7818bcb0991SDimitry Andric     Summary = std::make_unique<ProfileSummary>(
782*0b57cec5SDimitry Andric         UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
783*0b57cec5SDimitry Andric         DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
784*0b57cec5SDimitry Andric         SummaryData->get(Summary::MaxBlockCount),
785*0b57cec5SDimitry Andric         SummaryData->get(Summary::MaxInternalBlockCount),
786*0b57cec5SDimitry Andric         SummaryData->get(Summary::MaxFunctionCount),
787*0b57cec5SDimitry Andric         SummaryData->get(Summary::TotalNumBlocks),
788*0b57cec5SDimitry Andric         SummaryData->get(Summary::TotalNumFunctions));
789*0b57cec5SDimitry Andric     return Cur + SummarySize;
790*0b57cec5SDimitry Andric   } else {
7918bcb0991SDimitry Andric     // The older versions do not support a profile summary. This just computes
7928bcb0991SDimitry Andric     // an empty summary, which will not result in accurate hot/cold detection.
7938bcb0991SDimitry Andric     // We would need to call addRecord for all NamedInstrProfRecords to get the
7948bcb0991SDimitry Andric     // correct summary. However, this version is old (prior to early 2016) and
7958bcb0991SDimitry Andric     // has not been supporting an accurate summary for several years.
796*0b57cec5SDimitry Andric     InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
7978bcb0991SDimitry Andric     Summary = Builder.getSummary();
798*0b57cec5SDimitry Andric     return Cur;
799*0b57cec5SDimitry Andric   }
800*0b57cec5SDimitry Andric }
801*0b57cec5SDimitry Andric 
802*0b57cec5SDimitry Andric Error IndexedInstrProfReader::readHeader() {
803*0b57cec5SDimitry Andric   using namespace support;
804*0b57cec5SDimitry Andric 
805*0b57cec5SDimitry Andric   const unsigned char *Start =
806*0b57cec5SDimitry Andric       (const unsigned char *)DataBuffer->getBufferStart();
807*0b57cec5SDimitry Andric   const unsigned char *Cur = Start;
808*0b57cec5SDimitry Andric   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
809*0b57cec5SDimitry Andric     return error(instrprof_error::truncated);
810*0b57cec5SDimitry Andric 
811*0b57cec5SDimitry Andric   auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
812*0b57cec5SDimitry Andric   Cur += sizeof(IndexedInstrProf::Header);
813*0b57cec5SDimitry Andric 
814*0b57cec5SDimitry Andric   // Check the magic number.
815*0b57cec5SDimitry Andric   uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
816*0b57cec5SDimitry Andric   if (Magic != IndexedInstrProf::Magic)
817*0b57cec5SDimitry Andric     return error(instrprof_error::bad_magic);
818*0b57cec5SDimitry Andric 
819*0b57cec5SDimitry Andric   // Read the version.
820*0b57cec5SDimitry Andric   uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
821*0b57cec5SDimitry Andric   if (GET_VERSION(FormatVersion) >
822*0b57cec5SDimitry Andric       IndexedInstrProf::ProfVersion::CurrentVersion)
823*0b57cec5SDimitry Andric     return error(instrprof_error::unsupported_version);
824*0b57cec5SDimitry Andric 
825*0b57cec5SDimitry Andric   Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
826*0b57cec5SDimitry Andric                     /* UseCS */ false);
827*0b57cec5SDimitry Andric   if (FormatVersion & VARIANT_MASK_CSIR_PROF)
828*0b57cec5SDimitry Andric     Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
829*0b57cec5SDimitry Andric                       /* UseCS */ true);
830*0b57cec5SDimitry Andric 
831*0b57cec5SDimitry Andric   // Read the hash type and start offset.
832*0b57cec5SDimitry Andric   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
833*0b57cec5SDimitry Andric       endian::byte_swap<uint64_t, little>(Header->HashType));
834*0b57cec5SDimitry Andric   if (HashType > IndexedInstrProf::HashT::Last)
835*0b57cec5SDimitry Andric     return error(instrprof_error::unsupported_hash_type);
836*0b57cec5SDimitry Andric 
837*0b57cec5SDimitry Andric   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
838*0b57cec5SDimitry Andric 
839*0b57cec5SDimitry Andric   // The rest of the file is an on disk hash table.
840*0b57cec5SDimitry Andric   auto IndexPtr =
8418bcb0991SDimitry Andric       std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
842*0b57cec5SDimitry Andric           Start + HashOffset, Cur, Start, HashType, FormatVersion);
843*0b57cec5SDimitry Andric 
844*0b57cec5SDimitry Andric   // Load the remapping table now if requested.
845*0b57cec5SDimitry Andric   if (RemappingBuffer) {
8468bcb0991SDimitry Andric     Remapper = std::make_unique<
847*0b57cec5SDimitry Andric         InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
848*0b57cec5SDimitry Andric         std::move(RemappingBuffer), *IndexPtr);
849*0b57cec5SDimitry Andric     if (Error E = Remapper->populateRemappings())
850*0b57cec5SDimitry Andric       return E;
851*0b57cec5SDimitry Andric   } else {
8528bcb0991SDimitry Andric     Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
853*0b57cec5SDimitry Andric   }
854*0b57cec5SDimitry Andric   Index = std::move(IndexPtr);
855*0b57cec5SDimitry Andric 
856*0b57cec5SDimitry Andric   return success();
857*0b57cec5SDimitry Andric }
858*0b57cec5SDimitry Andric 
859*0b57cec5SDimitry Andric InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
860*0b57cec5SDimitry Andric   if (Symtab.get())
861*0b57cec5SDimitry Andric     return *Symtab.get();
862*0b57cec5SDimitry Andric 
8638bcb0991SDimitry Andric   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
864*0b57cec5SDimitry Andric   if (Error E = Index->populateSymtab(*NewSymtab.get())) {
865*0b57cec5SDimitry Andric     consumeError(error(InstrProfError::take(std::move(E))));
866*0b57cec5SDimitry Andric   }
867*0b57cec5SDimitry Andric 
868*0b57cec5SDimitry Andric   Symtab = std::move(NewSymtab);
869*0b57cec5SDimitry Andric   return *Symtab.get();
870*0b57cec5SDimitry Andric }
871*0b57cec5SDimitry Andric 
872*0b57cec5SDimitry Andric Expected<InstrProfRecord>
873*0b57cec5SDimitry Andric IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
874*0b57cec5SDimitry Andric                                            uint64_t FuncHash) {
875*0b57cec5SDimitry Andric   ArrayRef<NamedInstrProfRecord> Data;
876*0b57cec5SDimitry Andric   Error Err = Remapper->getRecords(FuncName, Data);
877*0b57cec5SDimitry Andric   if (Err)
878*0b57cec5SDimitry Andric     return std::move(Err);
879*0b57cec5SDimitry Andric   // Found it. Look for counters with the right hash.
880*0b57cec5SDimitry Andric   for (unsigned I = 0, E = Data.size(); I < E; ++I) {
881*0b57cec5SDimitry Andric     // Check for a match and fill the vector if there is one.
882*0b57cec5SDimitry Andric     if (Data[I].Hash == FuncHash) {
883*0b57cec5SDimitry Andric       return std::move(Data[I]);
884*0b57cec5SDimitry Andric     }
885*0b57cec5SDimitry Andric   }
886*0b57cec5SDimitry Andric   return error(instrprof_error::hash_mismatch);
887*0b57cec5SDimitry Andric }
888*0b57cec5SDimitry Andric 
889*0b57cec5SDimitry Andric Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
890*0b57cec5SDimitry Andric                                                 uint64_t FuncHash,
891*0b57cec5SDimitry Andric                                                 std::vector<uint64_t> &Counts) {
892*0b57cec5SDimitry Andric   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
893*0b57cec5SDimitry Andric   if (Error E = Record.takeError())
894*0b57cec5SDimitry Andric     return error(std::move(E));
895*0b57cec5SDimitry Andric 
896*0b57cec5SDimitry Andric   Counts = Record.get().Counts;
897*0b57cec5SDimitry Andric   return success();
898*0b57cec5SDimitry Andric }
899*0b57cec5SDimitry Andric 
900*0b57cec5SDimitry Andric Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
901*0b57cec5SDimitry Andric   ArrayRef<NamedInstrProfRecord> Data;
902*0b57cec5SDimitry Andric 
903*0b57cec5SDimitry Andric   Error E = Index->getRecords(Data);
904*0b57cec5SDimitry Andric   if (E)
905*0b57cec5SDimitry Andric     return error(std::move(E));
906*0b57cec5SDimitry Andric 
907*0b57cec5SDimitry Andric   Record = Data[RecordIndex++];
908*0b57cec5SDimitry Andric   if (RecordIndex >= Data.size()) {
909*0b57cec5SDimitry Andric     Index->advanceToNextKey();
910*0b57cec5SDimitry Andric     RecordIndex = 0;
911*0b57cec5SDimitry Andric   }
912*0b57cec5SDimitry Andric   return success();
913*0b57cec5SDimitry Andric }
914*0b57cec5SDimitry Andric 
9158bcb0991SDimitry Andric void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) {
916*0b57cec5SDimitry Andric   uint64_t NumFuncs = 0;
917*0b57cec5SDimitry Andric   for (const auto &Func : *this) {
918*0b57cec5SDimitry Andric     if (isIRLevelProfile()) {
919*0b57cec5SDimitry Andric       bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
920*0b57cec5SDimitry Andric       if (FuncIsCS != IsCS)
921*0b57cec5SDimitry Andric         continue;
922*0b57cec5SDimitry Andric     }
9238bcb0991SDimitry Andric     Func.accumulateCounts(Sum);
924*0b57cec5SDimitry Andric     ++NumFuncs;
925*0b57cec5SDimitry Andric   }
926*0b57cec5SDimitry Andric   Sum.NumEntries = NumFuncs;
927*0b57cec5SDimitry Andric }
928