diff options
Diffstat (limited to 'llvm/lib/ProfileData/InstrProf.cpp')
-rw-r--r-- | llvm/lib/ProfileData/InstrProf.cpp | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 07d467305ae5..48ac5ce0d607 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -51,6 +51,7 @@ #include <memory> #include <string> #include <system_error> +#include <type_traits> #include <utility> #include <vector> @@ -466,12 +467,8 @@ Error collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs, } SmallString<128> CompressedNameStrings; - Error E = zlib::compress(StringRef(UncompressedNameStrings), - CompressedNameStrings, zlib::BestSizeCompression); - if (E) { - consumeError(std::move(E)); - return make_error<InstrProfError>(instrprof_error::compress_failed); - } + zlib::compress(StringRef(UncompressedNameStrings), CompressedNameStrings, + zlib::BestSizeCompression); return WriteStringToResult(CompressedNameStrings.size(), CompressedNameStrings); @@ -1311,4 +1308,76 @@ void OverlapStats::dump(raw_fd_ostream &OS) const { } } +namespace IndexedInstrProf { +// A C++14 compatible version of the offsetof macro. +template <typename T1, typename T2> +inline size_t constexpr offsetOf(T1 T2::*Member) { + constexpr T2 Object{}; + return size_t(&(Object.*Member)) - size_t(&Object); +} + +static inline uint64_t read(const unsigned char *Buffer, size_t Offset) { + return *reinterpret_cast<const uint64_t *>(Buffer + Offset); +} + +uint64_t Header::formatVersion() const { + using namespace support; + return endian::byte_swap<uint64_t, little>(Version); +} + +Expected<Header> Header::readFromBuffer(const unsigned char *Buffer) { + using namespace support; + static_assert(std::is_standard_layout<Header>::value, + "The header should be standard layout type since we use offset " + "of fields to read."); + Header H; + + H.Magic = read(Buffer, offsetOf(&Header::Magic)); + // Check the magic number. + uint64_t Magic = endian::byte_swap<uint64_t, little>(H.Magic); + if (Magic != IndexedInstrProf::Magic) + return make_error<InstrProfError>(instrprof_error::bad_magic); + + // Read the version. + H.Version = read(Buffer, offsetOf(&Header::Version)); + if (GET_VERSION(H.formatVersion()) > + IndexedInstrProf::ProfVersion::CurrentVersion) + return make_error<InstrProfError>(instrprof_error::unsupported_version); + + switch (GET_VERSION(H.formatVersion())) { + // When a new field is added in the header add a case statement here to + // populate it. + static_assert( + IndexedInstrProf::ProfVersion::CurrentVersion == Version8, + "Please update the reading code below if a new field has been added, " + "if not add a case statement to fall through to the latest version."); + case 8ull: + H.MemProfOffset = read(Buffer, offsetOf(&Header::MemProfOffset)); + LLVM_FALLTHROUGH; + default: // Version7 (when the backwards compatible header was introduced). + H.HashType = read(Buffer, offsetOf(&Header::HashType)); + H.HashOffset = read(Buffer, offsetOf(&Header::HashOffset)); + } + + return H; +} + +size_t Header::size() const { + switch (GET_VERSION(formatVersion())) { + // When a new field is added to the header add a case statement here to + // compute the size as offset of the new field + size of the new field. This + // relies on the field being added to the end of the list. + static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version8, + "Please update the size computation below if a new field has " + "been added to the header, if not add a case statement to " + "fall through to the latest version."); + case 8ull: + return offsetOf(&Header::MemProfOffset) + sizeof(Header::MemProfOffset); + default: // Version7 (when the backwards compatible header was introduced). + return offsetOf(&Header::HashOffset) + sizeof(Header::HashOffset); + } +} + +} // namespace IndexedInstrProf + } // end namespace llvm |