#ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
#include <memory>
#include <set>
#include <system_error>
namespace llvm {
namespace sampleprof {
enum SectionLayout {
DefaultLayout,
CtxSplitLayout,
NumOfLayout,
};
class SampleProfileWriter {
public:
virtual ~SampleProfileWriter() = default;
virtual std::error_code writeSample(const FunctionSamples &S) = 0;
virtual std::error_code write(const SampleProfileMap &ProfileMap);
raw_ostream &getOutputStream() { return *OutputStream; }
static ErrorOr<std::unique_ptr<SampleProfileWriter>>
create(StringRef Filename, SampleProfileFormat Format);
static ErrorOr<std::unique_ptr<SampleProfileWriter>>
create(std::unique_ptr<raw_ostream> &OS, SampleProfileFormat Format);
virtual void setProfileSymbolList(ProfileSymbolList *PSL) {}
virtual void setToCompressAllSections() {}
virtual void setUseMD5() {}
virtual void setPartialProfile() {}
virtual void resetSecLayout(SectionLayout SL) {}
protected:
SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
: OutputStream(std::move(OS)) {}
virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap) = 0;
virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap);
std::unique_ptr<raw_ostream> OutputStream;
std::unique_ptr<ProfileSummary> Summary;
void computeSummary(const SampleProfileMap &ProfileMap);
SampleProfileFormat Format = SPF_None;
};
class SampleProfileWriterText : public SampleProfileWriter {
public:
std::error_code writeSample(const FunctionSamples &S) override;
protected:
SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriter(OS), Indent(0) {}
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override {
return sampleprof_error::success;
}
private:
unsigned Indent;
friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
SampleProfileFormat Format);
};
class SampleProfileWriterBinary : public SampleProfileWriter {
public:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriter(OS) {}
std::error_code writeSample(const FunctionSamples &S) override;
protected:
virtual MapVector<StringRef, uint32_t> &getNameTable() { return NameTable; }
virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
virtual std::error_code writeNameTable();
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
std::error_code writeSummary();
virtual std::error_code writeContextIdx(const SampleContext &Context);
std::error_code writeNameIdx(StringRef FName);
std::error_code writeBody(const FunctionSamples &S);
inline void stablizeNameTable(MapVector<StringRef, uint32_t> &NameTable,
std::set<StringRef> &V);
MapVector<StringRef, uint32_t> NameTable;
void addName(StringRef FName);
virtual void addContext(const SampleContext &Context);
void addNames(const FunctionSamples &S);
private:
friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
SampleProfileFormat Format);
};
class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
using SampleProfileWriterBinary::SampleProfileWriterBinary;
};
const std::array<SmallVector<SecHdrTableEntry, 8>, NumOfLayout>
ExtBinaryHdrLayoutTable = {
SmallVector<SecHdrTableEntry, 8>({{SecProfSummary, 0, 0, 0, 0},
{SecNameTable, 0, 0, 0, 0},
{SecCSNameTable, 0, 0, 0, 0},
{SecFuncOffsetTable, 0, 0, 0, 0},
{SecLBRProfile, 0, 0, 0, 0},
{SecProfileSymbolList, 0, 0, 0, 0},
{SecFuncMetadata, 0, 0, 0, 0}}),
SmallVector<SecHdrTableEntry, 8>({{SecProfSummary, 0, 0, 0, 0},
{SecNameTable, 0, 0, 0, 0},
{SecFuncOffsetTable, 0, 0, 0, 0},
{SecLBRProfile, 0, 0, 0, 0},
{SecFuncOffsetTable, 0, 0, 0, 0},
{SecLBRProfile, 0, 0, 0, 0},
{SecProfileSymbolList, 0, 0, 0, 0},
{SecFuncMetadata, 0, 0, 0, 0}}),
};
class SampleProfileWriterExtBinaryBase : public SampleProfileWriterBinary {
using SampleProfileWriterBinary::SampleProfileWriterBinary;
public:
std::error_code write(const SampleProfileMap &ProfileMap) override;
void setToCompressAllSections() override;
void setToCompressSection(SecType Type);
std::error_code writeSample(const FunctionSamples &S) override;
void setUseMD5() override {
UseMD5 = true;
addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagMD5Name);
addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagFixedLengthMD5);
}
void setPartialProfile() override {
addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagPartial);
}
void setProfileSymbolList(ProfileSymbolList *PSL) override {
ProfSymList = PSL;
};
void resetSecLayout(SectionLayout SL) override {
verifySecLayout(SL);
#ifndef NDEBUG
for (auto &Entry : SectionHdrLayout) {
assert(Entry.Flags == 0 &&
"resetSecLayout has to be called before any flag setting");
}
#endif
SecLayout = SL;
SectionHdrLayout = ExtBinaryHdrLayoutTable[SL];
}
protected:
uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx);
std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx,
uint64_t SectionStart);
template <class SecFlagType>
void addSectionFlag(SecType Type, SecFlagType Flag) {
for (auto &Entry : SectionHdrLayout) {
if (Entry.Type == Type)
addSecFlag(Entry, Flag);
}
}
template <class SecFlagType>
void addSectionFlag(uint32_t SectionIdx, SecFlagType Flag) {
addSecFlag(SectionHdrLayout[SectionIdx], Flag);
}
void addContext(const SampleContext &Context) override;
virtual std::error_code writeCustomSection(SecType Type) = 0;
virtual void verifySecLayout(SectionLayout SL) = 0;
virtual std::error_code writeSections(const SampleProfileMap &ProfileMap) = 0;
virtual std::error_code writeOneSection(SecType Type, uint32_t LayoutIdx,
const SampleProfileMap &ProfileMap);
std::error_code writeNameTable() override;
std::error_code writeContextIdx(const SampleContext &Context) override;
std::error_code writeCSNameIdx(const SampleContext &Context);
std::error_code writeCSNameTableSection();
std::error_code writeFuncMetadata(const SampleProfileMap &Profiles);
std::error_code writeFuncMetadata(const FunctionSamples &Profile);
std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap);
std::error_code writeFuncOffsetTable();
std::error_code writeProfileSymbolListSection();
SectionLayout SecLayout = DefaultLayout;
SmallVector<SecHdrTableEntry, 8> SectionHdrLayout =
ExtBinaryHdrLayoutTable[DefaultLayout];
uint64_t SecLBRProfileStart = 0;
private:
void allocSecHdrTable();
std::error_code writeSecHdrTable();
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
std::error_code compressAndOutput();
std::unique_ptr<raw_ostream> LocalBufStream;
uint64_t FileStart;
uint64_t SecHdrTableOffset;
std::vector<SecHdrTableEntry> SecHdrTable;
MapVector<SampleContext, uint64_t> FuncOffsetTable;
bool UseMD5 = false;
MapVector<SampleContext, uint32_t> CSNameTable;
ProfileSymbolList *ProfSymList = nullptr;
};
class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
public:
SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriterExtBinaryBase(OS) {}
private:
std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap);
std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
std::error_code writeCustomSection(SecType Type) override {
return sampleprof_error::success;
};
void verifySecLayout(SectionLayout SL) override {
assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
"Unsupported layout");
}
};
class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
using SampleProfileWriterBinary::SampleProfileWriterBinary;
public:
std::error_code writeSample(const FunctionSamples &S) override;
std::error_code write(const SampleProfileMap &ProfileMap) override;
protected:
MapVector<StringRef, uint64_t> FuncOffsetTable;
uint64_t TableOffset;
std::error_code writeNameTable() override;
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
std::error_code writeFuncOffsetTable();
};
} }
#endif