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