mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
DotGraph: add EdgeRef and ChildEdgeIteratorType
Add EdgeRef and ChildEdgeIteratorType to GraphTraits<DotNode *> and to GraphTraits<const DotNode *>. This allows iterating on edges of DotGraphs, which will be useful for some testing on edge properties.
This commit is contained in:
committed by
Alessandro Di Federico
parent
a955cb9a50
commit
2bf702b74b
@@ -8,6 +8,7 @@
|
||||
// Standard includes
|
||||
#include <cstdlib>
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
// LLVM includes
|
||||
@@ -21,17 +22,24 @@ class DotNode {
|
||||
|
||||
// Define the container for the successors and some useful helpers.
|
||||
public:
|
||||
using child_container = llvm::SmallVector<DotNode *, 2>;
|
||||
using child_container = std::vector<DotNode *>;
|
||||
using child_iterator = typename child_container::iterator;
|
||||
using child_const_iterator = typename child_container::const_iterator;
|
||||
using child_range = llvm::iterator_range<child_iterator>;
|
||||
using child_const_range = llvm::iterator_range<child_const_iterator>;
|
||||
|
||||
using edge_container = std::vector<std::pair<DotNode *, DotNode *>>;
|
||||
using edge_iterator = typename edge_container::iterator;
|
||||
using edge_const_iterator = typename edge_container::const_iterator;
|
||||
using edge_range = llvm::iterator_range<edge_iterator>;
|
||||
using edge_const_range = llvm::iterator_range<edge_const_iterator>;
|
||||
|
||||
private:
|
||||
llvm::SmallString<8> Name;
|
||||
|
||||
// Actual container for the pointers to the successors nodes.
|
||||
child_container Successors;
|
||||
edge_container SuccEdges;
|
||||
|
||||
public:
|
||||
DotNode(llvm::StringRef Name) : Name(Name) {}
|
||||
@@ -45,6 +53,14 @@ public:
|
||||
return llvm::make_range(Successors.begin(), Successors.end());
|
||||
}
|
||||
|
||||
edge_range edge_successors() {
|
||||
return llvm::make_range(SuccEdges.begin(), SuccEdges.end());
|
||||
}
|
||||
|
||||
edge_const_range edge_successors() const {
|
||||
return llvm::make_range(SuccEdges.begin(), SuccEdges.end());
|
||||
}
|
||||
|
||||
llvm::StringRef getName() const { return Name; }
|
||||
|
||||
void addSuccessor(DotNode *Successor);
|
||||
@@ -53,25 +69,28 @@ public:
|
||||
class DotGraph {
|
||||
static DotNode *ptrFromRef(std::unique_ptr<DotNode> &P) { return P.get(); }
|
||||
|
||||
using PtrFromRefT = DotNode *(*) (std::unique_ptr<DotNode> &P);
|
||||
|
||||
static const DotNode *constPtrFromRef(const std::unique_ptr<DotNode> &P) {
|
||||
return P.get();
|
||||
}
|
||||
|
||||
using PtrFromRefT = DotNode *(*) (std::unique_ptr<DotNode> &P);
|
||||
using CPtrFromRefT = const DotNode *(*) (const std::unique_ptr<DotNode> &P);
|
||||
|
||||
public:
|
||||
using child_container = std::vector<std::unique_ptr<DotNode>>;
|
||||
using internal_iterator = typename child_container::iterator;
|
||||
using internal_const_iterator = typename child_container::const_iterator;
|
||||
using child_iterator = llvm::mapped_iterator<internal_iterator, PtrFromRefT>;
|
||||
using child_const_iterator = llvm::mapped_iterator<internal_const_iterator,
|
||||
CPtrFromRefT>;
|
||||
using child_range = llvm::iterator_range<child_iterator>;
|
||||
using child_const_range = llvm::iterator_range<child_const_iterator>;
|
||||
using node_container = std::vector<std::unique_ptr<DotNode>>;
|
||||
|
||||
using internal_iterator = typename node_container::iterator;
|
||||
using node_iterator = llvm::mapped_iterator<internal_iterator, PtrFromRefT>;
|
||||
using node_range = llvm::iterator_range<node_iterator>;
|
||||
|
||||
using internal_const_iterator = typename node_container::const_iterator;
|
||||
using node_const_iterator = llvm::mapped_iterator<internal_const_iterator,
|
||||
CPtrFromRefT>;
|
||||
using node_const_range = llvm::iterator_range<node_const_iterator>;
|
||||
|
||||
private:
|
||||
child_container Nodes;
|
||||
node_container Nodes;
|
||||
DotNode *EntryNode;
|
||||
|
||||
public:
|
||||
@@ -82,21 +101,21 @@ public:
|
||||
void
|
||||
parseDotFromFile(llvm::StringRef FileName, llvm::StringRef EntryName = "");
|
||||
|
||||
child_range nodes() { return llvm::make_range(begin(), end()); }
|
||||
node_range nodes() { return llvm::make_range(begin(), end()); }
|
||||
|
||||
child_const_range nodes() const { return llvm::make_range(begin(), end()); }
|
||||
node_const_range nodes() const { return llvm::make_range(begin(), end()); }
|
||||
|
||||
child_iterator begin() {
|
||||
node_iterator begin() {
|
||||
return llvm::map_iterator(Nodes.begin(), ptrFromRef);
|
||||
}
|
||||
|
||||
child_const_iterator begin() const {
|
||||
node_const_iterator begin() const {
|
||||
return llvm::map_iterator(Nodes.begin(), constPtrFromRef);
|
||||
}
|
||||
|
||||
child_iterator end() { return llvm::map_iterator(Nodes.end(), ptrFromRef); }
|
||||
node_iterator end() { return llvm::map_iterator(Nodes.end(), ptrFromRef); }
|
||||
|
||||
child_const_iterator end() const {
|
||||
node_const_iterator end() const {
|
||||
return llvm::map_iterator(Nodes.end(), constPtrFromRef);
|
||||
}
|
||||
|
||||
@@ -117,9 +136,24 @@ namespace llvm {
|
||||
|
||||
template<>
|
||||
struct GraphTraits<DotNode *> {
|
||||
public:
|
||||
using NodeRef = DotNode *;
|
||||
using ChildIteratorType = DotNode::child_iterator;
|
||||
|
||||
using EdgeRef = std::pair<NodeRef, NodeRef>;
|
||||
using ChildEdgeIteratorType = DotNode::edge_iterator;
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
using unref_t = std::remove_reference_t<T>;
|
||||
|
||||
using ChildT = unref_t<decltype(*std::declval<ChildIteratorType>())>;
|
||||
static_assert(std::is_same_v<NodeRef, ChildT>);
|
||||
|
||||
using ChildEdgeT = unref_t<decltype(*std::declval<ChildEdgeIteratorType>())>;
|
||||
static_assert(std::is_same_v<EdgeRef, ChildEdgeT>);
|
||||
|
||||
public:
|
||||
static inline ChildIteratorType child_begin(NodeRef N) {
|
||||
return N->successors().begin();
|
||||
}
|
||||
@@ -127,25 +161,78 @@ struct GraphTraits<DotNode *> {
|
||||
static inline ChildIteratorType child_end(NodeRef N) {
|
||||
return N->successors().end();
|
||||
}
|
||||
|
||||
public:
|
||||
static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
|
||||
return N->edge_successors().begin();
|
||||
}
|
||||
|
||||
static ChildEdgeIteratorType child_edge_end(NodeRef N) {
|
||||
return N->edge_successors().end();
|
||||
}
|
||||
|
||||
static NodeRef edge_dest(EdgeRef E) { return E.second; };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct GraphTraits<const DotNode *> {
|
||||
using NodeRef = const DotNode *;
|
||||
using ChildIteratorType = DotNode::child_const_iterator;
|
||||
using EdgeRef = std::pair<const NodeRef, const NodeRef>;
|
||||
|
||||
protected:
|
||||
static const DotNode *toConstNode(const NodeRef P) { return P; }
|
||||
using ConstNode = const DotNode *(*) (const NodeRef);
|
||||
|
||||
using const_node_it = llvm::mapped_iterator<DotNode::child_const_iterator,
|
||||
ConstNode>;
|
||||
|
||||
static std::pair<const NodeRef, const NodeRef> toConstEdge(const EdgeRef E) {
|
||||
return E;
|
||||
}
|
||||
using ConstEdge = std::pair<const NodeRef, const NodeRef> (*)(const EdgeRef);
|
||||
|
||||
using const_edge_it = llvm::mapped_iterator<DotNode::edge_const_iterator,
|
||||
ConstEdge>;
|
||||
|
||||
public:
|
||||
using ChildIteratorType = const_node_it;
|
||||
|
||||
using ChildEdgeIteratorType = const_edge_it;
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
using unref_t = std::remove_reference_t<T>;
|
||||
|
||||
using ChildT = unref_t<decltype(*std::declval<ChildIteratorType>())>;
|
||||
static_assert(std::is_same_v<NodeRef, ChildT>);
|
||||
|
||||
using ChildEdgeT = unref_t<decltype(*std::declval<ChildEdgeIteratorType>())>;
|
||||
static_assert(std::is_same_v<EdgeRef, ChildEdgeT>);
|
||||
|
||||
public:
|
||||
static inline ChildIteratorType child_begin(NodeRef N) {
|
||||
return N->successors().begin();
|
||||
return llvm::map_iterator(N->successors().begin(), toConstNode);
|
||||
}
|
||||
|
||||
static inline ChildIteratorType child_end(NodeRef N) {
|
||||
return N->successors().end();
|
||||
return llvm::map_iterator(N->successors().end(), toConstNode);
|
||||
}
|
||||
|
||||
public:
|
||||
static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
|
||||
return llvm::map_iterator(N->edge_successors().begin(), toConstEdge);
|
||||
}
|
||||
|
||||
static ChildEdgeIteratorType child_edge_end(NodeRef N) {
|
||||
return llvm::map_iterator(N->edge_successors().end(), toConstEdge);
|
||||
}
|
||||
|
||||
static NodeRef edge_dest(EdgeRef E) { return E.second; };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct GraphTraits<DotGraph *> : public GraphTraits<DotNode *> {
|
||||
using nodes_iterator = DotGraph::child_iterator;
|
||||
using nodes_iterator = DotGraph::node_iterator;
|
||||
|
||||
static NodeRef getEntryNode(DotGraph *G) { return G->getEntryNode(); }
|
||||
|
||||
@@ -158,7 +245,7 @@ struct GraphTraits<DotGraph *> : public GraphTraits<DotNode *> {
|
||||
|
||||
template<>
|
||||
struct GraphTraits<const DotGraph *> : public GraphTraits<const DotNode *> {
|
||||
using nodes_iterator = DotGraph::child_const_iterator;
|
||||
using nodes_iterator = DotGraph::node_const_iterator;
|
||||
|
||||
static NodeRef getEntryNode(const DotGraph *G) { return G->getEntryNode(); }
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ void DotNode::addSuccessor(DotNode *NewSuccessor) {
|
||||
revng_assert(not Found);
|
||||
|
||||
Successors.push_back(NewSuccessor);
|
||||
SuccEdges.push_back(std::make_pair(this, NewSuccessor));
|
||||
}
|
||||
|
||||
void DotGraph::parseDotImpl(std::ifstream &F, llvm::StringRef EntryName) {
|
||||
|
||||
Reference in New Issue
Block a user