//===-- 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, 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), 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);
    }
  }
}
