#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallVector.h" #include "revng/ADT/Concepts.h" namespace yield::layout { using Coordinate = float; using Dimension = Coordinate; struct Point { Coordinate X; Coordinate Y; }; using Path = llvm::SmallVector; struct Size { Dimension W; Dimension H; }; template concept HasLLVMGraphTraits = requires(const GraphType &Graph) { { llvm::GraphTraits::getEntryNode(Graph) } -> std::convertible_to::NodeRef>; }; template struct LayoutableGraphTraits { using LLVMTrait = llvm::GraphTraits; // Elements to provide to qualify as an input graph: // // const Size &getNodeSize(typename LLVMTrait::NodeRef Node); // Elements to provide to qualify as an output graph: // // void setNodePosition(typename LLVMTrait::NodeRef Node, Point &&Point); // void setEdgePath(typename LLVMTrait::EdgeRef Edge, Path &&Path); // Note that a single graph is allowed to provide everything, so it can // qualify as both (for computing the layout in-place). }; namespace detail { template using NR = typename llvm::GraphTraits::NodeRef; template using ER = typename llvm::GraphTraits::EdgeRef; } // namespace detail template concept HasLayoutableInputGraphTraits = requires(detail::NR Node) { { LayoutableGraphTraits::getNodeSize(Node) } -> std::convertible_to; } && HasLLVMGraphTraits; template concept HasLayoutableOutputGraphTraits = requires(detail::NR Node, detail::ER Edge) { { LayoutableGraphTraits::setNodePosition(Node, Point()) }; { LayoutableGraphTraits::setEdgePath(Edge, Path()) }; } && HasLLVMGraphTraits; template concept HasLayoutableGraphTraits = HasLLVMGraphTraits && HasLayoutableInputGraphTraits && HasLayoutableOutputGraphTraits; } // namespace yield::layout