#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; constexpr Point(Coordinate X = 0, Coordinate Y = 0) : X(X), Y(Y) {} }; using Path = llvm::SmallVector; struct Size { Dimension W; Dimension H; constexpr Size(Dimension W = 0, Dimension H = 0) : W(W), H(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