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