Files
2024-09-27 12:07:17 +02:00

180 lines
5.5 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <compare>
#include <map>
#include <unordered_map>
#include <vector>
#include "revng/GraphLayout/SugiyamaStyle/Compute.h"
using RankingStrategy = yield::layout::sugiyama::RankingStrategy;
using Configuration = yield::layout::sugiyama::Configuration;
using Point = yield::layout::Point;
using Size = yield::layout::Size;
using Index = size_t;
using Rank = size_t;
using RankDelta = std::ptrdiff_t;
using InternalGraph = yield::layout::sugiyama::InternalGraph;
using InternalNode = InternalGraph::Node;
using InternalEdge = InternalNode::Edge;
/// A wrapper around an `InternalNode` pointer used for comparison overloading.
class NodeView {
public:
NodeView(InternalNode *Pointer = nullptr) : Pointer(Pointer) {}
operator InternalNode *() const {
revng_assert(Pointer != nullptr);
return Pointer;
}
InternalNode &operator*() const {
revng_assert(Pointer != nullptr);
return *Pointer;
}
InternalNode *operator->() const {
revng_assert(Pointer != nullptr);
return Pointer;
}
auto operator<=>(const NodeView &Another) const {
revng_assert(Pointer != nullptr);
revng_assert(Another.Pointer != nullptr);
return Pointer->index() <=> Another.Pointer->index();
}
private:
InternalNode *Pointer = nullptr;
};
namespace std {
template<>
struct hash<::NodeView> {
auto operator()(const ::NodeView &View) const {
return std::hash<InternalNode *>()(&*View);
}
};
} // namespace std
/// A view onto an edge as a extension of a known node.
/// This is useful as a `second` value for a map where the `first` one
/// is the `From` node.
struct EdgeDestinationView {
NodeView To;
size_t EdgeIndex;
EdgeDestinationView(NodeView To, const InternalEdge &Label) :
To(To), EdgeIndex(Label.index()) {}
auto operator<=>(const EdgeDestinationView &) const = default;
};
/// A generic view onto an edge. It's the same as the `EdgeDestinationView`
/// but stores the views onto both of the nodes.
struct EdgeView : EdgeDestinationView {
public:
NodeView From;
EdgeView(NodeView From, NodeView To, const InternalEdge &Label) :
EdgeDestinationView(To, Label), From(From) {}
auto operator<=>(const EdgeView &) const = default;
InternalEdge &label() {
auto Lambda = [this](auto Edge) {
return Edge.Neighbor == To && Edge.Label->index() == EdgeIndex;
};
revng_assert(llvm::count_if(From->successor_edges(), Lambda) == 1);
auto Iterator = llvm::find_if(From->successor_edges(), Lambda);
revng_assert(Iterator != From->successor_edges().end());
revng_assert(Iterator->Label != nullptr);
return *Iterator->Label;
}
const InternalEdge &label() const {
auto Lambda = [this](auto Edge) {
return Edge.Neighbor == To && Edge.Label->index() == EdgeIndex;
};
revng_assert(llvm::count_if(From->successor_edges(), Lambda) == 1);
auto Iterator = llvm::find_if(From->successor_edges(), Lambda);
revng_assert(Iterator != From->successor_edges().end());
revng_assert(Iterator->Label != nullptr);
return *Iterator->Label;
}
};
/// An internal data structure used to pass node ranks around.
using RankContainer = std::unordered_map<NodeView, Rank>;
/// An internal data structure used to pass around information about
/// the layers specific nodes belong to.
using LayerContainer = std::vector<std::vector<NodeView>>;
/// An internal data structure used to pass around information about the way
/// graph is split onto segments.
using SegmentContainer = std::unordered_map<NodeView, NodeView>;
/// It's used to describe the position of a single node within the layered grid.
struct LogicalPosition {
Rank Layer; /// Rank of the layer the node is in.
Rank Index; /// An index within the layer
};
/// It's used to describe the complete layout by storing the exact
/// position of each node relative to all the others.
using LayoutContainer = std::unordered_map<NodeView, LogicalPosition>;
/// An internal data structure used to pass around information about the lanes
/// used to route edges.
struct LaneContainer {
/// Stores edges that require a horizontal section grouped by layer.
std::vector<std::map<EdgeView, Rank>> Horizontal;
/// Stores edges entering a node groped by the node they enter.
std::unordered_map<NodeView, std::map<EdgeDestinationView, Rank>> Entries;
/// Stores edges leaving a node grouped by the node they leave.
std::unordered_map<NodeView, std::map<EdgeDestinationView, Rank>> Exits;
};
/// An internal data structure used to represent a corner. It stores three
/// points: center of the corner and two ends.
struct Corner {
Point Start, Center, End;
};
/// An internal data structure used to represent a pair of nodes.
struct NodePair {
NodeView From, To;
auto operator<=>(const NodePair &) const = default;
};
/// An internal data structure used to pass around information about the routed
/// corners.
using CornerContainer = std::map<NodePair, Corner>;
/// An internal data structure used to represent all the necessary information
/// for an edge to be routed. This data is usable even after the internal graph
/// was destroyed.
struct RoutableEdge {
InternalEdge *Label = nullptr;
Point FromCenter, ToCenter;
Size FromSize, ToSize;
Rank LaneIndex, ExitCount, EntryCount;
float CenteredExitIndex, CenteredEntryIndex;
std::optional<Corner> Prerouted;
};
/// An internal data structure used to pass around an ordered list of routed
/// edges.
using OrderedEdgeContainer = std::vector<RoutableEdge>;