Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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