xref: /llvm-project/llvm/lib/CGData/OutlinedHashTreeRecord.cpp (revision e4e3ff5adc8b374be0620223ea2b654adde038ea)
19bb55568SKyungwoo Lee //===-- OutlinedHashTreeRecord.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 defines the OutlinedHashTreeRecord class. This class holds the outlined
109bb55568SKyungwoo Lee // hash tree for both serialization and deserialization processes. It utilizes
119bb55568SKyungwoo Lee // two data formats for serialization: raw binary data and YAML.
129bb55568SKyungwoo Lee // These two formats can be used interchangeably.
139bb55568SKyungwoo Lee //
149bb55568SKyungwoo Lee //===----------------------------------------------------------------------===//
159bb55568SKyungwoo Lee 
169bb55568SKyungwoo Lee #include "llvm/CGData/OutlinedHashTreeRecord.h"
179bb55568SKyungwoo Lee #include "llvm/ObjectYAML/YAML.h"
189bb55568SKyungwoo Lee #include "llvm/Support/Endian.h"
199bb55568SKyungwoo Lee #include "llvm/Support/EndianStream.h"
209bb55568SKyungwoo Lee 
219bb55568SKyungwoo Lee #define DEBUG_TYPE "outlined-hash-tree"
229bb55568SKyungwoo Lee 
239bb55568SKyungwoo Lee using namespace llvm;
249bb55568SKyungwoo Lee using namespace llvm::support;
259bb55568SKyungwoo Lee 
269bb55568SKyungwoo Lee namespace llvm {
279bb55568SKyungwoo Lee namespace yaml {
289bb55568SKyungwoo Lee 
299bb55568SKyungwoo Lee template <> struct MappingTraits<HashNodeStable> {
309bb55568SKyungwoo Lee   static void mapping(IO &io, HashNodeStable &res) {
319bb55568SKyungwoo Lee     io.mapRequired("Hash", res.Hash);
329bb55568SKyungwoo Lee     io.mapRequired("Terminals", res.Terminals);
339bb55568SKyungwoo Lee     io.mapRequired("SuccessorIds", res.SuccessorIds);
349bb55568SKyungwoo Lee   }
359bb55568SKyungwoo Lee };
369bb55568SKyungwoo Lee 
379bb55568SKyungwoo Lee template <> struct CustomMappingTraits<IdHashNodeStableMapTy> {
389bb55568SKyungwoo Lee   static void inputOne(IO &io, StringRef Key, IdHashNodeStableMapTy &V) {
399bb55568SKyungwoo Lee     HashNodeStable NodeStable;
409bb55568SKyungwoo Lee     io.mapRequired(Key.str().c_str(), NodeStable);
419bb55568SKyungwoo Lee     unsigned Id;
429bb55568SKyungwoo Lee     if (Key.getAsInteger(0, Id)) {
439bb55568SKyungwoo Lee       io.setError("Id not an integer");
449bb55568SKyungwoo Lee       return;
459bb55568SKyungwoo Lee     }
469bb55568SKyungwoo Lee     V.insert({Id, NodeStable});
479bb55568SKyungwoo Lee   }
489bb55568SKyungwoo Lee 
499bb55568SKyungwoo Lee   static void output(IO &io, IdHashNodeStableMapTy &V) {
509bb55568SKyungwoo Lee     for (auto Iter = V.begin(); Iter != V.end(); ++Iter)
519bb55568SKyungwoo Lee       io.mapRequired(utostr(Iter->first).c_str(), Iter->second);
529bb55568SKyungwoo Lee   }
539bb55568SKyungwoo Lee };
549bb55568SKyungwoo Lee 
559bb55568SKyungwoo Lee } // namespace yaml
569bb55568SKyungwoo Lee } // namespace llvm
579bb55568SKyungwoo Lee 
589bb55568SKyungwoo Lee void OutlinedHashTreeRecord::serialize(raw_ostream &OS) const {
599bb55568SKyungwoo Lee   IdHashNodeStableMapTy IdNodeStableMap;
609bb55568SKyungwoo Lee   convertToStableData(IdNodeStableMap);
619bb55568SKyungwoo Lee   support::endian::Writer Writer(OS, endianness::little);
629bb55568SKyungwoo Lee   Writer.write<uint32_t>(IdNodeStableMap.size());
639bb55568SKyungwoo Lee 
649bb55568SKyungwoo Lee   for (const auto &[Id, NodeStable] : IdNodeStableMap) {
659bb55568SKyungwoo Lee     Writer.write<uint32_t>(Id);
669bb55568SKyungwoo Lee     Writer.write<uint64_t>(NodeStable.Hash);
679bb55568SKyungwoo Lee     Writer.write<uint32_t>(NodeStable.Terminals);
689bb55568SKyungwoo Lee     Writer.write<uint32_t>(NodeStable.SuccessorIds.size());
699bb55568SKyungwoo Lee     for (auto SuccessorId : NodeStable.SuccessorIds)
709bb55568SKyungwoo Lee       Writer.write<uint32_t>(SuccessorId);
719bb55568SKyungwoo Lee   }
729bb55568SKyungwoo Lee }
739bb55568SKyungwoo Lee 
749bb55568SKyungwoo Lee void OutlinedHashTreeRecord::deserialize(const unsigned char *&Ptr) {
759bb55568SKyungwoo Lee   IdHashNodeStableMapTy IdNodeStableMap;
769bb55568SKyungwoo Lee   auto NumIdNodeStableMap =
779bb55568SKyungwoo Lee       endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
789bb55568SKyungwoo Lee 
799bb55568SKyungwoo Lee   for (unsigned I = 0; I < NumIdNodeStableMap; ++I) {
809bb55568SKyungwoo Lee     auto Id = endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
819bb55568SKyungwoo Lee     HashNodeStable NodeStable;
829bb55568SKyungwoo Lee     NodeStable.Hash =
839bb55568SKyungwoo Lee         endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);
849bb55568SKyungwoo Lee     NodeStable.Terminals =
859bb55568SKyungwoo Lee         endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
869bb55568SKyungwoo Lee     auto NumSuccessorIds =
879bb55568SKyungwoo Lee         endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
889bb55568SKyungwoo Lee     for (unsigned J = 0; J < NumSuccessorIds; ++J)
899bb55568SKyungwoo Lee       NodeStable.SuccessorIds.push_back(
909bb55568SKyungwoo Lee           endian::readNext<uint32_t, endianness::little, unaligned>(Ptr));
919bb55568SKyungwoo Lee 
929bb55568SKyungwoo Lee     IdNodeStableMap[Id] = std::move(NodeStable);
939bb55568SKyungwoo Lee   }
949bb55568SKyungwoo Lee 
959bb55568SKyungwoo Lee   convertFromStableData(IdNodeStableMap);
969bb55568SKyungwoo Lee }
979bb55568SKyungwoo Lee 
989bb55568SKyungwoo Lee void OutlinedHashTreeRecord::serializeYAML(yaml::Output &YOS) const {
999bb55568SKyungwoo Lee   IdHashNodeStableMapTy IdNodeStableMap;
1009bb55568SKyungwoo Lee   convertToStableData(IdNodeStableMap);
1019bb55568SKyungwoo Lee 
1029bb55568SKyungwoo Lee   YOS << IdNodeStableMap;
1039bb55568SKyungwoo Lee }
1049bb55568SKyungwoo Lee 
1059bb55568SKyungwoo Lee void OutlinedHashTreeRecord::deserializeYAML(yaml::Input &YIS) {
1069bb55568SKyungwoo Lee   IdHashNodeStableMapTy IdNodeStableMap;
1079bb55568SKyungwoo Lee 
1089bb55568SKyungwoo Lee   YIS >> IdNodeStableMap;
1099bb55568SKyungwoo Lee   YIS.nextDocument();
1109bb55568SKyungwoo Lee 
1119bb55568SKyungwoo Lee   convertFromStableData(IdNodeStableMap);
1129bb55568SKyungwoo Lee }
1139bb55568SKyungwoo Lee 
1149bb55568SKyungwoo Lee void OutlinedHashTreeRecord::convertToStableData(
1159bb55568SKyungwoo Lee     IdHashNodeStableMapTy &IdNodeStableMap) const {
1169bb55568SKyungwoo Lee   // Build NodeIdMap
1179bb55568SKyungwoo Lee   HashNodeIdMapTy NodeIdMap;
1189bb55568SKyungwoo Lee   HashTree->walkGraph(
1199bb55568SKyungwoo Lee       [&NodeIdMap](const HashNode *Current) {
1209bb55568SKyungwoo Lee         size_t Index = NodeIdMap.size();
1219bb55568SKyungwoo Lee         NodeIdMap[Current] = Index;
1229bb55568SKyungwoo Lee         assert((Index + 1 == NodeIdMap.size()) &&
1239bb55568SKyungwoo Lee                "Duplicate key in NodeIdMap: 'Current' should be unique.");
1249bb55568SKyungwoo Lee       },
1259bb55568SKyungwoo Lee       /*EdgeCallbackFn=*/nullptr, /*SortedWork=*/true);
1269bb55568SKyungwoo Lee 
1279bb55568SKyungwoo Lee   // Convert NodeIdMap to NodeStableMap
1289bb55568SKyungwoo Lee   for (auto &P : NodeIdMap) {
1299bb55568SKyungwoo Lee     auto *Node = P.first;
1309bb55568SKyungwoo Lee     auto Id = P.second;
1319bb55568SKyungwoo Lee     HashNodeStable NodeStable;
1329bb55568SKyungwoo Lee     NodeStable.Hash = Node->Hash;
133*e4e3ff5aSKazu Hirata     NodeStable.Terminals = Node->Terminals.value_or(0);
1349bb55568SKyungwoo Lee     for (auto &P : Node->Successors)
1359bb55568SKyungwoo Lee       NodeStable.SuccessorIds.push_back(NodeIdMap[P.second.get()]);
1369bb55568SKyungwoo Lee     IdNodeStableMap[Id] = NodeStable;
1379bb55568SKyungwoo Lee   }
1389bb55568SKyungwoo Lee 
1399bb55568SKyungwoo Lee   // Sort the Successors so that they come out in the same order as in the map.
1409bb55568SKyungwoo Lee   for (auto &P : IdNodeStableMap)
1419bb55568SKyungwoo Lee     llvm::sort(P.second.SuccessorIds);
1429bb55568SKyungwoo Lee }
1439bb55568SKyungwoo Lee 
1449bb55568SKyungwoo Lee void OutlinedHashTreeRecord::convertFromStableData(
1459bb55568SKyungwoo Lee     const IdHashNodeStableMapTy &IdNodeStableMap) {
1469bb55568SKyungwoo Lee   IdHashNodeMapTy IdNodeMap;
1479bb55568SKyungwoo Lee   // Initialize the root node at 0.
1489bb55568SKyungwoo Lee   IdNodeMap[0] = HashTree->getRoot();
1499bb55568SKyungwoo Lee   assert(IdNodeMap[0]->Successors.empty());
1509bb55568SKyungwoo Lee 
1519bb55568SKyungwoo Lee   for (auto &P : IdNodeStableMap) {
1529bb55568SKyungwoo Lee     auto Id = P.first;
1539bb55568SKyungwoo Lee     const HashNodeStable &NodeStable = P.second;
1549bb55568SKyungwoo Lee     assert(IdNodeMap.count(Id));
1559bb55568SKyungwoo Lee     HashNode *Curr = IdNodeMap[Id];
1569bb55568SKyungwoo Lee     Curr->Hash = NodeStable.Hash;
1579bb55568SKyungwoo Lee     if (NodeStable.Terminals)
1589bb55568SKyungwoo Lee       Curr->Terminals = NodeStable.Terminals;
1599bb55568SKyungwoo Lee     auto &Successors = Curr->Successors;
1609bb55568SKyungwoo Lee     assert(Successors.empty());
1619bb55568SKyungwoo Lee     for (auto SuccessorId : NodeStable.SuccessorIds) {
1629bb55568SKyungwoo Lee       auto Sucessor = std::make_unique<HashNode>();
1639bb55568SKyungwoo Lee       IdNodeMap[SuccessorId] = Sucessor.get();
1649bb55568SKyungwoo Lee       auto Hash = IdNodeStableMap.at(SuccessorId).Hash;
1659bb55568SKyungwoo Lee       Successors[Hash] = std::move(Sucessor);
1669bb55568SKyungwoo Lee     }
1679bb55568SKyungwoo Lee   }
1689bb55568SKyungwoo Lee }
169