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