mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-17 20:23:59 +00:00
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
This commit is contained in:
@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user