169 lines
5.6 KiB
C++
169 lines
5.6 KiB
C++
//===-- OutlinedHashTreeRecord.cpp ----------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This defines the OutlinedHashTreeRecord class. This class holds the outlined
|
|
// hash tree for both serialization and deserialization processes. It utilizes
|
|
// two data formats for serialization: raw binary data and YAML.
|
|
// These two formats can be used interchangeably.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CGData/OutlinedHashTreeRecord.h"
|
|
#include "llvm/ObjectYAML/YAML.h"
|
|
#include "llvm/Support/Endian.h"
|
|
#include "llvm/Support/EndianStream.h"
|
|
|
|
#define DEBUG_TYPE "outlined-hash-tree"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::support;
|
|
|
|
namespace llvm {
|
|
namespace yaml {
|
|
|
|
template <> struct MappingTraits<HashNodeStable> {
|
|
static void mapping(IO &io, HashNodeStable &res) {
|
|
io.mapRequired("Hash", res.Hash);
|
|
io.mapRequired("Terminals", res.Terminals);
|
|
io.mapRequired("SuccessorIds", res.SuccessorIds);
|
|
}
|
|
};
|
|
|
|
template <> struct CustomMappingTraits<IdHashNodeStableMapTy> {
|
|
static void inputOne(IO &io, StringRef Key, IdHashNodeStableMapTy &V) {
|
|
HashNodeStable NodeStable;
|
|
io.mapRequired(Key.str().c_str(), NodeStable);
|
|
unsigned Id;
|
|
if (Key.getAsInteger(0, Id)) {
|
|
io.setError("Id not an integer");
|
|
return;
|
|
}
|
|
V.insert({Id, NodeStable});
|
|
}
|
|
|
|
static void output(IO &io, IdHashNodeStableMapTy &V) {
|
|
for (auto Iter = V.begin(); Iter != V.end(); ++Iter)
|
|
io.mapRequired(utostr(Iter->first).c_str(), Iter->second);
|
|
}
|
|
};
|
|
|
|
} // namespace yaml
|
|
} // namespace llvm
|
|
|
|
void OutlinedHashTreeRecord::serialize(raw_ostream &OS) const {
|
|
IdHashNodeStableMapTy IdNodeStableMap;
|
|
convertToStableData(IdNodeStableMap);
|
|
support::endian::Writer Writer(OS, endianness::little);
|
|
Writer.write<uint32_t>(IdNodeStableMap.size());
|
|
|
|
for (const auto &[Id, NodeStable] : IdNodeStableMap) {
|
|
Writer.write<uint32_t>(Id);
|
|
Writer.write<uint64_t>(NodeStable.Hash);
|
|
Writer.write<uint32_t>(NodeStable.Terminals);
|
|
Writer.write<uint32_t>(NodeStable.SuccessorIds.size());
|
|
for (auto SuccessorId : NodeStable.SuccessorIds)
|
|
Writer.write<uint32_t>(SuccessorId);
|
|
}
|
|
}
|
|
|
|
void OutlinedHashTreeRecord::deserialize(const unsigned char *&Ptr) {
|
|
IdHashNodeStableMapTy IdNodeStableMap;
|
|
auto NumIdNodeStableMap =
|
|
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
|
|
|
|
for (unsigned I = 0; I < NumIdNodeStableMap; ++I) {
|
|
auto Id = endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
|
|
HashNodeStable NodeStable;
|
|
NodeStable.Hash =
|
|
endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);
|
|
NodeStable.Terminals =
|
|
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
|
|
auto NumSuccessorIds =
|
|
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
|
|
for (unsigned J = 0; J < NumSuccessorIds; ++J)
|
|
NodeStable.SuccessorIds.push_back(
|
|
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr));
|
|
|
|
IdNodeStableMap[Id] = std::move(NodeStable);
|
|
}
|
|
|
|
convertFromStableData(IdNodeStableMap);
|
|
}
|
|
|
|
void OutlinedHashTreeRecord::serializeYAML(yaml::Output &YOS) const {
|
|
IdHashNodeStableMapTy IdNodeStableMap;
|
|
convertToStableData(IdNodeStableMap);
|
|
|
|
YOS << IdNodeStableMap;
|
|
}
|
|
|
|
void OutlinedHashTreeRecord::deserializeYAML(yaml::Input &YIS) {
|
|
IdHashNodeStableMapTy IdNodeStableMap;
|
|
|
|
YIS >> IdNodeStableMap;
|
|
YIS.nextDocument();
|
|
|
|
convertFromStableData(IdNodeStableMap);
|
|
}
|
|
|
|
void OutlinedHashTreeRecord::convertToStableData(
|
|
IdHashNodeStableMapTy &IdNodeStableMap) const {
|
|
// Build NodeIdMap
|
|
HashNodeIdMapTy NodeIdMap;
|
|
HashTree->walkGraph(
|
|
[&NodeIdMap](const HashNode *Current) {
|
|
size_t Index = NodeIdMap.size();
|
|
NodeIdMap[Current] = Index;
|
|
assert((Index + 1 == NodeIdMap.size()) &&
|
|
"Duplicate key in NodeIdMap: 'Current' should be unique.");
|
|
},
|
|
/*EdgeCallbackFn=*/nullptr, /*SortedWork=*/true);
|
|
|
|
// Convert NodeIdMap to NodeStableMap
|
|
for (auto &P : NodeIdMap) {
|
|
auto *Node = P.first;
|
|
auto Id = P.second;
|
|
HashNodeStable NodeStable;
|
|
NodeStable.Hash = Node->Hash;
|
|
NodeStable.Terminals = Node->Terminals.value_or(0);
|
|
for (auto &P : Node->Successors)
|
|
NodeStable.SuccessorIds.push_back(NodeIdMap[P.second.get()]);
|
|
IdNodeStableMap[Id] = NodeStable;
|
|
}
|
|
|
|
// Sort the Successors so that they come out in the same order as in the map.
|
|
for (auto &P : IdNodeStableMap)
|
|
llvm::sort(P.second.SuccessorIds);
|
|
}
|
|
|
|
void OutlinedHashTreeRecord::convertFromStableData(
|
|
const IdHashNodeStableMapTy &IdNodeStableMap) {
|
|
IdHashNodeMapTy IdNodeMap;
|
|
// Initialize the root node at 0.
|
|
IdNodeMap[0] = HashTree->getRoot();
|
|
assert(IdNodeMap[0]->Successors.empty());
|
|
|
|
for (auto &P : IdNodeStableMap) {
|
|
auto Id = P.first;
|
|
const HashNodeStable &NodeStable = P.second;
|
|
assert(IdNodeMap.count(Id));
|
|
HashNode *Curr = IdNodeMap[Id];
|
|
Curr->Hash = NodeStable.Hash;
|
|
if (NodeStable.Terminals)
|
|
Curr->Terminals = NodeStable.Terminals;
|
|
auto &Successors = Curr->Successors;
|
|
assert(Successors.empty());
|
|
for (auto SuccessorId : NodeStable.SuccessorIds) {
|
|
auto Sucessor = std::make_unique<HashNode>();
|
|
IdNodeMap[SuccessorId] = Sucessor.get();
|
|
auto Hash = IdNodeStableMap.at(SuccessorId).Hash;
|
|
Successors[Hash] = std::move(Sucessor);
|
|
}
|
|
}
|
|
}
|