blob: 64da198b33679e88e58fb639c371a7518b4ae948 [file] [log] [blame]
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +00001//===-- sanitizer_bvgraph.h -------------------------------------*- 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// This file is a part of Sanitizer runtime.
11// BVGraph -- a directed graph.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef SANITIZER_BVGRAPH_H
16#define SANITIZER_BVGRAPH_H
17
18#include "sanitizer_common.h"
19#include "sanitizer_bitvector.h"
20
21namespace __sanitizer {
22
23// Directed graph of fixed size implemented as an array of bit vectors.
Kostya Serebryanye233d862014-02-14 12:08:23 +000024// Not thread-safe, all accesses should be protected by an external lock.
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000025template<class BV>
26class BVGraph {
27 public:
28 enum SizeEnum { kSize = BV::kSize };
29 uptr size() const { return kSize; }
30 // No CTOR.
31 void clear() {
32 for (uptr i = 0; i < size(); i++)
33 v[i].clear();
34 }
35
36 // Returns true if a new edge was added.
37 bool addEdge(uptr from, uptr to) {
Kostya Serebryany07526fb2014-02-13 12:39:21 +000038 check(from, to);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000039 return v[from].setBit(to);
40 }
41
42 bool hasEdge(uptr from, uptr to) const {
Kostya Serebryany07526fb2014-02-13 12:39:21 +000043 check(from, to);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000044 return v[from].getBit(to);
45 }
46
47 // Returns true if there is a path from the node 'from'
Kostya Serebryany5e52d482014-02-13 07:44:51 +000048 // to any of the nodes in 'targets'.
49 bool isReachable(uptr from, const BV &targets) {
Kostya Serebryanye233d862014-02-14 12:08:23 +000050 BV &to_visit = t1,
51 &visited = t2;
Kostya Serebryanyf6cb35a2014-02-13 09:52:15 +000052 to_visit.copyFrom(v[from]);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000053 visited.clear();
54 visited.setBit(from);
55 while (!to_visit.empty()) {
56 uptr idx = to_visit.getAndClearFirstOne();
57 if (visited.setBit(idx))
58 to_visit.setUnion(v[idx]);
59 }
Kostya Serebryany5e52d482014-02-13 07:44:51 +000060 return targets.intersectsWith(visited);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000061 }
62
Kostya Serebryanyf6cb35a2014-02-13 09:52:15 +000063 // Finds a path from 'from' to one of the nodes in 'target',
64 // stores up to 'path_size' items of the path into 'path',
65 // returns the path length, or 0 if there is no path of size 'path_size'.
66 uptr findPath(uptr from, const BV &targets, uptr *path, uptr path_size) {
67 if (path_size == 0)
68 return 0;
69 path[0] = from;
70 if (targets.getBit(from))
71 return 1;
Kostya Serebryanye233d862014-02-14 12:08:23 +000072 // The function is recursive, so we don't want to create BV on stack.
73 // Instead of a getAndClearFirstOne loop we use the slower iterator.
74 for (typename BV::Iterator it(v[from]); it.hasNext(); ) {
75 uptr idx = it.next();
Kostya Serebryanyf6cb35a2014-02-13 09:52:15 +000076 if (uptr res = findPath(idx, targets, path + 1, path_size - 1))
77 return res + 1;
78 }
79 return 0;
80 }
81
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000082 private:
Kostya Serebryany67d41972014-02-13 15:45:20 +000083 void check(uptr idx1, uptr idx2) const {
84 CHECK_LT(idx1, size());
85 CHECK_LT(idx2, size());
86 }
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000087 BV v[kSize];
Kostya Serebryanye233d862014-02-14 12:08:23 +000088 // Keep temporary vectors here since we can not create large objects on stack.
89 BV t1, t2;
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000090};
91
92} // namespace __sanitizer
93
94#endif // SANITIZER_BVGRAPH_H