void InstrProfWriter::writeImpl(ProfOStream &OS) { using namespace IndexedInstrProf; OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator; InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs); InfoObj->SummaryBuilder = &ISB; InstrProfSummaryBuilder CSISB(ProfileSummaryBuilder::DefaultCutoffs); InfoObj->CSSummaryBuilder = &CSISB; // Populate the hash table generator. for (const auto &I : FunctionData) if (shouldEncodeData(I.getValue())) Generator.insert(I.getKey(), &I.getValue()); // Write the header. IndexedInstrProf::Header Header; Header.Magic = IndexedInstrProf::Magic; Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion; if (ProfileKind == PF_IRLevel) Header.Version |= VARIANT_MASK_IR_PROF; if (ProfileKind == PF_IRLevelWithCS) { Header.Version |= VARIANT_MASK_IR_PROF; Header.Version |= VARIANT_MASK_CSIR_PROF; } Header.Unused = 0; Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType); Header.HashOffset = 0; int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t); // Only write out all the fields except 'HashOffset'. We need // to remember the offset of that field to allow back patching // later. for (int I = 0; I < N - 1; I++) OS.write(reinterpret_cast<uint64_t *>(&Header)[I]); // Save the location of Header.HashOffset field in \c OS. uint64_t HashTableStartFieldOffset = OS.tell(); // Reserve the space for HashOffset field. OS.write(0); // Reserve space to write profile summary data. uint32_t NumEntries = ProfileSummaryBuilder::DefaultCutoffs.size(); uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries); // Remember the summary offset. uint64_t SummaryOffset = OS.tell(); for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) OS.write(0); uint64_t CSSummaryOffset = 0; uint64_t CSSummarySize = 0; if (ProfileKind == PF_IRLevelWithCS) { CSSummaryOffset = OS.tell(); CSSummarySize = SummarySize / sizeof(uint64_t); for (unsigned I = 0; I < CSSummarySize; I++) OS.write(0); } // Write the hash table. uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj); // Allocate space for data to be serialized out. std::unique_ptr<IndexedInstrProf::Summary> TheSummary = IndexedInstrProf::allocSummary(SummarySize); // Compute the Summary and copy the data to the data // structure to be serialized out (to disk or buffer). std::unique_ptr<ProfileSummary> PS = ISB.getSummary(); setSummary(TheSummary.get(), *PS); InfoObj->SummaryBuilder = nullptr; // For Context Sensitive summary. std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary = nullptr; if (ProfileKind == PF_IRLevelWithCS) { TheCSSummary = IndexedInstrProf::allocSummary(SummarySize); std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary(); setSummary(TheCSSummary.get(), *CSPS); } InfoObj->CSSummaryBuilder = nullptr; // Now do the final patch: PatchItem PatchItems[] = { // Patch the Header.HashOffset field. {HashTableStartFieldOffset, &HashTableStart, 1}, // Patch the summary data. {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()), (int)(SummarySize / sizeof(uint64_t))}, {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()), (int)CSSummarySize}}; OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems)); }
void InstrProfWriter::writeImpl(ProfOStream &OS) { OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator; using namespace IndexedInstrProf; std::vector<uint32_t> Cutoffs(&SummaryCutoffs[0], &SummaryCutoffs[NumSummaryCutoffs]); ProfileSummary PS(Cutoffs); InfoObj->TheProfileSummary = &PS; // Populate the hash table generator. for (const auto &I : FunctionData) if (shouldEncodeData(I.getValue())) Generator.insert(I.getKey(), &I.getValue()); // Write the header. IndexedInstrProf::Header Header; Header.Magic = IndexedInstrProf::Magic; Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion; Header.Unused = 0; Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType); Header.HashOffset = 0; int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t); // Only write out all the fields except 'HashOffset'. We need // to remember the offset of that field to allow back patching // later. for (int I = 0; I < N - 1; I++) OS.write(reinterpret_cast<uint64_t *>(&Header)[I]); // Save the location of Header.HashOffset field in \c OS. uint64_t HashTableStartFieldOffset = OS.tell(); // Reserve the space for HashOffset field. OS.write(0); // Reserve space to write profile summary data. uint32_t NumEntries = Cutoffs.size(); uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries); // Remember the summary offset. uint64_t SummaryOffset = OS.tell(); for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) OS.write(0); // Write the hash table. uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj); // Allocate space for data to be serialized out. std::unique_ptr<IndexedInstrProf::Summary> TheSummary = IndexedInstrProf::allocSummary(SummarySize); // Compute the Summary and copy the data to the data // structure to be serialized out (to disk or buffer). setSummary(TheSummary.get(), PS); InfoObj->TheProfileSummary = 0; // Now do the final patch: PatchItem PatchItems[] = { // Patch the Header.HashOffset field. {HashTableStartFieldOffset, &HashTableStart, 1}, // Patch the summary data. {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()), (int)(SummarySize / sizeof(uint64_t))}}; OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems)); }