Path: blob/main/contrib/llvm-project/llvm/lib/CGData/StableFunctionMapRecord.cpp
213764 views
//===-- StableFunctionMapRecord.cpp ---------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This implements the functionality for the StableFunctionMapRecord class,9// including methods for serialization and deserialization of stable function10// maps to and from raw and YAML streams. It also includes utilities for11// managing function entries and their metadata.12//13//===----------------------------------------------------------------------===//1415#include "llvm/CGData/StableFunctionMapRecord.h"16#include "llvm/Support/EndianStream.h"1718#define DEBUG_TYPE "stable-function-map-record"1920using namespace llvm;21using namespace llvm::support;2223LLVM_YAML_IS_SEQUENCE_VECTOR(IndexPairHash)24LLVM_YAML_IS_SEQUENCE_VECTOR(StableFunction)2526namespace llvm {27namespace yaml {2829template <> struct MappingTraits<IndexPairHash> {30static void mapping(IO &IO, IndexPairHash &Key) {31IO.mapRequired("InstIndex", Key.first.first);32IO.mapRequired("OpndIndex", Key.first.second);33IO.mapRequired("OpndHash", Key.second);34}35};3637template <> struct MappingTraits<StableFunction> {38static void mapping(IO &IO, StableFunction &Func) {39IO.mapRequired("Hash", Func.Hash);40IO.mapRequired("FunctionName", Func.FunctionName);41IO.mapRequired("ModuleName", Func.ModuleName);42IO.mapRequired("InstCount", Func.InstCount);43IO.mapRequired("IndexOperandHashes", Func.IndexOperandHashes);44}45};4647} // namespace yaml48} // namespace llvm4950// Get a sorted vector of StableFunctionEntry pointers.51static SmallVector<const StableFunctionMap::StableFunctionEntry *>52getStableFunctionEntries(const StableFunctionMap &SFM) {53SmallVector<const StableFunctionMap::StableFunctionEntry *> FuncEntries;54for (const auto &P : SFM.getFunctionMap())55for (auto &Func : P.second)56FuncEntries.emplace_back(Func.get());5758llvm::stable_sort(59FuncEntries, [&](auto &A, auto &B) {60return std::tuple(A->Hash, SFM.getNameForId(A->ModuleNameId),61SFM.getNameForId(A->FunctionNameId)) <62std::tuple(B->Hash, SFM.getNameForId(B->ModuleNameId),63SFM.getNameForId(B->FunctionNameId));64});65return FuncEntries;66}6768// Get a sorted vector of IndexOperandHashes.69static IndexOperandHashVecType getStableIndexOperandHashes(70const StableFunctionMap::StableFunctionEntry *FuncEntry) {71IndexOperandHashVecType IndexOperandHashes;72for (auto &[Indices, OpndHash] : *FuncEntry->IndexOperandHashMap)73IndexOperandHashes.emplace_back(Indices, OpndHash);74// The indices are unique, so we can just sort by the first.75llvm::sort(IndexOperandHashes);76return IndexOperandHashes;77}7879void StableFunctionMapRecord::serialize(80raw_ostream &OS, std::vector<CGDataPatchItem> &PatchItems) const {81serialize(OS, FunctionMap.get(), PatchItems);82}8384void StableFunctionMapRecord::serialize(85raw_ostream &OS, const StableFunctionMap *FunctionMap,86std::vector<CGDataPatchItem> &PatchItems) {87support::endian::Writer Writer(OS, endianness::little);8889// Write Names.90ArrayRef<std::string> Names = FunctionMap->getNames();91Writer.write<uint32_t>(Names.size());92// Remember the position, write back the total size of Names, so we can skip93// reading them if needed.94const uint64_t NamesByteSizeOffset = Writer.OS.tell();95Writer.write<uint64_t>(0);96for (auto &Name : Names)97Writer.OS << Name << '\0';98// Align current position to 4 bytes.99uint32_t Padding = offsetToAlignment(Writer.OS.tell(), Align(4));100for (uint32_t I = 0; I < Padding; ++I)101Writer.OS << '\0';102const auto NamesByteSize =103Writer.OS.tell() - NamesByteSizeOffset - sizeof(NamesByteSizeOffset);104PatchItems.emplace_back(NamesByteSizeOffset, &NamesByteSize, 1);105106// Write StableFunctionEntries whose pointers are sorted.107auto FuncEntries = getStableFunctionEntries(*FunctionMap);108Writer.write<uint32_t>(FuncEntries.size());109110for (const auto *FuncRef : FuncEntries) {111Writer.write<stable_hash>(FuncRef->Hash);112Writer.write<uint32_t>(FuncRef->FunctionNameId);113Writer.write<uint32_t>(FuncRef->ModuleNameId);114Writer.write<uint32_t>(FuncRef->InstCount);115116// Emit IndexOperandHashes sorted from IndexOperandHashMap.117IndexOperandHashVecType IndexOperandHashes =118getStableIndexOperandHashes(FuncRef);119Writer.write<uint32_t>(IndexOperandHashes.size());120for (auto &IndexOperandHash : IndexOperandHashes) {121Writer.write<uint32_t>(IndexOperandHash.first.first);122Writer.write<uint32_t>(IndexOperandHash.first.second);123Writer.write<stable_hash>(IndexOperandHash.second);124}125}126}127128void StableFunctionMapRecord::deserialize(const unsigned char *&Ptr,129bool ReadStableFunctionMapNames) {130// Assert that Ptr is 4-byte aligned131assert(((uintptr_t)Ptr % 4) == 0);132// Read Names.133auto NumNames =134endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);135// Early exit if there is no name.136if (NumNames == 0)137return;138const auto NamesByteSize =139endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);140const auto NamesOffset = reinterpret_cast<uintptr_t>(Ptr);141if (ReadStableFunctionMapNames) {142for (unsigned I = 0; I < NumNames; ++I) {143StringRef Name(reinterpret_cast<const char *>(Ptr));144Ptr += Name.size() + 1;145FunctionMap->getIdOrCreateForName(Name);146}147// Align Ptr to 4 bytes.148Ptr = reinterpret_cast<const uint8_t *>(alignAddr(Ptr, Align(4)));149assert(reinterpret_cast<uintptr_t>(Ptr) - NamesOffset == NamesByteSize &&150"NamesByteSize does not match the actual size of names");151} else {152// skip reading Names by advancing the pointer.153Ptr = reinterpret_cast<const uint8_t *>(NamesOffset + NamesByteSize);154}155156// Read StableFunctionEntries.157auto NumFuncs =158endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);159for (unsigned I = 0; I < NumFuncs; ++I) {160auto Hash =161endian::readNext<stable_hash, endianness::little, unaligned>(Ptr);162auto FunctionNameId =163endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);164assert(FunctionMap->getNameForId(FunctionNameId) &&165"FunctionNameId out of range");166auto ModuleNameId =167endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);168assert(FunctionMap->getNameForId(ModuleNameId) &&169"ModuleNameId out of range");170auto InstCount =171endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);172173// Read IndexOperandHashes to build IndexOperandHashMap174auto NumIndexOperandHashes =175endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);176auto IndexOperandHashMap = std::make_unique<IndexOperandHashMapType>();177for (unsigned J = 0; J < NumIndexOperandHashes; ++J) {178auto InstIndex =179endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);180auto OpndIndex =181endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);182auto OpndHash =183endian::readNext<stable_hash, endianness::little, unaligned>(Ptr);184assert(InstIndex < InstCount && "InstIndex out of range");185186IndexOperandHashMap->try_emplace({InstIndex, OpndIndex}, OpndHash);187}188189// Insert a new StableFunctionEntry into the map.190auto FuncEntry = std::make_unique<StableFunctionMap::StableFunctionEntry>(191Hash, FunctionNameId, ModuleNameId, InstCount,192std::move(IndexOperandHashMap));193194FunctionMap->insert(std::move(FuncEntry));195}196}197198void StableFunctionMapRecord::serializeYAML(yaml::Output &YOS) const {199auto FuncEntries = getStableFunctionEntries(*FunctionMap);200SmallVector<StableFunction> Functions;201for (const auto *FuncEntry : FuncEntries) {202auto IndexOperandHashes = getStableIndexOperandHashes(FuncEntry);203Functions.emplace_back(204FuncEntry->Hash, *FunctionMap->getNameForId(FuncEntry->FunctionNameId),205*FunctionMap->getNameForId(FuncEntry->ModuleNameId),206FuncEntry->InstCount, std::move(IndexOperandHashes));207}208209YOS << Functions;210}211212void StableFunctionMapRecord::deserializeYAML(yaml::Input &YIS) {213std::vector<StableFunction> Funcs;214YIS >> Funcs;215for (auto &Func : Funcs)216FunctionMap->insert(Func);217YIS.nextDocument();218}219220221