Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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