#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/ProfileData/InstrProf.h"
-#include "llvm/Support/Endian.h"
#include <cassert>
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));
+ // Create the reader.
+ if (RawInstrProfReader64::hasFormat(*Buffer))
+ Result.reset(new RawInstrProfReader64(std::move(Buffer)));
+ else if (RawInstrProfReader32::hasFormat(*Buffer))
+ Result.reset(new RawInstrProfReader32(std::move(Buffer)));
+ else
+ Result.reset(new TextInstrProfReader(std::move(Buffer)));
- return instrprof_error::success;
+ // Read the header and return the result.
+ return Result->readHeader();
}
void InstrProfIterator::Increment() {
return success();
}
+
+template <class IntPtrT>
+static uint64_t getRawMagic();
+
+template <>
+uint64_t getRawMagic<uint64_t>() {
+ return
+ uint64_t(255) << 56 |
+ uint64_t('l') << 48 |
+ uint64_t('p') << 40 |
+ uint64_t('r') << 32 |
+ uint64_t('o') << 24 |
+ uint64_t('f') << 16 |
+ uint64_t('r') << 8 |
+ uint64_t(129);
+}
+
+template <>
+uint64_t getRawMagic<uint32_t>() {
+ return
+ uint64_t(255) << 56 |
+ uint64_t('l') << 48 |
+ uint64_t('p') << 40 |
+ uint64_t('r') << 32 |
+ uint64_t('o') << 24 |
+ uint64_t('f') << 16 |
+ uint64_t('R') << 8 |
+ uint64_t(129);
+}
+
+template <class IntPtrT>
+bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
+ if (DataBuffer.getBufferSize() < sizeof(uint64_t))
+ return false;
+ uint64_t Magic =
+ *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
+ return getRawMagic<IntPtrT>() == Magic ||
+ sys::SwapByteOrder(getRawMagic<IntPtrT>()) == Magic;
+}
+
+template <class IntPtrT>
+error_code RawInstrProfReader<IntPtrT>::readHeader() {
+ if (!hasFormat(*DataBuffer))
+ return error(instrprof_error::bad_magic);
+ if (DataBuffer->getBufferSize() < sizeof(RawHeader))
+ return error(instrprof_error::bad_header);
+ auto *Header =
+ reinterpret_cast<const RawHeader *>(DataBuffer->getBufferStart());
+ ShouldSwapBytes = Header->Magic != getRawMagic<IntPtrT>();
+ return readHeader(*Header);
+}
+
+static uint64_t getRawVersion() {
+ return 1;
+}
+
+template <class IntPtrT>
+error_code RawInstrProfReader<IntPtrT>::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::bad_header);
+
+ const char *Start = DataBuffer->getBufferStart();
+ Data = reinterpret_cast<const ProfileData *>(Start + DataOffset);
+ DataEnd = Data + DataSize;
+ CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
+ NamesStart = Start + NamesOffset;
+
+ return success();
+}
+
+template <class IntPtrT>
+error_code
+RawInstrProfReader<IntPtrT>::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.
+ auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
+ if (RawName.data() < NamesStart ||
+ RawName.data() + RawName.size() > DataBuffer->getBufferEnd() ||
+ RawCounts.data() < CountersStart ||
+ RawCounts.data() + RawCounts.size() > NamesStartAsCounter)
+ 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();
+}
+
+namespace llvm {
+template class RawInstrProfReader<uint32_t>;
+template class RawInstrProfReader<uint64_t>;
+}