blob: 4aed87ab5fb20f51b4d489de1b1f2dd2055f2e26 [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.
24template<class BV>
25class BVGraph {
26 public:
27 enum SizeEnum { kSize = BV::kSize };
28 uptr size() const { return kSize; }
29 // No CTOR.
30 void clear() {
31 for (uptr i = 0; i < size(); i++)
32 v[i].clear();
33 }
34
35 // Returns true if a new edge was added.
36 bool addEdge(uptr from, uptr to) {
Kostya Serebryany07526fb2014-02-13 12:39:21 +000037 check(from, to);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000038 return v[from].setBit(to);
39 }
40
41 bool hasEdge(uptr from, uptr to) const {
Kostya Serebryany07526fb2014-02-13 12:39:21 +000042 check(from, to);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000043 return v[from].getBit(to);
44 }
45
46 // Returns true if there is a path from the node 'from'
Kostya Serebryany5e52d482014-02-13 07:44:51 +000047 // to any of the nodes in 'targets'.
48 bool isReachable(uptr from, const BV &targets) {
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000049 BV to_visit, visited;
Kostya Serebryanyf6cb35a2014-02-13 09:52:15 +000050 to_visit.copyFrom(v[from]);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000051 visited.clear();
52 visited.setBit(from);
53 while (!to_visit.empty()) {
54 uptr idx = to_visit.getAndClearFirstOne();
55 if (visited.setBit(idx))
56 to_visit.setUnion(v[idx]);
57 }
Kostya Serebryany5e52d482014-02-13 07:44:51 +000058 return targets.intersectsWith(visited);
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000059 }
60
Kostya Serebryanyf6cb35a2014-02-13 09:52:15 +000061 // Finds a path from 'from' to one of the nodes in 'target',
62 // stores up to 'path_size' items of the path into 'path',
63 // returns the path length, or 0 if there is no path of size 'path_size'.
64 uptr findPath(uptr from, const BV &targets, uptr *path, uptr path_size) {
65 if (path_size == 0)
66 return 0;
67 path[0] = from;
68 if (targets.getBit(from))
69 return 1;
70 BV t;
71 t.copyFrom(v[from]);
72 while (!t.empty()) {
73 uptr idx = t.getAndClearFirstOne();
74 if (uptr res = findPath(idx, targets, path + 1, path_size - 1))
75 return res + 1;
76 }
77 return 0;
78 }
79
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000080 private:
Kostya Serebryany67d41972014-02-13 15:45:20 +000081 void check(uptr idx1, uptr idx2) const {
82 CHECK_LT(idx1, size());
83 CHECK_LT(idx2, size());
84 }
Kostya Serebryanybe1d22b2014-02-12 11:28:09 +000085 BV v[kSize];
86};
87
88} // namespace __sanitizer
89
90#endif // SANITIZER_BVGRAPH_H