1 //===- llvm/ADT/GraphTraits.h - Graph traits template -----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the little GraphTraits<X> template class that should be
10 // specialized by classes that want to be iteratable by generic graph iterators.
11 //
12 // This file also defines the marker class Inverse that is used to iterate over
13 // graphs in a graph defined, inverse ordering...
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_ADT_GRAPHTRAITS_H
18 #define LLVM_ADT_GRAPHTRAITS_H
19 
20 #include "llvm/ADT/iterator_range.h"
21 
22 namespace llvm {
23 
24 // GraphTraits - This class should be specialized by different graph types...
25 // which is why the default version is empty.
26 //
27 // This template evolved from supporting `BasicBlock` to also later supporting
28 // more complex types (e.g. CFG and DomTree).
29 //
30 // GraphTraits can be used to create a view over a graph interpreting it
31 // differently without requiring a copy of the original graph. This could
32 // be achieved by carrying more data in NodeRef. See LoopBodyTraits for one
33 // example.
34 template<class GraphType>
35 struct GraphTraits {
36   // Elements to provide:
37 
38   // typedef NodeRef           - Type of Node token in the graph, which should
39   //                             be cheap to copy.
40   // typedef ChildIteratorType - Type used to iterate over children in graph,
41   //                             dereference to a NodeRef.
42 
43   // static NodeRef getEntryNode(const GraphType &)
44   //    Return the entry node of the graph
45 
46   // static ChildIteratorType child_begin(NodeRef)
47   // static ChildIteratorType child_end  (NodeRef)
48   //    Return iterators that point to the beginning and ending of the child
49   //    node list for the specified node.
50 
51   // typedef  ...iterator nodes_iterator; - dereference to a NodeRef
52   // static nodes_iterator nodes_begin(GraphType *G)
53   // static nodes_iterator nodes_end  (GraphType *G)
54   //    nodes_iterator/begin/end - Allow iteration over all nodes in the graph
55 
56   // typedef EdgeRef           - Type of Edge token in the graph, which should
57   //                             be cheap to copy.
58   // typedef ChildEdgeIteratorType - Type used to iterate over children edges in
59   //                             graph, dereference to a EdgeRef.
60 
61   // static ChildEdgeIteratorType child_edge_begin(NodeRef)
62   // static ChildEdgeIteratorType child_edge_end(NodeRef)
63   //     Return iterators that point to the beginning and ending of the
64   //     edge list for the given callgraph node.
65   //
66   // static NodeRef edge_dest(EdgeRef)
67   //     Return the destination node of an edge.
68 
69   // static unsigned       size       (GraphType *G)
70   //    Return total number of nodes in the graph
71 
72   // If anyone tries to use this class without having an appropriate
73   // specialization, make an error.  If you get this error, it's because you
74   // need to include the appropriate specialization of GraphTraits<> for your
75   // graph, or you need to define it for a new graph type. Either that or
76   // your argument to XXX_begin(...) is unknown or needs to have the proper .h
77   // file #include'd.
78   using NodeRef = typename GraphType::UnknownGraphTypeError;
79 };
80 
81 // Inverse - This class is used as a little marker class to tell the graph
82 // iterator to iterate over the graph in a graph defined "Inverse" ordering.
83 // Not all graphs define an inverse ordering, and if they do, it depends on
84 // the graph exactly what that is.  Here's an example of usage with the
85 // df_iterator:
86 //
87 // idf_iterator<Method*> I = idf_begin(M), E = idf_end(M);
88 // for (; I != E; ++I) { ... }
89 //
90 // Which is equivalent to:
91 // df_iterator<Inverse<Method*>> I = idf_begin(M), E = idf_end(M);
92 // for (; I != E; ++I) { ... }
93 //
94 template <class GraphType>
95 struct Inverse {
96   const GraphType &Graph;
97 
98   inline Inverse(const GraphType &G) : Graph(G) {}
99 };
100 
101 // Provide a partial specialization of GraphTraits so that the inverse of an
102 // inverse falls back to the original graph.
103 template <class T> struct GraphTraits<Inverse<Inverse<T>>> : GraphTraits<T> {};
104 
105 // Provide iterator ranges for the graph traits nodes and children
106 template <class GraphType>
107 iterator_range<typename GraphTraits<GraphType>::nodes_iterator>
108 nodes(const GraphType &G) {
109   return make_range(GraphTraits<GraphType>::nodes_begin(G),
110                     GraphTraits<GraphType>::nodes_end(G));
111 }
112 template <class GraphType>
113 iterator_range<typename GraphTraits<Inverse<GraphType>>::nodes_iterator>
114 inverse_nodes(const GraphType &G) {
115   return make_range(GraphTraits<Inverse<GraphType>>::nodes_begin(G),
116                     GraphTraits<Inverse<GraphType>>::nodes_end(G));
117 }
118 
119 template <class GraphType>
120 iterator_range<typename GraphTraits<GraphType>::ChildIteratorType>
121 children(const typename GraphTraits<GraphType>::NodeRef &G) {
122   return make_range(GraphTraits<GraphType>::child_begin(G),
123                     GraphTraits<GraphType>::child_end(G));
124 }
125 
126 template <class GraphType>
127 iterator_range<typename GraphTraits<Inverse<GraphType>>::ChildIteratorType>
128 inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) {
129   return make_range(GraphTraits<Inverse<GraphType>>::child_begin(G),
130                     GraphTraits<Inverse<GraphType>>::child_end(G));
131 }
132 
133 template <class GraphType>
134 iterator_range<typename GraphTraits<GraphType>::ChildEdgeIteratorType>
135 children_edges(const typename GraphTraits<GraphType>::NodeRef &G) {
136   return make_range(GraphTraits<GraphType>::child_edge_begin(G),
137                     GraphTraits<GraphType>::child_edge_end(G));
138 }
139 
140 } // end namespace llvm
141 
142 #endif // LLVM_ADT_GRAPHTRAITS_H
143