brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · a2bbcee Raw
172 lines · cpp
1//===- CodeGenDataWriter.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains support for writing codegen data.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/CGData/CodeGenDataWriter.h"14 15#define DEBUG_TYPE "cg-data-writer"16 17using namespace llvm;18 19void CGDataOStream::patch(ArrayRef<CGDataPatchItem> P) {20  using namespace support;21 22  switch (Kind) {23  case OStreamKind::fd: {24    raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);25    const uint64_t LastPos = FDOStream.tell();26    for (const auto &K : P) {27      FDOStream.seek(K.Pos);28      for (size_t I = 0; I < K.D.size(); ++I)29        write(K.D[I]);30    }31    // Reset the stream to the last position after patching so that users32    // don't accidentally overwrite data. This makes it consistent with33    // the string stream below which replaces the data directly.34    FDOStream.seek(LastPos);35    break;36  }37  case OStreamKind::string: {38    raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);39    std::string &Data = SOStream.str(); // with flush40    for (const auto &K : P) {41      for (size_t I = 0; I < K.D.size(); ++I) {42        uint64_t Bytes =43            endian::byte_swap<uint64_t>(K.D[I], llvm::endianness::little);44        Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),45                     reinterpret_cast<const char *>(&Bytes), sizeof(uint64_t));46      }47    }48    break;49  }50  case OStreamKind::svector: {51    raw_svector_ostream &VOStream = static_cast<raw_svector_ostream &>(OS);52    for (const auto &K : P) {53      for (size_t I = 0; I < K.D.size(); ++I) {54        uint64_t Bytes =55            endian::byte_swap<uint64_t>(K.D[I], llvm::endianness::little);56        VOStream.pwrite(reinterpret_cast<const char *>(&Bytes),57                        sizeof(uint64_t), K.Pos + I * sizeof(uint64_t));58      }59    }60    break;61  }62  }63}64 65void CodeGenDataWriter::addRecord(OutlinedHashTreeRecord &Record) {66  assert(Record.HashTree && "empty hash tree in the record");67  HashTreeRecord.HashTree = std::move(Record.HashTree);68 69  DataKind |= CGDataKind::FunctionOutlinedHashTree;70}71 72void CodeGenDataWriter::addRecord(StableFunctionMapRecord &Record) {73  assert(Record.FunctionMap && "empty function map in the record");74  FunctionMapRecord.FunctionMap = std::move(Record.FunctionMap);75 76  DataKind |= CGDataKind::StableFunctionMergingMap;77}78 79Error CodeGenDataWriter::write(raw_fd_ostream &OS) {80  CGDataOStream COS(OS);81  return writeImpl(COS);82}83 84Error CodeGenDataWriter::writeHeader(CGDataOStream &COS) {85  using namespace support;86  IndexedCGData::Header Header;87  Header.Magic = IndexedCGData::Magic;88  Header.Version = IndexedCGData::Version;89 90  // Set the CGDataKind depending on the kind.91  Header.DataKind = 0;92  if (static_cast<bool>(DataKind & CGDataKind::FunctionOutlinedHashTree))93    Header.DataKind |=94        static_cast<uint32_t>(CGDataKind::FunctionOutlinedHashTree);95  if (static_cast<bool>(DataKind & CGDataKind::StableFunctionMergingMap))96    Header.DataKind |=97        static_cast<uint32_t>(CGDataKind::StableFunctionMergingMap);98  Header.OutlinedHashTreeOffset = 0;99  Header.StableFunctionMapOffset = 0;100 101  // Only write up to the CGDataKind. We need to remember the offset of the102  // remaining fields to allow back-patching later.103  COS.write(Header.Magic);104  COS.write32(Header.Version);105  COS.write32(Header.DataKind);106 107  // Save the location of Header.OutlinedHashTreeOffset field in \c COS.108  OutlinedHashTreeOffset = COS.tell();109 110  // Reserve the space for OutlinedHashTreeOffset field.111  COS.write(0);112 113  // Save the location of Header.StableFunctionMapOffset field in \c COS.114  StableFunctionMapOffset = COS.tell();115 116  // Reserve the space for StableFunctionMapOffset field.117  COS.write(0);118 119  return Error::success();120}121 122Error CodeGenDataWriter::writeImpl(CGDataOStream &COS) {123  if (Error E = writeHeader(COS))124    return E;125 126  std::vector<CGDataPatchItem> PatchItems;127 128  uint64_t OutlinedHashTreeFieldStart = COS.tell();129  if (hasOutlinedHashTree())130    HashTreeRecord.serialize(COS.OS);131  uint64_t StableFunctionMapFieldStart = COS.tell();132  if (hasStableFunctionMap())133    FunctionMapRecord.serialize(COS.OS, PatchItems);134 135  // Back patch the offsets.136  PatchItems.emplace_back(OutlinedHashTreeOffset, &OutlinedHashTreeFieldStart,137                          1);138  PatchItems.emplace_back(StableFunctionMapOffset, &StableFunctionMapFieldStart,139                          1);140  COS.patch(PatchItems);141 142  return Error::success();143}144 145Error CodeGenDataWriter::writeHeaderText(raw_fd_ostream &OS) {146  if (hasOutlinedHashTree())147    OS << "# Outlined stable hash tree\n:outlined_hash_tree\n";148 149  if (hasStableFunctionMap())150    OS << "# Stable function map\n:stable_function_map\n";151 152  // TODO: Add more data types in this header153 154  return Error::success();155}156 157Error CodeGenDataWriter::writeText(raw_fd_ostream &OS) {158  if (Error E = writeHeaderText(OS))159    return E;160 161  yaml::Output YOS(OS);162  if (hasOutlinedHashTree())163    HashTreeRecord.serializeYAML(YOS);164 165  if (hasStableFunctionMap())166    FunctionMapRecord.serializeYAML(YOS);167 168  // TODO: Write more yaml cgdata in order169 170  return Error::success();171}172