summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/ProfileData
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-11-24 17:02:24 +0000
committerdim <dim@FreeBSD.org>2014-11-24 17:02:24 +0000
commit2c8643c6396b0a3db33430cf9380e70bbb9efce0 (patch)
tree4df130b28021d86e13bf4565ef58c1c5a5e093b4 /contrib/llvm/lib/ProfileData
parent678318cd20f7db4e6c6b85d83fe00fa327b04fca (diff)
parente27feadae0885aa074df58ebfda2e7a7f7a7d590 (diff)
downloadFreeBSD-src-2c8643c6396b0a3db33430cf9380e70bbb9efce0.zip
FreeBSD-src-2c8643c6396b0a3db33430cf9380e70bbb9efce0.tar.gz
Merge llvm 3.5.0 release from ^/vendor/llvm/dist, resolve conflicts, and
preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/lib/ProfileData')
-rw-r--r--contrib/llvm/lib/ProfileData/CMakeLists.txt5
-rw-r--r--contrib/llvm/lib/ProfileData/InstrProf.cpp61
-rw-r--r--contrib/llvm/lib/ProfileData/InstrProfIndexed.h55
-rw-r--r--contrib/llvm/lib/ProfileData/InstrProfReader.cpp360
-rw-r--r--contrib/llvm/lib/ProfileData/InstrProfWriter.cpp127
-rw-r--r--contrib/llvm/lib/ProfileData/LLVMBuild.txt22
-rw-r--r--contrib/llvm/lib/ProfileData/Makefile14
7 files changed, 644 insertions, 0 deletions
diff --git a/contrib/llvm/lib/ProfileData/CMakeLists.txt b/contrib/llvm/lib/ProfileData/CMakeLists.txt
new file mode 100644
index 0000000..aefb16c
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_llvm_library(LLVMProfileData
+ InstrProf.cpp
+ InstrProfReader.cpp
+ InstrProfWriter.cpp
+ )
diff --git a/contrib/llvm/lib/ProfileData/InstrProf.cpp b/contrib/llvm/lib/ProfileData/InstrProf.cpp
new file mode 100644
index 0000000..0121222
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/InstrProf.cpp
@@ -0,0 +1,61 @@
+//=-- InstrProf.cpp - Instrumented profiling format support -----------------=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for clang's instrumentation based PGO and
+// coverage.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+class InstrProfErrorCategoryType : public std::error_category {
+ const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
+ std::string message(int IE) const override {
+ instrprof_error E = static_cast<instrprof_error>(IE);
+ switch (E) {
+ case instrprof_error::success:
+ return "Success";
+ case instrprof_error::eof:
+ return "End of File";
+ case instrprof_error::bad_magic:
+ return "Invalid file format (bad magic)";
+ case instrprof_error::bad_header:
+ return "Invalid header";
+ case instrprof_error::unsupported_version:
+ return "Unsupported format version";
+ case instrprof_error::unsupported_hash_type:
+ return "Unsupported hash function";
+ case instrprof_error::too_large:
+ return "Too much profile data";
+ case instrprof_error::truncated:
+ return "Truncated profile data";
+ case instrprof_error::malformed:
+ return "Malformed profile data";
+ case instrprof_error::unknown_function:
+ return "No profile data available for function";
+ case instrprof_error::hash_mismatch:
+ return "Function hash mismatch";
+ case instrprof_error::count_mismatch:
+ return "Function count mismatch";
+ case instrprof_error::counter_overflow:
+ return "Counter overflow";
+ }
+ llvm_unreachable("A value of instrprof_error has no message.");
+ }
+};
+}
+
+const std::error_category &llvm::instrprof_category() {
+ static InstrProfErrorCategoryType C;
+ return C;
+}
diff --git a/contrib/llvm/lib/ProfileData/InstrProfIndexed.h b/contrib/llvm/lib/ProfileData/InstrProfIndexed.h
new file mode 100644
index 0000000..7761704
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/InstrProfIndexed.h
@@ -0,0 +1,55 @@
+//=-- InstrProfIndexed.h - Indexed profiling format support -------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared header for the instrumented profile data reader and writer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_INSTRPROF_INDEXED_H_
+#define LLVM_PROFILEDATA_INSTRPROF_INDEXED_H_
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.h"
+
+namespace llvm {
+
+namespace IndexedInstrProf {
+enum class HashT : uint32_t {
+ MD5,
+
+ Last = MD5
+};
+
+static inline uint64_t MD5Hash(StringRef Str) {
+ MD5 Hash;
+ Hash.update(Str);
+ llvm::MD5::MD5Result Result;
+ Hash.final(Result);
+ // Return the least significant 8 bytes. Our MD5 implementation returns the
+ // result in little endian, so we may need to swap bytes.
+ using namespace llvm::support;
+ return endian::read<uint64_t, little, unaligned>(Result);
+}
+
+static inline uint64_t ComputeHash(HashT Type, StringRef K) {
+ switch (Type) {
+ case HashT::MD5:
+ return IndexedInstrProf::MD5Hash(K);
+ }
+ llvm_unreachable("Unhandled hash type");
+}
+
+const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81"
+const uint64_t Version = 1;
+const HashT HashType = HashT::MD5;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_PROFILEDATA_INSTRPROF_INDEXED_H_
diff --git a/contrib/llvm/lib/ProfileData/InstrProfReader.cpp b/contrib/llvm/lib/ProfileData/InstrProfReader.cpp
new file mode 100644
index 0000000..0b36728
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -0,0 +1,360 @@
+//=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for reading profiling data for clang's
+// instrumentation based PGO and coverage.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/ProfileData/InstrProf.h"
+
+#include "InstrProfIndexed.h"
+
+#include <cassert>
+
+using namespace llvm;
+
+static std::error_code
+setupMemoryBuffer(std::string Path, std::unique_ptr<MemoryBuffer> &Buffer) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+ MemoryBuffer::getFileOrSTDIN(Path);
+ if (std::error_code EC = BufferOrErr.getError())
+ return EC;
+ Buffer = std::move(BufferOrErr.get());
+
+ // Sanity check the file.
+ if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max())
+ return instrprof_error::too_large;
+ return instrprof_error::success;
+}
+
+static std::error_code initializeReader(InstrProfReader &Reader) {
+ return Reader.readHeader();
+}
+
+std::error_code
+InstrProfReader::create(std::string Path,
+ std::unique_ptr<InstrProfReader> &Result) {
+ // Set up the buffer to read.
+ std::unique_ptr<MemoryBuffer> Buffer;
+ if (std::error_code EC = setupMemoryBuffer(Path, Buffer))
+ return EC;
+
+ // Create the reader.
+ if (IndexedInstrProfReader::hasFormat(*Buffer))
+ Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
+ else 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)));
+
+ // Initialize the reader and return the result.
+ return initializeReader(*Result);
+}
+
+std::error_code IndexedInstrProfReader::create(
+ std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result) {
+ // Set up the buffer to read.
+ std::unique_ptr<MemoryBuffer> Buffer;
+ if (std::error_code EC = setupMemoryBuffer(Path, Buffer))
+ return EC;
+
+ // Create the reader.
+ if (!IndexedInstrProfReader::hasFormat(*Buffer))
+ return instrprof_error::bad_magic;
+ Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
+
+ // Initialize the reader and return the result.
+ return initializeReader(*Result);
+}
+
+void InstrProfIterator::Increment() {
+ if (Reader->readNextRecord(Record))
+ *this = InstrProfIterator();
+}
+
+std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
+ // Skip empty lines.
+ while (!Line.is_at_end() && Line->empty())
+ ++Line;
+ // If we hit EOF while looking for a name, we're done.
+ if (Line.is_at_end())
+ return error(instrprof_error::eof);
+
+ // Read the function name.
+ Record.Name = *Line++;
+
+ // Read the function hash.
+ if (Line.is_at_end())
+ return error(instrprof_error::truncated);
+ if ((Line++)->getAsInteger(10, Record.Hash))
+ return error(instrprof_error::malformed);
+
+ // Read the number of counters.
+ uint64_t NumCounters;
+ if (Line.is_at_end())
+ return error(instrprof_error::truncated);
+ if ((Line++)->getAsInteger(10, NumCounters))
+ return error(instrprof_error::malformed);
+ if (NumCounters == 0)
+ return error(instrprof_error::malformed);
+
+ // Read each counter and fill our internal storage with the values.
+ Counts.clear();
+ Counts.reserve(NumCounters);
+ for (uint64_t I = 0; I < NumCounters; ++I) {
+ if (Line.is_at_end())
+ return error(instrprof_error::truncated);
+ uint64_t Count;
+ if ((Line++)->getAsInteger(10, Count))
+ return error(instrprof_error::malformed);
+ Counts.push_back(Count);
+ }
+ // Give the record a reference to our internal counter storage.
+ Record.Counts = Counts;
+
+ 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::getSwappedBytes(getRawMagic<IntPtrT>()) == Magic;
+}
+
+template <class IntPtrT>
+std::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);
+}
+
+template <class IntPtrT>
+std::error_code
+RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
+ const char *End = DataBuffer->getBufferEnd();
+ // Skip zero padding between profiles.
+ while (CurrentPos != End && *CurrentPos == 0)
+ ++CurrentPos;
+ // If there's nothing left, we're done.
+ if (CurrentPos == End)
+ return instrprof_error::eof;
+ // If there isn't enough space for another header, this is probably just
+ // garbage at the end of the file.
+ if (CurrentPos + sizeof(RawHeader) > End)
+ return instrprof_error::malformed;
+ // The magic should have the same byte order as in the previous header.
+ uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
+ if (Magic != swap(getRawMagic<IntPtrT>()))
+ return instrprof_error::bad_magic;
+
+ // There's another profile to read, so we need to process the header.
+ auto *Header = reinterpret_cast<const RawHeader *>(CurrentPos);
+ return readHeader(*Header);
+}
+
+static uint64_t getRawVersion() {
+ return 1;
+}
+
+template <class IntPtrT>
+std::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 ProfileSize = NamesOffset + sizeof(char) * NamesSize;
+
+ auto *Start = reinterpret_cast<const char *>(&Header);
+ if (Start + ProfileSize > DataBuffer->getBufferEnd())
+ return error(instrprof_error::bad_header);
+
+ Data = reinterpret_cast<const ProfileData *>(Start + DataOffset);
+ DataEnd = Data + DataSize;
+ CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
+ NamesStart = Start + NamesOffset;
+ ProfileEnd = Start + ProfileSize;
+
+ return success();
+}
+
+template <class IntPtrT>
+std::error_code
+RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
+ if (Data == DataEnd)
+ if (std::error_code EC = readNextHeader(ProfileEnd))
+ return EC;
+
+ // Get the raw data.
+ StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize));
+ uint32_t NumCounters = swap(Data->NumCounters);
+ if (NumCounters == 0)
+ return error(instrprof_error::malformed);
+ auto RawCounts = makeArrayRef(getCounter(Data->CounterPtr), 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>;
+}
+
+InstrProfLookupTrait::hash_value_type
+InstrProfLookupTrait::ComputeHash(StringRef K) {
+ return IndexedInstrProf::ComputeHash(HashType, K);
+}
+
+bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
+ if (DataBuffer.getBufferSize() < 8)
+ return false;
+ using namespace support;
+ uint64_t Magic =
+ endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
+ return Magic == IndexedInstrProf::Magic;
+}
+
+std::error_code IndexedInstrProfReader::readHeader() {
+ const unsigned char *Start =
+ (const unsigned char *)DataBuffer->getBufferStart();
+ const unsigned char *Cur = Start;
+ if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
+ return error(instrprof_error::truncated);
+
+ using namespace support;
+
+ // Check the magic number.
+ uint64_t Magic = endian::readNext<uint64_t, little, unaligned>(Cur);
+ if (Magic != IndexedInstrProf::Magic)
+ return error(instrprof_error::bad_magic);
+
+ // Read the version.
+ uint64_t Version = endian::readNext<uint64_t, little, unaligned>(Cur);
+ if (Version != IndexedInstrProf::Version)
+ return error(instrprof_error::unsupported_version);
+
+ // Read the maximal function count.
+ MaxFunctionCount = endian::readNext<uint64_t, little, unaligned>(Cur);
+
+ // Read the hash type and start offset.
+ IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
+ endian::readNext<uint64_t, little, unaligned>(Cur));
+ if (HashType > IndexedInstrProf::HashT::Last)
+ return error(instrprof_error::unsupported_hash_type);
+ uint64_t HashOffset = endian::readNext<uint64_t, little, unaligned>(Cur);
+
+ // The rest of the file is an on disk hash table.
+ Index.reset(InstrProfReaderIndex::Create(Start + HashOffset, Cur, Start,
+ InstrProfLookupTrait(HashType)));
+ // Set up our iterator for readNextRecord.
+ RecordIterator = Index->data_begin();
+
+ return success();
+}
+
+std::error_code IndexedInstrProfReader::getFunctionCounts(
+ StringRef FuncName, uint64_t &FuncHash, std::vector<uint64_t> &Counts) {
+ const auto &Iter = Index->find(FuncName);
+ if (Iter == Index->end())
+ return error(instrprof_error::unknown_function);
+
+ // Found it. Make sure it's valid before giving back a result.
+ const InstrProfRecord &Record = *Iter;
+ if (Record.Name.empty())
+ return error(instrprof_error::malformed);
+ FuncHash = Record.Hash;
+ Counts = Record.Counts;
+ return success();
+}
+
+std::error_code
+IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) {
+ // Are we out of records?
+ if (RecordIterator == Index->data_end())
+ return error(instrprof_error::eof);
+
+ // Read the next one.
+ Record = *RecordIterator;
+ ++RecordIterator;
+ if (Record.Name.empty())
+ return error(instrprof_error::malformed);
+ return success();
+}
diff --git a/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp b/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp
new file mode 100644
index 0000000..e55c299
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -0,0 +1,127 @@
+//=-- InstrProfWriter.cpp - Instrumented profiling writer -------------------=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing profiling data for clang's
+// instrumentation based PGO and coverage.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/InstrProfWriter.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/OnDiskHashTable.h"
+
+#include "InstrProfIndexed.h"
+
+using namespace llvm;
+
+namespace {
+class InstrProfRecordTrait {
+public:
+ typedef StringRef key_type;
+ typedef StringRef key_type_ref;
+
+ typedef const InstrProfWriter::CounterData *const data_type;
+ typedef const InstrProfWriter::CounterData *const data_type_ref;
+
+ typedef uint64_t hash_value_type;
+ typedef uint64_t offset_type;
+
+ static hash_value_type ComputeHash(key_type_ref K) {
+ return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType, K);
+ }
+
+ static std::pair<offset_type, offset_type>
+ EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+
+ offset_type N = K.size();
+ LE.write<offset_type>(N);
+
+ offset_type M = (1 + V->Counts.size()) * sizeof(uint64_t);
+ LE.write<offset_type>(M);
+
+ return std::make_pair(N, M);
+ }
+
+ static void EmitKey(raw_ostream &Out, key_type_ref K, offset_type N){
+ Out.write(K.data(), N);
+ }
+
+ static void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V,
+ offset_type) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ LE.write<uint64_t>(V->Hash);
+ for (uint64_t I : V->Counts)
+ LE.write<uint64_t>(I);
+ }
+};
+}
+
+std::error_code
+InstrProfWriter::addFunctionCounts(StringRef FunctionName,
+ uint64_t FunctionHash,
+ ArrayRef<uint64_t> Counters) {
+ auto Where = FunctionData.find(FunctionName);
+ if (Where == FunctionData.end()) {
+ // If this is the first time we've seen this function, just add it.
+ auto &Data = FunctionData[FunctionName];
+ Data.Hash = FunctionHash;
+ Data.Counts = Counters;
+ return instrprof_error::success;
+ }
+
+ auto &Data = Where->getValue();
+ // We can only add to existing functions if they match, so we check the hash
+ // and number of counters.
+ if (Data.Hash != FunctionHash)
+ return instrprof_error::hash_mismatch;
+ if (Data.Counts.size() != Counters.size())
+ return instrprof_error::count_mismatch;
+ // These match, add up the counters.
+ for (size_t I = 0, E = Counters.size(); I < E; ++I) {
+ if (Data.Counts[I] + Counters[I] < Data.Counts[I])
+ return instrprof_error::counter_overflow;
+ Data.Counts[I] += Counters[I];
+ }
+ return instrprof_error::success;
+}
+
+void InstrProfWriter::write(raw_fd_ostream &OS) {
+ OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator;
+ uint64_t MaxFunctionCount = 0;
+
+ // Populate the hash table generator.
+ for (const auto &I : FunctionData) {
+ Generator.insert(I.getKey(), &I.getValue());
+ if (I.getValue().Counts[0] > MaxFunctionCount)
+ MaxFunctionCount = I.getValue().Counts[0];
+ }
+
+ using namespace llvm::support;
+ endian::Writer<little> LE(OS);
+
+ // Write the header.
+ LE.write<uint64_t>(IndexedInstrProf::Magic);
+ LE.write<uint64_t>(IndexedInstrProf::Version);
+ LE.write<uint64_t>(MaxFunctionCount);
+ LE.write<uint64_t>(static_cast<uint64_t>(IndexedInstrProf::HashType));
+
+ // Save a space to write the hash table start location.
+ uint64_t HashTableStartLoc = OS.tell();
+ LE.write<uint64_t>(0);
+ // Write the hash table.
+ uint64_t HashTableStart = Generator.Emit(OS);
+
+ // Go back and fill in the hash table start.
+ OS.seek(HashTableStartLoc);
+ LE.write<uint64_t>(HashTableStart);
+}
diff --git a/contrib/llvm/lib/ProfileData/LLVMBuild.txt b/contrib/llvm/lib/ProfileData/LLVMBuild.txt
new file mode 100644
index 0000000..0a8cbe3
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/ProfileData/LLVMBuild.txt --------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = ProfileData
+parent = Libraries
+required_libraries = Support
diff --git a/contrib/llvm/lib/ProfileData/Makefile b/contrib/llvm/lib/ProfileData/Makefile
new file mode 100644
index 0000000..2674361
--- /dev/null
+++ b/contrib/llvm/lib/ProfileData/Makefile
@@ -0,0 +1,14 @@
+##===- lib/ProfileData/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = LLVMProfileData
+BUILD_ARCHIVE := 1
+
+include $(LEVEL)/Makefile.common
OpenPOWER on IntegriCloud