diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-03-21 18:26:05 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-03-21 18:26:05 +0000 |
commit | ddfcb21b3f728fd569e106f43c1bcaed356223e4 (patch) | |
tree | f50994e1caa945d32234c0d1c5b4516de49871d3 /lib/ProfileData | |
parent | c61e1f53d97e35b9f75dabb7099f35eabffcce5b (diff) | |
download | llvm-ddfcb21b3f728fd569e106f43c1bcaed356223e4.tar.gz llvm-ddfcb21b3f728fd569e106f43c1bcaed356223e4.tar.bz2 llvm-ddfcb21b3f728fd569e106f43c1bcaed356223e4.tar.xz |
InstrProf: Read raw binary profile in llvm-profdata
Read a raw binary profile that corresponds to a memory dump from the
runtime profile.
The test is a binary file generated from
cfe/trunk/test/Profile/c-general.c with the new compiler-rt runtime and
the matching text version of the input. It includes instructions on how
to regenerate.
<rdar://problem/15950346>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204496 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ProfileData')
-rw-r--r-- | lib/ProfileData/InstrProfReader.cpp | 110 |
1 files changed, 106 insertions, 4 deletions
diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index 8b3600090b..c563355599 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -14,12 +14,23 @@ #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProf.h" -#include "llvm/Support/Endian.h" #include <cassert> using namespace llvm; +static uint64_t getRawMagic() { + return + uint64_t('l') << 56 | + uint64_t('p') << 48 | + uint64_t('r') << 40 | + uint64_t('o') << 32 | + uint64_t('f') << 24 | + uint64_t('r') << 16 | + uint64_t('a') << 8 | + uint64_t('w'); +} + error_code InstrProfReader::create(std::string Path, std::unique_ptr<InstrProfReader> &Result) { std::unique_ptr<MemoryBuffer> Buffer; @@ -30,10 +41,19 @@ error_code InstrProfReader::create(std::string Path, if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) return instrprof_error::too_large; - // FIXME: This needs to determine which format the file is and construct the - // correct subclass. - Result.reset(new TextInstrProfReader(Buffer)); + if (Buffer->getBufferSize() < sizeof(uint64_t)) { + Result.reset(new TextInstrProfReader(Buffer)); + Result->readHeader(); + return instrprof_error::success; + } + uint64_t Magic = *(uint64_t *)Buffer->getBufferStart(); + uint64_t SwappedMagic = sys::SwapByteOrder(Magic); + if (Magic == getRawMagic() || SwappedMagic == getRawMagic()) + Result.reset(new RawInstrProfReader(Buffer)); + else + Result.reset(new TextInstrProfReader(Buffer)); + Result->readHeader(); return instrprof_error::success; } @@ -82,3 +102,85 @@ error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { return success(); } + +static uint64_t getRawVersion() { + return 1; +} +namespace { +} +RawInstrProfReader::RawInstrProfReader(std::unique_ptr<MemoryBuffer> &DataBuffer) + : DataBuffer(DataBuffer.release()) { } + +error_code RawInstrProfReader::readHeader() { + if (DataBuffer->getBufferSize() < sizeof(RawHeader)) + return error(instrprof_error::malformed); + const RawHeader *Header = (RawHeader *)DataBuffer->getBufferStart(); + if (Header->Magic == getRawMagic()) + ShouldSwapBytes = false; + else { + if (sys::SwapByteOrder(Header->Magic) != getRawMagic()) + return error(instrprof_error::malformed); + + ShouldSwapBytes = true; + } + return readHeader(*Header); +} + +error_code RawInstrProfReader::readHeader(const RawHeader &Header) { + if (swap(Header.Version) != getRawVersion()) + return error(instrprof_error::unsupported_version); + + CountersDelta = swap(Header.CountersDelta); + NamesDelta = swap(Header.NamesDelta); + auto DataSize = swap(Header.DataSize); + auto CountersSize = swap(Header.CountersSize); + auto NamesSize = swap(Header.NamesSize); + + ptrdiff_t DataOffset = sizeof(RawHeader); + ptrdiff_t CountersOffset = DataOffset + sizeof(ProfileData) * DataSize; + ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; + size_t FileSize = NamesOffset + sizeof(char) * NamesSize; + + if (FileSize != DataBuffer->getBufferSize()) + return error(instrprof_error::malformed); + + Data = (ProfileData *)(DataBuffer->getBufferStart() + DataOffset); + DataEnd = Data + DataSize; + CountersStart = (uint64_t *)(DataBuffer->getBufferStart() + CountersOffset); + NamesStart = DataBuffer->getBufferStart() + NamesOffset; + + return success(); +} + +error_code RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { + if (Data == DataEnd) + return error(instrprof_error::eof); + + // Get the raw data. + StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize)); + auto RawCounts = makeArrayRef(getCounter(Data->CounterPtr), + swap(Data->NumCounters)); + + // Check bounds. + if (RawName.data() < NamesStart || + RawName.data() + RawName.size() > DataBuffer->getBufferEnd() || + RawCounts.data() < CountersStart || + RawCounts.data() + RawCounts.size() > (uint64_t *)NamesStart) + return error(instrprof_error::malformed); + + // Store the data in Record, byte-swapping as necessary. + Record.Hash = swap(Data->FuncHash); + Record.Name = RawName; + if (ShouldSwapBytes) { + Counts.clear(); + Counts.reserve(RawCounts.size()); + for (uint64_t Count : RawCounts) + Counts.push_back(swap(Count)); + Record.Counts = Counts; + } else + Record.Counts = RawCounts; + + // Iterate. + ++Data; + return success(); +} |