summaryrefslogtreecommitdiff
path: root/lib/ProfileData
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-03-21 18:26:05 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-03-21 18:26:05 +0000
commitddfcb21b3f728fd569e106f43c1bcaed356223e4 (patch)
treef50994e1caa945d32234c0d1c5b4516de49871d3 /lib/ProfileData
parentc61e1f53d97e35b9f75dabb7099f35eabffcce5b (diff)
downloadllvm-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.cpp110
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();
+}