#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include "revng/ADT/GenericGraph.h" #include "revng/GraphLayout/Traits.h" namespace yield::layout { namespace detail { template struct InputNode : public DataType { Size Size = { 0, 0 }; using DataType::DataType; InputNode(const DataType &Another) : DataType(Another){}; InputNode(DataType &&Another) : DataType(Another){}; }; template struct OutputNode : public DataType { Point Center = { 0, 0 }; Size Size = { 0, 0 }; using DataType::DataType; OutputNode(const DataType &Another) : DataType(Another){}; OutputNode(DataType &&Another) : DataType(Another){}; }; template struct InputEdge : public DataType { using DataType::DataType; InputEdge(const DataType &Another) : DataType(Another){}; InputEdge(DataType &&Another) : DataType(Another){}; }; template struct OutputEdge : public DataType { Path Path = {}; using DataType::DataType; OutputEdge(const DataType &Another) : DataType(Another){}; OutputEdge(DataType &&Another) : DataType(Another){}; }; } // namespace detail template using InputNode = MutableEdgeNode, detail::InputEdge, false>; template class InputGraph : public GenericGraph, 16, true> { using Base = GenericGraph, 16, true>; public: using Base::Base; }; template using OutputNode = MutableEdgeNode, detail::OutputEdge, false>; template class OutputGraph : public GenericGraph, 16, true> { using Base = GenericGraph, 16, true>; public: using Base::Base; }; template struct LayoutableGraphTraits *> { using GraphType = InputGraph *; static_assert(SpecializationOfGenericGraph>); using LLVMTrait = llvm::GraphTraits; static const Size &getNodeSize(typename LLVMTrait::NodeRef Node) { return Node.Size; } }; template struct LayoutableGraphTraits *> { using GraphType = OutputGraph *; static_assert(SpecializationOfGenericGraph>); using LLVMTrait = llvm::GraphTraits; static const Size &getNodeSize(typename LLVMTrait::NodeRef Node) { return Node->Size; } static void setNodePosition(typename LLVMTrait::NodeRef Node, Point &&Point) { Node->Center = std::move(Point); } static void setEdgePath(typename LLVMTrait::EdgeRef Edge, Path &&Path) { Edge.Label->Path = std::move(Path); } }; namespace detail { template OutputGraph convert(const InputGraph &Input) { OutputGraph Result; using InputNode = layout::InputNode; using OutputNode = layout::OutputNode; std::unordered_map Lookup; for (const InputNode *Node : Input.nodes()) { OutputNode Output(*Node); Output.Size = Node->Size; auto &&[It, Success] = Lookup.emplace(Node, Result.addNode(std::move(Output))); revng_assert(Success); } for (const InputNode *From : Input.nodes()) for (auto &&[To, EdgeLabel] : From->successor_edges()) Lookup.at(From)->addSuccessor(Lookup.at(To), EdgeDataType(std::move(*EdgeLabel))); return Result; } } // namespace detail } // namespace yield::layout