xref: /llvm-project/llvm/lib/CGData/CodeGenDataWriter.cpp (revision ffcf3c8688f57acaf6a404a1238673c9d197ba9a)
19bb55568SKyungwoo Lee //===- CodeGenDataWriter.cpp ----------------------------------------------===//
29bb55568SKyungwoo Lee //
39bb55568SKyungwoo Lee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49bb55568SKyungwoo Lee // See https://llvm.org/LICENSE.txt for license information.
59bb55568SKyungwoo Lee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69bb55568SKyungwoo Lee //
79bb55568SKyungwoo Lee //===----------------------------------------------------------------------===//
89bb55568SKyungwoo Lee //
99bb55568SKyungwoo Lee // This file contains support for writing codegen data.
109bb55568SKyungwoo Lee //
119bb55568SKyungwoo Lee //===----------------------------------------------------------------------===//
129bb55568SKyungwoo Lee 
139bb55568SKyungwoo Lee #include "llvm/CGData/CodeGenDataWriter.h"
149bb55568SKyungwoo Lee 
159bb55568SKyungwoo Lee #define DEBUG_TYPE "cg-data-writer"
169bb55568SKyungwoo Lee 
179bb55568SKyungwoo Lee using namespace llvm;
189bb55568SKyungwoo Lee 
199bb55568SKyungwoo Lee void CGDataOStream::patch(ArrayRef<CGDataPatchItem> P) {
209bb55568SKyungwoo Lee   using namespace support;
219bb55568SKyungwoo Lee 
229bb55568SKyungwoo Lee   if (IsFDOStream) {
239bb55568SKyungwoo Lee     raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
249bb55568SKyungwoo Lee     const uint64_t LastPos = FDOStream.tell();
259bb55568SKyungwoo Lee     for (const auto &K : P) {
269bb55568SKyungwoo Lee       FDOStream.seek(K.Pos);
279bb55568SKyungwoo Lee       for (int I = 0; I < K.N; I++)
289bb55568SKyungwoo Lee         write(K.D[I]);
299bb55568SKyungwoo Lee     }
309bb55568SKyungwoo Lee     // Reset the stream to the last position after patching so that users
319bb55568SKyungwoo Lee     // don't accidentally overwrite data. This makes it consistent with
329bb55568SKyungwoo Lee     // the string stream below which replaces the data directly.
339bb55568SKyungwoo Lee     FDOStream.seek(LastPos);
349bb55568SKyungwoo Lee   } else {
359bb55568SKyungwoo Lee     raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
369bb55568SKyungwoo Lee     std::string &Data = SOStream.str(); // with flush
379bb55568SKyungwoo Lee     for (const auto &K : P) {
389bb55568SKyungwoo Lee       for (int I = 0; I < K.N; I++) {
399bb55568SKyungwoo Lee         uint64_t Bytes =
409bb55568SKyungwoo Lee             endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
419bb55568SKyungwoo Lee         Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
429bb55568SKyungwoo Lee                      reinterpret_cast<const char *>(&Bytes), sizeof(uint64_t));
439bb55568SKyungwoo Lee       }
449bb55568SKyungwoo Lee     }
459bb55568SKyungwoo Lee   }
469bb55568SKyungwoo Lee }
479bb55568SKyungwoo Lee 
489bb55568SKyungwoo Lee void CodeGenDataWriter::addRecord(OutlinedHashTreeRecord &Record) {
499bb55568SKyungwoo Lee   assert(Record.HashTree && "empty hash tree in the record");
509bb55568SKyungwoo Lee   HashTreeRecord.HashTree = std::move(Record.HashTree);
519bb55568SKyungwoo Lee 
529bb55568SKyungwoo Lee   DataKind |= CGDataKind::FunctionOutlinedHashTree;
539bb55568SKyungwoo Lee }
549bb55568SKyungwoo Lee 
55*ffcf3c86SKyungwoo Lee void CodeGenDataWriter::addRecord(StableFunctionMapRecord &Record) {
56*ffcf3c86SKyungwoo Lee   assert(Record.FunctionMap && "empty function map in the record");
57*ffcf3c86SKyungwoo Lee   FunctionMapRecord.FunctionMap = std::move(Record.FunctionMap);
58*ffcf3c86SKyungwoo Lee 
59*ffcf3c86SKyungwoo Lee   DataKind |= CGDataKind::StableFunctionMergingMap;
60*ffcf3c86SKyungwoo Lee }
61*ffcf3c86SKyungwoo Lee 
629bb55568SKyungwoo Lee Error CodeGenDataWriter::write(raw_fd_ostream &OS) {
639bb55568SKyungwoo Lee   CGDataOStream COS(OS);
649bb55568SKyungwoo Lee   return writeImpl(COS);
659bb55568SKyungwoo Lee }
669bb55568SKyungwoo Lee 
679bb55568SKyungwoo Lee Error CodeGenDataWriter::writeHeader(CGDataOStream &COS) {
689bb55568SKyungwoo Lee   using namespace support;
699bb55568SKyungwoo Lee   IndexedCGData::Header Header;
709bb55568SKyungwoo Lee   Header.Magic = IndexedCGData::Magic;
719bb55568SKyungwoo Lee   Header.Version = IndexedCGData::Version;
729bb55568SKyungwoo Lee 
739bb55568SKyungwoo Lee   // Set the CGDataKind depending on the kind.
749bb55568SKyungwoo Lee   Header.DataKind = 0;
759bb55568SKyungwoo Lee   if (static_cast<bool>(DataKind & CGDataKind::FunctionOutlinedHashTree))
769bb55568SKyungwoo Lee     Header.DataKind |=
779bb55568SKyungwoo Lee         static_cast<uint32_t>(CGDataKind::FunctionOutlinedHashTree);
78*ffcf3c86SKyungwoo Lee   if (static_cast<bool>(DataKind & CGDataKind::StableFunctionMergingMap))
79*ffcf3c86SKyungwoo Lee     Header.DataKind |=
80*ffcf3c86SKyungwoo Lee         static_cast<uint32_t>(CGDataKind::StableFunctionMergingMap);
819bb55568SKyungwoo Lee   Header.OutlinedHashTreeOffset = 0;
82*ffcf3c86SKyungwoo Lee   Header.StableFunctionMapOffset = 0;
839bb55568SKyungwoo Lee 
849bb55568SKyungwoo Lee   // Only write up to the CGDataKind. We need to remember the offset of the
859bb55568SKyungwoo Lee   // remaining fields to allow back-patching later.
869bb55568SKyungwoo Lee   COS.write(Header.Magic);
879bb55568SKyungwoo Lee   COS.write32(Header.Version);
889bb55568SKyungwoo Lee   COS.write32(Header.DataKind);
899bb55568SKyungwoo Lee 
909bb55568SKyungwoo Lee   // Save the location of Header.OutlinedHashTreeOffset field in \c COS.
919bb55568SKyungwoo Lee   OutlinedHashTreeOffset = COS.tell();
929bb55568SKyungwoo Lee 
939bb55568SKyungwoo Lee   // Reserve the space for OutlinedHashTreeOffset field.
949bb55568SKyungwoo Lee   COS.write(0);
959bb55568SKyungwoo Lee 
96*ffcf3c86SKyungwoo Lee   // Save the location of Header.StableFunctionMapOffset field in \c COS.
97*ffcf3c86SKyungwoo Lee   StableFunctionMapOffset = COS.tell();
98*ffcf3c86SKyungwoo Lee 
99*ffcf3c86SKyungwoo Lee   // Reserve the space for StableFunctionMapOffset field.
100*ffcf3c86SKyungwoo Lee   COS.write(0);
101*ffcf3c86SKyungwoo Lee 
1029bb55568SKyungwoo Lee   return Error::success();
1039bb55568SKyungwoo Lee }
1049bb55568SKyungwoo Lee 
1059bb55568SKyungwoo Lee Error CodeGenDataWriter::writeImpl(CGDataOStream &COS) {
1069bb55568SKyungwoo Lee   if (Error E = writeHeader(COS))
1079bb55568SKyungwoo Lee     return E;
1089bb55568SKyungwoo Lee 
1099bb55568SKyungwoo Lee   uint64_t OutlinedHashTreeFieldStart = COS.tell();
1109bb55568SKyungwoo Lee   if (hasOutlinedHashTree())
1119bb55568SKyungwoo Lee     HashTreeRecord.serialize(COS.OS);
112*ffcf3c86SKyungwoo Lee   uint64_t StableFunctionMapFieldStart = COS.tell();
113*ffcf3c86SKyungwoo Lee   if (hasStableFunctionMap())
114*ffcf3c86SKyungwoo Lee     FunctionMapRecord.serialize(COS.OS);
1159bb55568SKyungwoo Lee 
1169bb55568SKyungwoo Lee   // Back patch the offsets.
1179bb55568SKyungwoo Lee   CGDataPatchItem PatchItems[] = {
118*ffcf3c86SKyungwoo Lee       {OutlinedHashTreeOffset, &OutlinedHashTreeFieldStart, 1},
119*ffcf3c86SKyungwoo Lee       {StableFunctionMapOffset, &StableFunctionMapFieldStart, 1}};
1209bb55568SKyungwoo Lee   COS.patch(PatchItems);
1219bb55568SKyungwoo Lee 
1229bb55568SKyungwoo Lee   return Error::success();
1239bb55568SKyungwoo Lee }
1249bb55568SKyungwoo Lee 
1259bb55568SKyungwoo Lee Error CodeGenDataWriter::writeHeaderText(raw_fd_ostream &OS) {
1269bb55568SKyungwoo Lee   if (hasOutlinedHashTree())
1279bb55568SKyungwoo Lee     OS << "# Outlined stable hash tree\n:outlined_hash_tree\n";
1289bb55568SKyungwoo Lee 
129*ffcf3c86SKyungwoo Lee   if (hasStableFunctionMap())
130*ffcf3c86SKyungwoo Lee     OS << "# Stable function map\n:stable_function_map\n";
131*ffcf3c86SKyungwoo Lee 
1329bb55568SKyungwoo Lee   // TODO: Add more data types in this header
1339bb55568SKyungwoo Lee 
1349bb55568SKyungwoo Lee   return Error::success();
1359bb55568SKyungwoo Lee }
1369bb55568SKyungwoo Lee 
1379bb55568SKyungwoo Lee Error CodeGenDataWriter::writeText(raw_fd_ostream &OS) {
1389bb55568SKyungwoo Lee   if (Error E = writeHeaderText(OS))
1399bb55568SKyungwoo Lee     return E;
1409bb55568SKyungwoo Lee 
1419bb55568SKyungwoo Lee   yaml::Output YOS(OS);
1429bb55568SKyungwoo Lee   if (hasOutlinedHashTree())
1439bb55568SKyungwoo Lee     HashTreeRecord.serializeYAML(YOS);
1449bb55568SKyungwoo Lee 
145*ffcf3c86SKyungwoo Lee   if (hasStableFunctionMap())
146*ffcf3c86SKyungwoo Lee     FunctionMapRecord.serializeYAML(YOS);
147*ffcf3c86SKyungwoo Lee 
1489bb55568SKyungwoo Lee   // TODO: Write more yaml cgdata in order
1499bb55568SKyungwoo Lee 
1509bb55568SKyungwoo Lee   return Error::success();
1519bb55568SKyungwoo Lee }
152