File indexing completed on 2026-05-10 08:44:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
0013 #define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
0014
0015 #include "llvm/ADT/MapVector.h"
0016 #include "llvm/ADT/StringRef.h"
0017 #include "llvm/IR/ProfileSummary.h"
0018 #include "llvm/ProfileData/SampleProf.h"
0019 #include "llvm/Support/ErrorOr.h"
0020 #include "llvm/Support/raw_ostream.h"
0021 #include <cstdint>
0022 #include <memory>
0023 #include <set>
0024 #include <system_error>
0025
0026 namespace llvm {
0027 namespace sampleprof {
0028
0029 enum SectionLayout {
0030 DefaultLayout,
0031
0032
0033
0034 CtxSplitLayout,
0035 NumOfLayout,
0036 };
0037
0038
0039
0040
0041
0042 class FunctionPruningStrategy {
0043 protected:
0044 SampleProfileMap &ProfileMap;
0045 size_t OutputSizeLimit;
0046
0047 public:
0048
0049
0050
0051
0052 FunctionPruningStrategy(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
0053 : ProfileMap(ProfileMap), OutputSizeLimit(OutputSizeLimit) {}
0054
0055 virtual ~FunctionPruningStrategy() = default;
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 virtual void Erase(size_t CurrentOutputSize) = 0;
0066 };
0067
0068 class DefaultFunctionPruningStrategy : public FunctionPruningStrategy {
0069 std::vector<NameFunctionSamples> SortedFunctions;
0070
0071 public:
0072 DefaultFunctionPruningStrategy(SampleProfileMap &ProfileMap,
0073 size_t OutputSizeLimit);
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 void Erase(size_t CurrentOutputSize) override;
0086 };
0087
0088
0089 class SampleProfileWriter {
0090 public:
0091 virtual ~SampleProfileWriter() = default;
0092
0093
0094
0095
0096 virtual std::error_code writeSample(const FunctionSamples &S) = 0;
0097
0098
0099
0100
0101 virtual std::error_code write(const SampleProfileMap &ProfileMap);
0102
0103
0104
0105
0106
0107 template <typename FunctionPruningStrategy = DefaultFunctionPruningStrategy>
0108 std::error_code writeWithSizeLimit(SampleProfileMap &ProfileMap,
0109 size_t OutputSizeLimit) {
0110 FunctionPruningStrategy Strategy(ProfileMap, OutputSizeLimit);
0111 return writeWithSizeLimitInternal(ProfileMap, OutputSizeLimit, &Strategy);
0112 }
0113
0114 raw_ostream &getOutputStream() { return *OutputStream; }
0115
0116
0117
0118
0119 static ErrorOr<std::unique_ptr<SampleProfileWriter>>
0120 create(StringRef Filename, SampleProfileFormat Format);
0121
0122
0123
0124 static ErrorOr<std::unique_ptr<SampleProfileWriter>>
0125 create(std::unique_ptr<raw_ostream> &OS, SampleProfileFormat Format);
0126
0127 virtual void setProfileSymbolList(ProfileSymbolList *PSL) {}
0128 virtual void setToCompressAllSections() {}
0129 virtual void setUseMD5() {}
0130 virtual void setPartialProfile() {}
0131 virtual void setUseCtxSplitLayout() {}
0132
0133 protected:
0134 SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
0135 : OutputStream(std::move(OS)) {}
0136
0137
0138 virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap) = 0;
0139
0140
0141 virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap);
0142
0143 std::error_code writeWithSizeLimitInternal(SampleProfileMap &ProfileMap,
0144 size_t OutputSizeLimit,
0145 FunctionPruningStrategy *Strategy);
0146
0147
0148
0149
0150 size_t LineCount;
0151
0152
0153 std::unique_ptr<raw_ostream> OutputStream;
0154
0155
0156 std::unique_ptr<ProfileSummary> Summary;
0157
0158
0159 void computeSummary(const SampleProfileMap &ProfileMap);
0160
0161
0162 SampleProfileFormat Format = SPF_None;
0163 };
0164
0165
0166 class SampleProfileWriterText : public SampleProfileWriter {
0167 public:
0168 std::error_code writeSample(const FunctionSamples &S) override;
0169
0170 protected:
0171 SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
0172 : SampleProfileWriter(OS) {}
0173
0174 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override {
0175 LineCount = 0;
0176 return sampleprof_error::success;
0177 }
0178
0179 void setUseCtxSplitLayout() override {
0180 MarkFlatProfiles = true;
0181 }
0182
0183 private:
0184
0185
0186
0187 unsigned Indent = 0;
0188
0189
0190
0191
0192
0193 bool MarkFlatProfiles = false;
0194
0195 friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
0196 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
0197 SampleProfileFormat Format);
0198 };
0199
0200
0201 class SampleProfileWriterBinary : public SampleProfileWriter {
0202 public:
0203 SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
0204 : SampleProfileWriter(OS) {}
0205
0206 std::error_code writeSample(const FunctionSamples &S) override;
0207
0208 protected:
0209 virtual MapVector<FunctionId, uint32_t> &getNameTable() { return NameTable; }
0210 virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
0211 virtual std::error_code writeNameTable();
0212 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
0213 std::error_code writeSummary();
0214 virtual std::error_code writeContextIdx(const SampleContext &Context);
0215 std::error_code writeNameIdx(FunctionId FName);
0216 std::error_code writeBody(const FunctionSamples &S);
0217 inline void stablizeNameTable(MapVector<FunctionId, uint32_t> &NameTable,
0218 std::set<FunctionId> &V);
0219
0220 MapVector<FunctionId, uint32_t> NameTable;
0221
0222 void addName(FunctionId FName);
0223 virtual void addContext(const SampleContext &Context);
0224 void addNames(const FunctionSamples &S);
0225
0226 private:
0227 friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
0228 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
0229 SampleProfileFormat Format);
0230 };
0231
0232 class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
0233 using SampleProfileWriterBinary::SampleProfileWriterBinary;
0234 };
0235
0236 const std::array<SmallVector<SecHdrTableEntry, 8>, NumOfLayout>
0237 ExtBinaryHdrLayoutTable = {
0238
0239
0240
0241
0242
0243
0244
0245 SmallVector<SecHdrTableEntry, 8>({{SecProfSummary, 0, 0, 0, 0},
0246 {SecNameTable, 0, 0, 0, 0},
0247 {SecCSNameTable, 0, 0, 0, 0},
0248 {SecFuncOffsetTable, 0, 0, 0, 0},
0249 {SecLBRProfile, 0, 0, 0, 0},
0250 {SecProfileSymbolList, 0, 0, 0, 0},
0251 {SecFuncMetadata, 0, 0, 0, 0}}),
0252
0253 SmallVector<SecHdrTableEntry, 8>({{SecProfSummary, 0, 0, 0, 0},
0254 {SecNameTable, 0, 0, 0, 0},
0255
0256
0257 {SecFuncOffsetTable, 0, 0, 0, 0},
0258 {SecLBRProfile, 0, 0, 0, 0},
0259
0260
0261 {SecFuncOffsetTable, 0, 0, 0, 0},
0262 {SecLBRProfile, 0, 0, 0, 0},
0263 {SecProfileSymbolList, 0, 0, 0, 0},
0264 {SecFuncMetadata, 0, 0, 0, 0}}),
0265 };
0266
0267 class SampleProfileWriterExtBinaryBase : public SampleProfileWriterBinary {
0268 using SampleProfileWriterBinary::SampleProfileWriterBinary;
0269 public:
0270 std::error_code write(const SampleProfileMap &ProfileMap) override;
0271
0272 void setToCompressAllSections() override;
0273 void setToCompressSection(SecType Type);
0274 std::error_code writeSample(const FunctionSamples &S) override;
0275
0276
0277 void setUseMD5() override {
0278 UseMD5 = true;
0279 addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagMD5Name);
0280
0281
0282 addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagFixedLengthMD5);
0283 }
0284
0285
0286
0287
0288 void setPartialProfile() override {
0289 addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagPartial);
0290 }
0291
0292 void setProfileSymbolList(ProfileSymbolList *PSL) override {
0293 ProfSymList = PSL;
0294 };
0295
0296 void setUseCtxSplitLayout() override {
0297 resetSecLayout(SectionLayout::CtxSplitLayout);
0298 }
0299
0300 void resetSecLayout(SectionLayout SL) {
0301 verifySecLayout(SL);
0302 #ifndef NDEBUG
0303
0304 for (auto &Entry : SectionHdrLayout) {
0305 assert(Entry.Flags == 0 &&
0306 "resetSecLayout has to be called before any flag setting");
0307 }
0308 #endif
0309 SecLayout = SL;
0310 SectionHdrLayout = ExtBinaryHdrLayoutTable[SL];
0311 }
0312
0313 protected:
0314 uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx);
0315 std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx,
0316 uint64_t SectionStart);
0317 template <class SecFlagType>
0318 void addSectionFlag(SecType Type, SecFlagType Flag) {
0319 for (auto &Entry : SectionHdrLayout) {
0320 if (Entry.Type == Type)
0321 addSecFlag(Entry, Flag);
0322 }
0323 }
0324 template <class SecFlagType>
0325 void addSectionFlag(uint32_t SectionIdx, SecFlagType Flag) {
0326 addSecFlag(SectionHdrLayout[SectionIdx], Flag);
0327 }
0328
0329 void addContext(const SampleContext &Context) override;
0330
0331
0332 virtual std::error_code writeCustomSection(SecType Type) = 0;
0333
0334 virtual void verifySecLayout(SectionLayout SL) = 0;
0335
0336
0337 virtual std::error_code writeSections(const SampleProfileMap &ProfileMap) = 0;
0338
0339
0340
0341 virtual std::error_code writeOneSection(SecType Type, uint32_t LayoutIdx,
0342 const SampleProfileMap &ProfileMap);
0343
0344
0345 std::error_code writeNameTable() override;
0346 std::error_code writeContextIdx(const SampleContext &Context) override;
0347 std::error_code writeCSNameIdx(const SampleContext &Context);
0348 std::error_code writeCSNameTableSection();
0349
0350 std::error_code writeFuncMetadata(const SampleProfileMap &Profiles);
0351 std::error_code writeFuncMetadata(const FunctionSamples &Profile);
0352
0353
0354 std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap);
0355 std::error_code writeFuncOffsetTable();
0356 std::error_code writeProfileSymbolListSection();
0357
0358 SectionLayout SecLayout = DefaultLayout;
0359
0360
0361
0362
0363 SmallVector<SecHdrTableEntry, 8> SectionHdrLayout =
0364 ExtBinaryHdrLayoutTable[DefaultLayout];
0365
0366
0367
0368
0369 uint64_t SecLBRProfileStart = 0;
0370
0371 private:
0372 void allocSecHdrTable();
0373 std::error_code writeSecHdrTable();
0374 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
0375 std::error_code compressAndOutput();
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 std::unique_ptr<raw_ostream> LocalBufStream;
0386
0387 uint64_t FileStart;
0388
0389
0390 uint64_t SecHdrTableOffset;
0391
0392
0393
0394
0395 std::vector<SecHdrTableEntry> SecHdrTable;
0396
0397
0398
0399 MapVector<SampleContext, uint64_t> FuncOffsetTable;
0400
0401 bool UseMD5 = false;
0402
0403
0404
0405 MapVector<SampleContext, uint32_t> CSNameTable;
0406
0407 ProfileSymbolList *ProfSymList = nullptr;
0408 };
0409
0410 class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
0411 public:
0412 SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS)
0413 : SampleProfileWriterExtBinaryBase(OS) {}
0414
0415 private:
0416 std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
0417 std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap);
0418
0419 std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
0420
0421 std::error_code writeCustomSection(SecType Type) override {
0422 return sampleprof_error::success;
0423 };
0424
0425 void verifySecLayout(SectionLayout SL) override {
0426 assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
0427 "Unsupported layout");
0428 }
0429 };
0430
0431 }
0432 }
0433
0434 #endif