Path: blob/main/contrib/llvm-project/llvm/lib/CGData/CodeGenDataWriter.cpp
213764 views
//===- CodeGenDataWriter.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 file contains support for writing codegen data.9//10//===----------------------------------------------------------------------===//1112#include "llvm/CGData/CodeGenDataWriter.h"1314#define DEBUG_TYPE "cg-data-writer"1516using namespace llvm;1718void CGDataOStream::patch(ArrayRef<CGDataPatchItem> P) {19using namespace support;2021switch (Kind) {22case OStreamKind::fd: {23raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);24const uint64_t LastPos = FDOStream.tell();25for (const auto &K : P) {26FDOStream.seek(K.Pos);27for (size_t I = 0; I < K.D.size(); ++I)28write(K.D[I]);29}30// Reset the stream to the last position after patching so that users31// don't accidentally overwrite data. This makes it consistent with32// the string stream below which replaces the data directly.33FDOStream.seek(LastPos);34break;35}36case OStreamKind::string: {37raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);38std::string &Data = SOStream.str(); // with flush39for (const auto &K : P) {40for (size_t I = 0; I < K.D.size(); ++I) {41uint64_t Bytes =42endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);43Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),44reinterpret_cast<const char *>(&Bytes), sizeof(uint64_t));45}46}47break;48}49case OStreamKind::svector: {50raw_svector_ostream &VOStream = static_cast<raw_svector_ostream &>(OS);51for (const auto &K : P) {52for (size_t I = 0; I < K.D.size(); ++I) {53uint64_t Bytes =54endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);55VOStream.pwrite(reinterpret_cast<const char *>(&Bytes),56sizeof(uint64_t), K.Pos + I * sizeof(uint64_t));57}58}59break;60}61}62}6364void CodeGenDataWriter::addRecord(OutlinedHashTreeRecord &Record) {65assert(Record.HashTree && "empty hash tree in the record");66HashTreeRecord.HashTree = std::move(Record.HashTree);6768DataKind |= CGDataKind::FunctionOutlinedHashTree;69}7071void CodeGenDataWriter::addRecord(StableFunctionMapRecord &Record) {72assert(Record.FunctionMap && "empty function map in the record");73FunctionMapRecord.FunctionMap = std::move(Record.FunctionMap);7475DataKind |= CGDataKind::StableFunctionMergingMap;76}7778Error CodeGenDataWriter::write(raw_fd_ostream &OS) {79CGDataOStream COS(OS);80return writeImpl(COS);81}8283Error CodeGenDataWriter::writeHeader(CGDataOStream &COS) {84using namespace support;85IndexedCGData::Header Header;86Header.Magic = IndexedCGData::Magic;87Header.Version = IndexedCGData::Version;8889// Set the CGDataKind depending on the kind.90Header.DataKind = 0;91if (static_cast<bool>(DataKind & CGDataKind::FunctionOutlinedHashTree))92Header.DataKind |=93static_cast<uint32_t>(CGDataKind::FunctionOutlinedHashTree);94if (static_cast<bool>(DataKind & CGDataKind::StableFunctionMergingMap))95Header.DataKind |=96static_cast<uint32_t>(CGDataKind::StableFunctionMergingMap);97Header.OutlinedHashTreeOffset = 0;98Header.StableFunctionMapOffset = 0;99100// Only write up to the CGDataKind. We need to remember the offset of the101// remaining fields to allow back-patching later.102COS.write(Header.Magic);103COS.write32(Header.Version);104COS.write32(Header.DataKind);105106// Save the location of Header.OutlinedHashTreeOffset field in \c COS.107OutlinedHashTreeOffset = COS.tell();108109// Reserve the space for OutlinedHashTreeOffset field.110COS.write(0);111112// Save the location of Header.StableFunctionMapOffset field in \c COS.113StableFunctionMapOffset = COS.tell();114115// Reserve the space for StableFunctionMapOffset field.116COS.write(0);117118return Error::success();119}120121Error CodeGenDataWriter::writeImpl(CGDataOStream &COS) {122if (Error E = writeHeader(COS))123return E;124125std::vector<CGDataPatchItem> PatchItems;126127uint64_t OutlinedHashTreeFieldStart = COS.tell();128if (hasOutlinedHashTree())129HashTreeRecord.serialize(COS.OS);130uint64_t StableFunctionMapFieldStart = COS.tell();131if (hasStableFunctionMap())132FunctionMapRecord.serialize(COS.OS, PatchItems);133134// Back patch the offsets.135PatchItems.emplace_back(OutlinedHashTreeOffset, &OutlinedHashTreeFieldStart,1361);137PatchItems.emplace_back(StableFunctionMapOffset, &StableFunctionMapFieldStart,1381);139COS.patch(PatchItems);140141return Error::success();142}143144Error CodeGenDataWriter::writeHeaderText(raw_fd_ostream &OS) {145if (hasOutlinedHashTree())146OS << "# Outlined stable hash tree\n:outlined_hash_tree\n";147148if (hasStableFunctionMap())149OS << "# Stable function map\n:stable_function_map\n";150151// TODO: Add more data types in this header152153return Error::success();154}155156Error CodeGenDataWriter::writeText(raw_fd_ostream &OS) {157if (Error E = writeHeaderText(OS))158return E;159160yaml::Output YOS(OS);161if (hasOutlinedHashTree())162HashTreeRecord.serializeYAML(YOS);163164if (hasStableFunctionMap())165FunctionMapRecord.serializeYAML(YOS);166167// TODO: Write more yaml cgdata in order168169return Error::success();170}171172173