xref: /freebsd/contrib/llvm-project/llvm/lib/CGData/OutlinedHashTreeRecord.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===-- OutlinedHashTreeRecord.cpp ----------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This defines the OutlinedHashTreeRecord class. This class holds the outlined
10*700637cbSDimitry Andric // hash tree for both serialization and deserialization processes. It utilizes
11*700637cbSDimitry Andric // two data formats for serialization: raw binary data and YAML.
12*700637cbSDimitry Andric // These two formats can be used interchangeably.
13*700637cbSDimitry Andric //
14*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
15*700637cbSDimitry Andric 
16*700637cbSDimitry Andric #include "llvm/CGData/OutlinedHashTreeRecord.h"
17*700637cbSDimitry Andric #include "llvm/ObjectYAML/YAML.h"
18*700637cbSDimitry Andric #include "llvm/Support/Endian.h"
19*700637cbSDimitry Andric #include "llvm/Support/EndianStream.h"
20*700637cbSDimitry Andric 
21*700637cbSDimitry Andric #define DEBUG_TYPE "outlined-hash-tree"
22*700637cbSDimitry Andric 
23*700637cbSDimitry Andric using namespace llvm;
24*700637cbSDimitry Andric using namespace llvm::support;
25*700637cbSDimitry Andric 
26*700637cbSDimitry Andric namespace llvm {
27*700637cbSDimitry Andric namespace yaml {
28*700637cbSDimitry Andric 
29*700637cbSDimitry Andric template <> struct MappingTraits<HashNodeStable> {
mappingllvm::yaml::MappingTraits30*700637cbSDimitry Andric   static void mapping(IO &io, HashNodeStable &res) {
31*700637cbSDimitry Andric     io.mapRequired("Hash", res.Hash);
32*700637cbSDimitry Andric     io.mapRequired("Terminals", res.Terminals);
33*700637cbSDimitry Andric     io.mapRequired("SuccessorIds", res.SuccessorIds);
34*700637cbSDimitry Andric   }
35*700637cbSDimitry Andric };
36*700637cbSDimitry Andric 
37*700637cbSDimitry Andric template <> struct CustomMappingTraits<IdHashNodeStableMapTy> {
inputOnellvm::yaml::CustomMappingTraits38*700637cbSDimitry Andric   static void inputOne(IO &io, StringRef Key, IdHashNodeStableMapTy &V) {
39*700637cbSDimitry Andric     HashNodeStable NodeStable;
40*700637cbSDimitry Andric     io.mapRequired(Key.str().c_str(), NodeStable);
41*700637cbSDimitry Andric     unsigned Id;
42*700637cbSDimitry Andric     if (Key.getAsInteger(0, Id)) {
43*700637cbSDimitry Andric       io.setError("Id not an integer");
44*700637cbSDimitry Andric       return;
45*700637cbSDimitry Andric     }
46*700637cbSDimitry Andric     V.insert({Id, NodeStable});
47*700637cbSDimitry Andric   }
48*700637cbSDimitry Andric 
outputllvm::yaml::CustomMappingTraits49*700637cbSDimitry Andric   static void output(IO &io, IdHashNodeStableMapTy &V) {
50*700637cbSDimitry Andric     for (auto Iter = V.begin(); Iter != V.end(); ++Iter)
51*700637cbSDimitry Andric       io.mapRequired(utostr(Iter->first).c_str(), Iter->second);
52*700637cbSDimitry Andric   }
53*700637cbSDimitry Andric };
54*700637cbSDimitry Andric 
55*700637cbSDimitry Andric } // namespace yaml
56*700637cbSDimitry Andric } // namespace llvm
57*700637cbSDimitry Andric 
serialize(raw_ostream & OS) const58*700637cbSDimitry Andric void OutlinedHashTreeRecord::serialize(raw_ostream &OS) const {
59*700637cbSDimitry Andric   IdHashNodeStableMapTy IdNodeStableMap;
60*700637cbSDimitry Andric   convertToStableData(IdNodeStableMap);
61*700637cbSDimitry Andric   support::endian::Writer Writer(OS, endianness::little);
62*700637cbSDimitry Andric   Writer.write<uint32_t>(IdNodeStableMap.size());
63*700637cbSDimitry Andric 
64*700637cbSDimitry Andric   for (const auto &[Id, NodeStable] : IdNodeStableMap) {
65*700637cbSDimitry Andric     Writer.write<uint32_t>(Id);
66*700637cbSDimitry Andric     Writer.write<uint64_t>(NodeStable.Hash);
67*700637cbSDimitry Andric     Writer.write<uint32_t>(NodeStable.Terminals);
68*700637cbSDimitry Andric     Writer.write<uint32_t>(NodeStable.SuccessorIds.size());
69*700637cbSDimitry Andric     for (auto SuccessorId : NodeStable.SuccessorIds)
70*700637cbSDimitry Andric       Writer.write<uint32_t>(SuccessorId);
71*700637cbSDimitry Andric   }
72*700637cbSDimitry Andric }
73*700637cbSDimitry Andric 
deserialize(const unsigned char * & Ptr)74*700637cbSDimitry Andric void OutlinedHashTreeRecord::deserialize(const unsigned char *&Ptr) {
75*700637cbSDimitry Andric   IdHashNodeStableMapTy IdNodeStableMap;
76*700637cbSDimitry Andric   auto NumIdNodeStableMap =
77*700637cbSDimitry Andric       endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
78*700637cbSDimitry Andric 
79*700637cbSDimitry Andric   for (unsigned I = 0; I < NumIdNodeStableMap; ++I) {
80*700637cbSDimitry Andric     auto Id = endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
81*700637cbSDimitry Andric     HashNodeStable NodeStable;
82*700637cbSDimitry Andric     NodeStable.Hash =
83*700637cbSDimitry Andric         endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);
84*700637cbSDimitry Andric     NodeStable.Terminals =
85*700637cbSDimitry Andric         endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
86*700637cbSDimitry Andric     auto NumSuccessorIds =
87*700637cbSDimitry Andric         endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
88*700637cbSDimitry Andric     for (unsigned J = 0; J < NumSuccessorIds; ++J)
89*700637cbSDimitry Andric       NodeStable.SuccessorIds.push_back(
90*700637cbSDimitry Andric           endian::readNext<uint32_t, endianness::little, unaligned>(Ptr));
91*700637cbSDimitry Andric 
92*700637cbSDimitry Andric     IdNodeStableMap[Id] = std::move(NodeStable);
93*700637cbSDimitry Andric   }
94*700637cbSDimitry Andric 
95*700637cbSDimitry Andric   convertFromStableData(IdNodeStableMap);
96*700637cbSDimitry Andric }
97*700637cbSDimitry Andric 
serializeYAML(yaml::Output & YOS) const98*700637cbSDimitry Andric void OutlinedHashTreeRecord::serializeYAML(yaml::Output &YOS) const {
99*700637cbSDimitry Andric   IdHashNodeStableMapTy IdNodeStableMap;
100*700637cbSDimitry Andric   convertToStableData(IdNodeStableMap);
101*700637cbSDimitry Andric 
102*700637cbSDimitry Andric   YOS << IdNodeStableMap;
103*700637cbSDimitry Andric }
104*700637cbSDimitry Andric 
deserializeYAML(yaml::Input & YIS)105*700637cbSDimitry Andric void OutlinedHashTreeRecord::deserializeYAML(yaml::Input &YIS) {
106*700637cbSDimitry Andric   IdHashNodeStableMapTy IdNodeStableMap;
107*700637cbSDimitry Andric 
108*700637cbSDimitry Andric   YIS >> IdNodeStableMap;
109*700637cbSDimitry Andric   YIS.nextDocument();
110*700637cbSDimitry Andric 
111*700637cbSDimitry Andric   convertFromStableData(IdNodeStableMap);
112*700637cbSDimitry Andric }
113*700637cbSDimitry Andric 
convertToStableData(IdHashNodeStableMapTy & IdNodeStableMap) const114*700637cbSDimitry Andric void OutlinedHashTreeRecord::convertToStableData(
115*700637cbSDimitry Andric     IdHashNodeStableMapTy &IdNodeStableMap) const {
116*700637cbSDimitry Andric   // Build NodeIdMap
117*700637cbSDimitry Andric   HashNodeIdMapTy NodeIdMap;
118*700637cbSDimitry Andric   HashTree->walkGraph(
119*700637cbSDimitry Andric       [&NodeIdMap](const HashNode *Current) {
120*700637cbSDimitry Andric         size_t Index = NodeIdMap.size();
121*700637cbSDimitry Andric         NodeIdMap[Current] = Index;
122*700637cbSDimitry Andric         assert((Index + 1 == NodeIdMap.size()) &&
123*700637cbSDimitry Andric                "Duplicate key in NodeIdMap: 'Current' should be unique.");
124*700637cbSDimitry Andric       },
125*700637cbSDimitry Andric       /*EdgeCallbackFn=*/nullptr, /*SortedWork=*/true);
126*700637cbSDimitry Andric 
127*700637cbSDimitry Andric   // Convert NodeIdMap to NodeStableMap
128*700637cbSDimitry Andric   for (auto &P : NodeIdMap) {
129*700637cbSDimitry Andric     auto *Node = P.first;
130*700637cbSDimitry Andric     auto Id = P.second;
131*700637cbSDimitry Andric     HashNodeStable NodeStable;
132*700637cbSDimitry Andric     NodeStable.Hash = Node->Hash;
133*700637cbSDimitry Andric     NodeStable.Terminals = Node->Terminals.value_or(0);
134*700637cbSDimitry Andric     for (auto &P : Node->Successors)
135*700637cbSDimitry Andric       NodeStable.SuccessorIds.push_back(NodeIdMap[P.second.get()]);
136*700637cbSDimitry Andric     IdNodeStableMap[Id] = NodeStable;
137*700637cbSDimitry Andric   }
138*700637cbSDimitry Andric 
139*700637cbSDimitry Andric   // Sort the Successors so that they come out in the same order as in the map.
140*700637cbSDimitry Andric   for (auto &P : IdNodeStableMap)
141*700637cbSDimitry Andric     llvm::sort(P.second.SuccessorIds);
142*700637cbSDimitry Andric }
143*700637cbSDimitry Andric 
convertFromStableData(const IdHashNodeStableMapTy & IdNodeStableMap)144*700637cbSDimitry Andric void OutlinedHashTreeRecord::convertFromStableData(
145*700637cbSDimitry Andric     const IdHashNodeStableMapTy &IdNodeStableMap) {
146*700637cbSDimitry Andric   IdHashNodeMapTy IdNodeMap;
147*700637cbSDimitry Andric   // Initialize the root node at 0.
148*700637cbSDimitry Andric   IdNodeMap[0] = HashTree->getRoot();
149*700637cbSDimitry Andric   assert(IdNodeMap[0]->Successors.empty());
150*700637cbSDimitry Andric 
151*700637cbSDimitry Andric   for (auto &P : IdNodeStableMap) {
152*700637cbSDimitry Andric     auto Id = P.first;
153*700637cbSDimitry Andric     const HashNodeStable &NodeStable = P.second;
154*700637cbSDimitry Andric     assert(IdNodeMap.count(Id));
155*700637cbSDimitry Andric     HashNode *Curr = IdNodeMap[Id];
156*700637cbSDimitry Andric     Curr->Hash = NodeStable.Hash;
157*700637cbSDimitry Andric     if (NodeStable.Terminals)
158*700637cbSDimitry Andric       Curr->Terminals = NodeStable.Terminals;
159*700637cbSDimitry Andric     auto &Successors = Curr->Successors;
160*700637cbSDimitry Andric     assert(Successors.empty());
161*700637cbSDimitry Andric     for (auto SuccessorId : NodeStable.SuccessorIds) {
162*700637cbSDimitry Andric       auto Sucessor = std::make_unique<HashNode>();
163*700637cbSDimitry Andric       IdNodeMap[SuccessorId] = Sucessor.get();
164*700637cbSDimitry Andric       auto Hash = IdNodeStableMap.at(SuccessorId).Hash;
165*700637cbSDimitry Andric       Successors[Hash] = std::move(Sucessor);
166*700637cbSDimitry Andric     }
167*700637cbSDimitry Andric   }
168*700637cbSDimitry Andric }
169