]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/XRay/Graph.h
Upgrade Unbound to 1.6.1. More to follow.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / XRay / Graph.h
1 //===-- Graph.h - XRay Graph Class ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // A Graph Datatype for XRay.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_XRAY_GRAPH_T_H
15 #define LLVM_XRAY_GRAPH_T_H
16
17 #include <initializer_list>
18 #include <stdint.h>
19 #include <type_traits>
20 #include <utility>
21
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/DenseSet.h"
24 #include "llvm/ADT/iterator.h"
25 #include "llvm/Support/Error.h"
26
27 namespace llvm {
28 namespace xray {
29
30 /// A Graph object represents a Directed Graph and is used in XRay to compute
31 /// and store function call graphs and associated statistical information.
32 ///
33 /// The graph takes in four template parameters, these are:
34 ///  - VertexAttribute, this is a structure which is stored for each vertex.
35 ///    Must be DefaultConstructible, CopyConstructible, CopyAssignable and
36 ///    Destructible.
37 ///  - EdgeAttribute, this is a structure which is stored for each edge
38 ///    Must be DefaultConstructible, CopyConstructible, CopyAssignable and
39 ///    Destructible.
40 ///  - EdgeAttribute, this is a structure which is stored for each variable
41 ///  - VI, this is a type over which DenseMapInfo is defined and is the type
42 ///    used look up strings, available as VertexIdentifier.
43 ///  - If the built in DenseMapInfo is not defined, provide a specialization
44 ///    class type here.
45 ///
46 /// Graph is CopyConstructible, CopyAssignable, MoveConstructible and
47 /// MoveAssignable but is not EqualityComparible or LessThanComparible.
48 ///
49 /// Usage Example Graph with weighted edges and vertices:
50 ///   Graph<int, int, int> G;
51 ///
52 ///   G[1] = 0;
53 ///   G[2] = 2;
54 ///   G[{1,2}] = 1;
55 ///   G[{2,1}] = -1;
56 ///   for(const auto &v : G.vertices()){
57 ///     // Do something with the vertices in the graph;
58 ///   }
59 ///   for(const auto &e : G.edges()){
60 ///     // Do something with the edges in the graph;
61 ///   }
62 ///
63 /// Usage Example with StrRef keys.
64 ///   Graph<int, double, StrRef> StrG;
65 ///    char va[] = "Vertex A";
66 ///    char vaa[] = "Vertex A";
67 ///    char vb[] = "Vertex B"; // Vertices are referenced by String Refs.
68 ///    G[va] = 0;
69 ///    G[vb] = 1;
70 ///    G[{va, vb}] = 1.0;
71 ///    cout() << G[vaa] << " " << G[{vaa, vb}]; //prints "0 1.0".
72 ///
73 template <typename VertexAttribute, typename EdgeAttribute,
74           typename VI = int32_t>
75 class Graph {
76 public:
77   /// These objects are used to name edges and vertices in the graph.
78   typedef VI VertexIdentifier;
79   typedef std::pair<VI, VI> EdgeIdentifier;
80
81   /// This type is the value_type of all iterators which range over vertices,
82   /// Determined by the Vertices DenseMap
83   using VertexValueType =
84       detail::DenseMapPair<VertexIdentifier, VertexAttribute>;
85
86   /// This type is the value_type of all iterators which range over edges,
87   /// Determined by the Edges DenseMap.
88   using EdgeValueType = detail::DenseMapPair<EdgeIdentifier, EdgeAttribute>;
89
90   using size_type = std::size_t;
91
92 private:
93   /// The type used for storing the EdgeAttribute for each edge in the graph
94   using EdgeMapT = DenseMap<EdgeIdentifier, EdgeAttribute>;
95
96   /// The type used for storing the VertexAttribute for each vertex in
97   /// the graph.
98   using VertexMapT = DenseMap<VertexIdentifier, VertexAttribute>;
99
100   /// The type used for storing the edges entering a vertex. Indexed by
101   /// the VertexIdentifier of the start of the edge. Only used to determine
102   /// where the incoming edges are, the EdgeIdentifiers are stored in an
103   /// InnerEdgeMapT.
104   using NeighborSetT = DenseSet<VertexIdentifier>;
105
106   /// The type storing the InnerInvGraphT corresponding to each vertex in
107   /// the graph (When a vertex has an incoming edge incident to it)
108   using NeighborLookupT = DenseMap<VertexIdentifier, NeighborSetT>;
109
110 private:
111   /// Stores the map from the start and end vertex of an edge to it's
112   /// EdgeAttribute
113   EdgeMapT Edges;
114
115   /// Stores the map from VertexIdentifier to VertexAttribute
116   VertexMapT Vertices;
117
118   /// Allows fast lookup for the incoming edge set of any given vertex.
119   NeighborLookupT InNeighbors;
120
121   /// Allows fast lookup for the outgoing edge set of any given vertex.
122   NeighborLookupT OutNeighbors;
123
124   /// An Iterator adapter using an InnerInvGraphT::iterator as a base iterator,
125   /// and storing the VertexIdentifier the iterator range comes from. The
126   /// dereference operator is then performed using a pointer to the graph's edge
127   /// set.
128   template <bool IsConst, bool IsOut,
129             typename BaseIt = typename NeighborSetT::const_iterator,
130             typename T = typename std::conditional<IsConst, const EdgeValueType,
131                                                    EdgeValueType>::type>
132   class NeighborEdgeIteratorT
133       : public iterator_adaptor_base<
134             NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
135             typename std::iterator_traits<BaseIt>::iterator_category, T> {
136     using InternalEdgeMapT =
137         typename std::conditional<IsConst, const EdgeMapT, EdgeMapT>::type;
138
139     friend class NeighborEdgeIteratorT<false, IsOut, BaseIt, EdgeValueType>;
140     friend class NeighborEdgeIteratorT<true, IsOut, BaseIt,
141                                        const EdgeValueType>;
142
143     InternalEdgeMapT *MP;
144     VertexIdentifier SI;
145
146   public:
147     template <bool IsConstDest,
148               typename = typename std::enable_if<IsConstDest && !IsConst>::type>
149     operator NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
150                                    const EdgeValueType>() const {
151       return NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
152                                    const EdgeValueType>(this->I, MP, SI);
153     }
154
155     NeighborEdgeIteratorT() = default;
156     NeighborEdgeIteratorT(BaseIt _I, InternalEdgeMapT *_MP,
157                           VertexIdentifier _SI)
158         : iterator_adaptor_base<
159               NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
160               typename std::iterator_traits<BaseIt>::iterator_category, T>(_I),
161           MP(_MP), SI(_SI) {}
162
163     T &operator*() const {
164       if (!IsOut)
165         return *(MP->find({*(this->I), SI}));
166       else
167         return *(MP->find({SI, *(this->I)}));
168     }
169   };
170
171 public:
172   /// A const iterator type for iterating through the set of edges entering a
173   /// vertex.
174   ///
175   /// Has a const EdgeValueType as its value_type
176   using ConstInEdgeIterator = NeighborEdgeIteratorT<true, false>;
177
178   /// An iterator type for iterating through the set of edges leaving a vertex.
179   ///
180   /// Has an EdgeValueType as its value_type
181   using InEdgeIterator = NeighborEdgeIteratorT<false, false>;
182
183   /// A const iterator type for iterating through the set of edges entering a
184   /// vertex.
185   ///
186   /// Has a const EdgeValueType as its value_type
187   using ConstOutEdgeIterator = NeighborEdgeIteratorT<true, true>;
188
189   /// An iterator type for iterating through the set of edges leaving a vertex.
190   ///
191   /// Has an EdgeValueType as its value_type
192   using OutEdgeIterator = NeighborEdgeIteratorT<false, true>;
193
194   /// A class for ranging over the incoming edges incident to a vertex.
195   ///
196   /// Like all views in this class it provides methods to get the beginning and
197   /// past the range iterators for the range, as well as methods to determine
198   /// the number of elements in the range and whether the range is empty.
199   template <bool isConst, bool isOut> class InOutEdgeView {
200   public:
201     using iterator = NeighborEdgeIteratorT<isConst, isOut>;
202     using const_iterator = NeighborEdgeIteratorT<true, isOut>;
203     using GraphT = typename std::conditional<isConst, const Graph, Graph>::type;
204     using InternalEdgeMapT =
205         typename std::conditional<isConst, const EdgeMapT, EdgeMapT>::type;
206
207   private:
208     InternalEdgeMapT &M;
209     const VertexIdentifier A;
210     const NeighborLookupT &NL;
211
212   public:
213     iterator begin() {
214       auto It = NL.find(A);
215       if (It == NL.end())
216         return iterator();
217       return iterator(It->second.begin(), &M, A);
218     }
219
220     const_iterator cbegin() const {
221       auto It = NL.find(A);
222       if (It == NL.end())
223         return const_iterator();
224       return const_iterator(It->second.begin(), &M, A);
225     }
226
227     const_iterator begin() const { return cbegin(); }
228
229     iterator end() {
230       auto It = NL.find(A);
231       if (It == NL.end())
232         return iterator();
233       return iterator(It->second.end(), &M, A);
234     }
235     const_iterator cend() const {
236       auto It = NL.find(A);
237       if (It == NL.end())
238         return const_iterator();
239       return const_iterator(It->second.end(), &M, A);
240     }
241
242     const_iterator end() const { return cend(); }
243
244     size_type size() const {
245       auto I = NL.find(A);
246       if (I == NL.end())
247         return 0;
248       else
249         return I->second.size();
250     }
251
252     bool empty() const { return NL.count(A) == 0; };
253
254     InOutEdgeView(GraphT &G, VertexIdentifier A)
255         : M(G.Edges), A(A), NL(isOut ? G.OutNeighbors : G.InNeighbors) {}
256   };
257
258   /// A const iterator type for iterating through the whole vertex set of the
259   /// graph.
260   ///
261   /// Has a const VertexValueType as its value_type
262   using ConstVertexIterator = typename VertexMapT::const_iterator;
263
264   /// An iterator type for iterating through the whole vertex set of the graph.
265   ///
266   /// Has a VertexValueType as its value_type
267   using VertexIterator = typename VertexMapT::iterator;
268
269   /// A class for ranging over the vertices in the graph.
270   ///
271   /// Like all views in this class it provides methods to get the beginning and
272   /// past the range iterators for the range, as well as methods to determine
273   /// the number of elements in the range and whether the range is empty.
274   template <bool isConst> class VertexView {
275   public:
276     using iterator = typename std::conditional<isConst, ConstVertexIterator,
277                                                VertexIterator>::type;
278     using const_iterator = ConstVertexIterator;
279     using GraphT = typename std::conditional<isConst, const Graph, Graph>::type;
280
281   private:
282     GraphT &G;
283
284   public:
285     iterator begin() { return G.Vertices.begin(); }
286     iterator end() { return G.Vertices.end(); }
287     const_iterator cbegin() const { return G.Vertices.cbegin(); }
288     const_iterator cend() const { return G.Vertices.cend(); }
289     const_iterator begin() const { return G.Vertices.begin(); }
290     const_iterator end() const { return G.Vertices.end(); }
291     size_type size() const { return G.Vertices.size(); }
292     bool empty() const { return G.Vertices.empty(); }
293     VertexView(GraphT &_G) : G(_G) {}
294   };
295
296   /// A const iterator for iterating through the entire edge set of the graph.
297   ///
298   /// Has a const EdgeValueType as its value_type
299   using ConstEdgeIterator = typename EdgeMapT::const_iterator;
300
301   /// An iterator for iterating through the entire edge set of the graph.
302   ///
303   /// Has an EdgeValueType as its value_type
304   using EdgeIterator = typename EdgeMapT::iterator;
305
306   /// A class for ranging over all the edges in the graph.
307   ///
308   /// Like all views in this class it provides methods to get the beginning and
309   /// past the range iterators for the range, as well as methods to determine
310   /// the number of elements in the range and whether the range is empty.
311   template <bool isConst> class EdgeView {
312   public:
313     using iterator = typename std::conditional<isConst, ConstEdgeIterator,
314                                                EdgeIterator>::type;
315     using const_iterator = ConstEdgeIterator;
316     using GraphT = typename std::conditional<isConst, const Graph, Graph>::type;
317
318   private:
319     GraphT &G;
320
321   public:
322     iterator begin() { return G.Edges.begin(); }
323     iterator end() { return G.Edges.end(); }
324     const_iterator cbegin() const { return G.Edges.cbegin(); }
325     const_iterator cend() const { return G.Edges.cend(); }
326     const_iterator begin() const { return G.Edges.begin(); }
327     const_iterator end() const { return G.Edges.end(); }
328     size_type size() const { return G.Edges.size(); }
329     bool empty() const { return G.Edges.empty(); }
330     EdgeView(GraphT &_G) : G(_G) {}
331   };
332
333 public:
334   // TODO: implement constructor to enable Graph Initialisation.\
335   // Something like:
336   //   Graph<int, int, int> G(
337   //   {1, 2, 3, 4, 5},
338   //   {{1, 2}, {2, 3}, {3, 4}});
339
340   /// Empty the Graph
341   void clear() {
342     Edges.clear();
343     Vertices.clear();
344     InNeighbors.clear();
345     OutNeighbors.clear();
346   }
347
348   /// Returns a view object allowing iteration over the vertices of the graph.
349   /// also allows access to the size of the vertex set.
350   VertexView<false> vertices() { return VertexView<false>(*this); }
351
352   VertexView<true> vertices() const { return VertexView<true>(*this); }
353
354   /// Returns a view object allowing iteration over the edges of the graph.
355   /// also allows access to the size of the edge set.
356   EdgeView<false> edges() { return EdgeView<false>(*this); }
357
358   EdgeView<true> edges() const { return EdgeView<true>(*this); }
359
360   /// Returns a view object allowing iteration over the edges which start at
361   /// a vertex I.
362   InOutEdgeView<false, true> outEdges(const VertexIdentifier I) {
363     return InOutEdgeView<false, true>(*this, I);
364   }
365
366   InOutEdgeView<true, true> outEdges(const VertexIdentifier I) const {
367     return InOutEdgeView<true, true>(*this, I);
368   }
369
370   /// Returns a view object allowing iteration over the edges which point to
371   /// a vertex I.
372   InOutEdgeView<false, false> inEdges(const VertexIdentifier I) {
373     return InOutEdgeView<false, false>(*this, I);
374   }
375
376   InOutEdgeView<true, false> inEdges(const VertexIdentifier I) const {
377     return InOutEdgeView<true, false>(*this, I);
378   }
379
380   /// Looks up the vertex with identifier I, if it does not exist it default
381   /// constructs it.
382   VertexAttribute &operator[](const VertexIdentifier &I) {
383     return Vertices.FindAndConstruct(I).second;
384   }
385
386   /// Looks up the edge with identifier I, if it does not exist it default
387   /// constructs it, if it's endpoints do not exist it also default constructs
388   /// them.
389   EdgeAttribute &operator[](const EdgeIdentifier &I) {
390     auto &P = Edges.FindAndConstruct(I);
391     Vertices.FindAndConstruct(I.first);
392     Vertices.FindAndConstruct(I.second);
393     InNeighbors[I.second].insert(I.first);
394     OutNeighbors[I.first].insert(I.second);
395     return P.second;
396   }
397
398   /// Looks up a vertex with Identifier I, or an error if it does not exist.
399   Expected<VertexAttribute &> at(const VertexIdentifier &I) {
400     auto It = Vertices.find(I);
401     if (It == Vertices.end())
402       return make_error<StringError>(
403           "Vertex Identifier Does Not Exist",
404           std::make_error_code(std::errc::invalid_argument));
405     return It->second;
406   }
407
408   Expected<const VertexAttribute &> at(const VertexIdentifier &I) const {
409     auto It = Vertices.find(I);
410     if (It == Vertices.end())
411       return make_error<StringError>(
412           "Vertex Identifier Does Not Exist",
413           std::make_error_code(std::errc::invalid_argument));
414     return It->second;
415   }
416
417   /// Looks up an edge with Identifier I, or an error if it does not exist.
418   Expected<EdgeAttribute &> at(const EdgeIdentifier &I) {
419     auto It = Edges.find(I);
420     if (It == Edges.end())
421       return make_error<StringError>(
422           "Edge Identifier Does Not Exist",
423           std::make_error_code(std::errc::invalid_argument));
424     return It->second;
425   }
426
427   Expected<const EdgeAttribute &> at(const EdgeIdentifier &I) const {
428     auto It = Edges.find(I);
429     if (It == Edges.end())
430       return make_error<StringError>(
431           "Edge Identifier Does Not Exist",
432           std::make_error_code(std::errc::invalid_argument));
433     return It->second;
434   }
435
436   /// Looks for a vertex with identifier I, returns 1 if one exists, and
437   /// 0 otherwise
438   size_type count(const VertexIdentifier &I) const {
439     return Vertices.count(I);
440   }
441
442   /// Looks for an edge with Identifier I, returns 1 if one exists and 0
443   /// otherwise
444   size_type count(const EdgeIdentifier &I) const { return Edges.count(I); }
445
446   /// Inserts a vertex into the graph with Identifier Val.first, and
447   /// Attribute Val.second.
448   std::pair<VertexIterator, bool>
449   insert(const std::pair<VertexIdentifier, VertexAttribute> &Val) {
450     return Vertices.insert(Val);
451   }
452
453   std::pair<VertexIterator, bool>
454   insert(std::pair<VertexIdentifier, VertexAttribute> &&Val) {
455     return Vertices.insert(std::move(Val));
456   }
457
458   /// Inserts an edge into the graph with Identifier Val.first, and
459   /// Attribute Val.second. If the key is already in the map, it returns false
460   /// and doesn't update the value.
461   std::pair<EdgeIterator, bool>
462   insert(const std::pair<EdgeIdentifier, EdgeAttribute> &Val) {
463     const auto &p = Edges.insert(Val);
464     if (p.second) {
465       const auto &EI = Val.first;
466       Vertices.FindAndConstruct(EI.first);
467       Vertices.FindAndConstruct(EI.second);
468       InNeighbors[EI.second].insert(EI.first);
469       OutNeighbors[EI.first].insert(EI.second);
470     };
471
472     return p;
473   }
474
475   /// Inserts an edge into the graph with Identifier Val.first, and
476   /// Attribute Val.second. If the key is already in the map, it returns false
477   /// and doesn't update the value.
478   std::pair<EdgeIterator, bool>
479   insert(std::pair<EdgeIdentifier, EdgeAttribute> &&Val) {
480     auto EI = Val.first;
481     const auto &p = Edges.insert(std::move(Val));
482     if (p.second) {
483       Vertices.FindAndConstruct(EI.first);
484       Vertices.FindAndConstruct(EI.second);
485       InNeighbors[EI.second].insert(EI.first);
486       OutNeighbors[EI.first].insert(EI.second);
487     };
488
489     return p;
490   }
491 };
492 }
493 }
494 #endif