InstrProfReader.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=// 236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// The LLVM Compiler Infrastructure 436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file is distributed under the University of Illinois Open Source 636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// License. See LICENSE.TXT for details. 736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===// 936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file contains support for reading profiling data for clang's 1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// instrumentation based PGO and coverage. 1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===// 1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ProfileData/InstrProfReader.h" 1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ProfileData/InstrProf.h" 1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <cassert> 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesusing namespace llvm; 2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineserror_code InstrProfReader::create(std::string Path, 2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<InstrProfReader> &Result) { 2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<MemoryBuffer> Buffer; 2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer)) 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Sanity check the file. 2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return instrprof_error::too_large; 3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Create the reader. 3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (RawInstrProfReader64::hasFormat(*Buffer)) 3436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result.reset(new RawInstrProfReader64(std::move(Buffer))); 3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (RawInstrProfReader32::hasFormat(*Buffer)) 3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result.reset(new RawInstrProfReader32(std::move(Buffer))); 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result.reset(new TextInstrProfReader(std::move(Buffer))); 3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Read the header and return the result. 4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Result->readHeader(); 4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid InstrProfIterator::Increment() { 4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Reader->readNextRecord(Record)) 4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *this = InstrProfIterator(); 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineserror_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { 5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Skip empty lines. 5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines while (!Line.is_at_end() && Line->empty()) 5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Line; 5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // If we hit EOF while looking for a name, we're done. 5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Line.is_at_end()) 5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::eof); 5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Read the function name. 5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Record.Name = *Line++; 5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Read the function hash. 6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Line.is_at_end()) 6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::truncated); 6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((Line++)->getAsInteger(10, Record.Hash)) 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::malformed); 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Read the number of counters. 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t NumCounters; 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Line.is_at_end()) 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::truncated); 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((Line++)->getAsInteger(10, NumCounters)) 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::malformed); 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Read each counter and fill our internal storage with the values. 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Counts.clear(); 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Counts.reserve(NumCounters); 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (uint64_t I = 0; I < NumCounters; ++I) { 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Line.is_at_end()) 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::truncated); 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Count; 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((Line++)->getAsInteger(10, Count)) 8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::malformed); 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Counts.push_back(Count); 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Give the record a reference to our internal counter storage. 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Record.Counts = Counts; 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return success(); 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <class IntPtrT> 9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint64_t getRawMagic(); 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <> 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesuint64_t getRawMagic<uint64_t>() { 9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t(255) << 56 | 9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('l') << 48 | 9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('p') << 40 | 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('r') << 32 | 10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('o') << 24 | 10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('f') << 16 | 10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('r') << 8 | 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t(129); 10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <> 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesuint64_t getRawMagic<uint32_t>() { 10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t(255) << 56 | 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('l') << 48 | 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('p') << 40 | 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('r') << 32 | 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('o') << 24 | 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('f') << 16 | 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t('R') << 8 | 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t(129); 11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <class IntPtrT> 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { 12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (DataBuffer.getBufferSize() < sizeof(uint64_t)) 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Magic = 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); 12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return getRawMagic<IntPtrT>() == Magic || 12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sys::SwapByteOrder(getRawMagic<IntPtrT>()) == Magic; 12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <class IntPtrT> 13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineserror_code RawInstrProfReader<IntPtrT>::readHeader() { 13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!hasFormat(*DataBuffer)) 13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::bad_magic); 13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (DataBuffer->getBufferSize() < sizeof(RawHeader)) 13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::bad_header); 13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto *Header = 13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines reinterpret_cast<const RawHeader *>(DataBuffer->getBufferStart()); 13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ShouldSwapBytes = Header->Magic != getRawMagic<IntPtrT>(); 13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return readHeader(*Header); 13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint64_t getRawVersion() { 14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 1; 14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 14536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <class IntPtrT> 14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineserror_code RawInstrProfReader<IntPtrT>::readHeader(const RawHeader &Header) { 14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (swap(Header.Version) != getRawVersion()) 14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::unsupported_version); 14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CountersDelta = swap(Header.CountersDelta); 15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines NamesDelta = swap(Header.NamesDelta); 15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto DataSize = swap(Header.DataSize); 15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto CountersSize = swap(Header.CountersSize); 15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto NamesSize = swap(Header.NamesSize); 15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptrdiff_t DataOffset = sizeof(RawHeader); 15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptrdiff_t CountersOffset = DataOffset + sizeof(ProfileData) * DataSize; 15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; 15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t FileSize = NamesOffset + sizeof(char) * NamesSize; 16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (FileSize != DataBuffer->getBufferSize()) 16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::bad_header); 16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const char *Start = DataBuffer->getBufferStart(); 16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Data = reinterpret_cast<const ProfileData *>(Start + DataOffset); 16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataEnd = Data + DataSize; 16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); 16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines NamesStart = Start + NamesOffset; 16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return success(); 17136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <class IntPtrT> 17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineserror_code 17536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesRawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) { 17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Data == DataEnd) 17736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::eof); 17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Get the raw data. 18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize)); 18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto RawCounts = makeArrayRef(getCounter(Data->CounterPtr), 18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines swap(Data->NumCounters)); 18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Check bounds. 18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); 18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (RawName.data() < NamesStart || 18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RawName.data() + RawName.size() > DataBuffer->getBufferEnd() || 18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RawCounts.data() < CountersStart || 18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RawCounts.data() + RawCounts.size() > NamesStartAsCounter) 19036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return error(instrprof_error::malformed); 19136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 19236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Store the data in Record, byte-swapping as necessary. 19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Record.Hash = swap(Data->FuncHash); 19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Record.Name = RawName; 19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ShouldSwapBytes) { 19636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Counts.clear(); 19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Counts.reserve(RawCounts.size()); 19836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (uint64_t Count : RawCounts) 19936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Counts.push_back(swap(Count)); 20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Record.Counts = Counts; 20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else 20236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Record.Counts = RawCounts; 20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Iterate. 20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Data; 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return success(); 20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace llvm { 21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate class RawInstrProfReader<uint32_t>; 21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate class RawInstrProfReader<uint64_t>; 21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 213