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