1// BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- 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 provides definition of dataflow types used by analyses such
11// as LiveVariables and UninitializedValues.  The underlying dataflow values
12// are implemented as bitvectors, but the definitions in this file include
13// the necessary boilerplate to use with our dataflow framework.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CLANG_STMTDECLBVDVAL_H
18#define LLVM_CLANG_STMTDECLBVDVAL_H
19
20#include "clang/Analysis/CFG.h"
21#include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion
22#include "llvm/ADT/BitVector.h"
23#include "llvm/ADT/DenseMap.h"
24
25namespace clang {
26
27  class Stmt;
28  class ASTContext;
29
30struct DeclBitVector_Types {
31
32  class Idx {
33    unsigned I;
34  public:
35    explicit Idx(unsigned i) : I(i) {}
36    Idx() : I(~0U) {}
37
38    bool isValid() const {
39      return I != ~0U;
40    }
41    operator unsigned() const {
42      assert (isValid());
43      return I;
44    }
45  };
46
47  //===--------------------------------------------------------------------===//
48  // AnalysisDataTy - Whole-function meta data.
49  //===--------------------------------------------------------------------===//
50
51  class AnalysisDataTy {
52  public:
53    typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy;
54    typedef DMapTy::const_iterator decl_iterator;
55
56  protected:
57    DMapTy DMap;
58    unsigned NDecls;
59
60  public:
61
62    AnalysisDataTy() : NDecls(0) {}
63    virtual ~AnalysisDataTy() {}
64
65    bool isTracked(const NamedDecl *SD) { return DMap.find(SD) != DMap.end(); }
66
67    Idx getIdx(const NamedDecl *SD) const {
68      DMapTy::const_iterator I = DMap.find(SD);
69      return I == DMap.end() ? Idx() : Idx(I->second);
70    }
71
72    unsigned getNumDecls() const { return NDecls; }
73
74    void Register(const NamedDecl *SD) {
75      if (!isTracked(SD)) DMap[SD] = NDecls++;
76    }
77
78    decl_iterator begin_decl() const { return DMap.begin(); }
79    decl_iterator end_decl() const { return DMap.end(); }
80  };
81
82  //===--------------------------------------------------------------------===//
83  // ValTy - Dataflow value.
84  //===--------------------------------------------------------------------===//
85
86  class ValTy {
87    llvm::BitVector DeclBV;
88  public:
89
90    void resetDeclValues(AnalysisDataTy& AD) {
91      DeclBV.resize(AD.getNumDecls());
92      DeclBV.reset();
93    }
94
95    void setDeclValues(AnalysisDataTy& AD) {
96      DeclBV.resize(AD.getNumDecls());
97      DeclBV.set();
98    }
99
100    void resetValues(AnalysisDataTy& AD) {
101      resetDeclValues(AD);
102    }
103
104    bool operator==(const ValTy& RHS) const {
105      assert (sizesEqual(RHS));
106      return DeclBV == RHS.DeclBV;
107    }
108
109    void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; }
110
111    llvm::BitVector::reference getBit(unsigned i) {
112      return DeclBV[i];
113    }
114
115    bool getBit(unsigned i) const {
116      return DeclBV[i];
117    }
118
119    llvm::BitVector::reference
120    operator()(const NamedDecl *ND, const AnalysisDataTy& AD) {
121      return getBit(AD.getIdx(ND));
122    }
123
124    bool operator()(const NamedDecl *ND, const AnalysisDataTy& AD) const {
125      return getBit(AD.getIdx(ND));
126    }
127
128    llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; }
129    const llvm::BitVector::reference getDeclBit(unsigned i) const {
130      return const_cast<llvm::BitVector&>(DeclBV)[i];
131    }
132
133    ValTy& operator|=(const ValTy& RHS) {
134      assert (sizesEqual(RHS));
135      DeclBV |= RHS.DeclBV;
136      return *this;
137    }
138
139    ValTy& operator&=(const ValTy& RHS) {
140      assert (sizesEqual(RHS));
141      DeclBV &= RHS.DeclBV;
142      return *this;
143    }
144
145    ValTy& OrDeclBits(const ValTy& RHS) {
146      return operator|=(RHS);
147    }
148
149    ValTy& AndDeclBits(const ValTy& RHS) {
150      return operator&=(RHS);
151    }
152
153    bool sizesEqual(const ValTy& RHS) const {
154      return DeclBV.size() == RHS.DeclBV.size();
155    }
156  };
157
158  //===--------------------------------------------------------------------===//
159  // Some useful merge operations.
160  //===--------------------------------------------------------------------===//
161
162  struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
163  struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
164};
165
166
167struct StmtDeclBitVector_Types {
168
169  //===--------------------------------------------------------------------===//
170  // AnalysisDataTy - Whole-function meta data.
171  //===--------------------------------------------------------------------===//
172
173  class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
174    ASTContext *ctx;
175    CFG* cfg;
176  public:
177    AnalysisDataTy() : ctx(0), cfg(0) {}
178    virtual ~AnalysisDataTy() {}
179
180    void setContext(ASTContext &c) { ctx = &c; }
181    ASTContext &getContext() {
182      assert(ctx && "ASTContext should not be NULL.");
183      return *ctx;
184    }
185
186    void setCFG(CFG& c) { cfg = &c; }
187    CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
188
189    bool isTracked(const Stmt *S) { return cfg->isBlkExpr(S); }
190    using DeclBitVector_Types::AnalysisDataTy::isTracked;
191
192    unsigned getIdx(const Stmt *S) const {
193      CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
194      assert(I && "Stmtession not tracked for bitvector.");
195      return I;
196    }
197    using DeclBitVector_Types::AnalysisDataTy::getIdx;
198
199    unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); }
200  };
201
202  //===--------------------------------------------------------------------===//
203  // ValTy - Dataflow value.
204  //===--------------------------------------------------------------------===//
205
206  class ValTy : public DeclBitVector_Types::ValTy {
207    llvm::BitVector BlkExprBV;
208    typedef DeclBitVector_Types::ValTy ParentTy;
209
210    static inline ParentTy& ParentRef(ValTy& X) {
211      return static_cast<ParentTy&>(X);
212    }
213
214    static inline const ParentTy& ParentRef(const ValTy& X) {
215      return static_cast<const ParentTy&>(X);
216    }
217
218  public:
219
220    void resetBlkExprValues(AnalysisDataTy& AD) {
221      BlkExprBV.resize(AD.getNumBlkExprs());
222      BlkExprBV.reset();
223    }
224
225    void setBlkExprValues(AnalysisDataTy& AD) {
226      BlkExprBV.resize(AD.getNumBlkExprs());
227      BlkExprBV.set();
228    }
229
230    void resetValues(AnalysisDataTy& AD) {
231      resetDeclValues(AD);
232      resetBlkExprValues(AD);
233    }
234
235    void setValues(AnalysisDataTy& AD) {
236      setDeclValues(AD);
237      setBlkExprValues(AD);
238    }
239
240    bool operator==(const ValTy& RHS) const {
241      return ParentRef(*this) == ParentRef(RHS)
242          && BlkExprBV == RHS.BlkExprBV;
243    }
244
245    void copyValues(const ValTy& RHS) {
246      ParentRef(*this).copyValues(ParentRef(RHS));
247      BlkExprBV = RHS.BlkExprBV;
248    }
249
250    llvm::BitVector::reference
251    operator()(const Stmt *S, const AnalysisDataTy& AD) {
252      return BlkExprBV[AD.getIdx(S)];
253    }
254    const llvm::BitVector::reference
255    operator()(const Stmt *S, const AnalysisDataTy& AD) const {
256      return const_cast<ValTy&>(*this)(S,AD);
257    }
258
259    using DeclBitVector_Types::ValTy::operator();
260
261
262    llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; }
263    const llvm::BitVector::reference getStmtBit(unsigned i) const {
264      return const_cast<llvm::BitVector&>(BlkExprBV)[i];
265    }
266
267    ValTy& OrBlkExprBits(const ValTy& RHS) {
268      BlkExprBV |= RHS.BlkExprBV;
269      return *this;
270    }
271
272    ValTy& AndBlkExprBits(const ValTy& RHS) {
273      BlkExprBV &= RHS.BlkExprBV;
274      return *this;
275    }
276
277    ValTy& operator|=(const ValTy& RHS) {
278      assert (sizesEqual(RHS));
279      ParentRef(*this) |= ParentRef(RHS);
280      BlkExprBV |= RHS.BlkExprBV;
281      return *this;
282    }
283
284    ValTy& operator&=(const ValTy& RHS) {
285      assert (sizesEqual(RHS));
286      ParentRef(*this) &= ParentRef(RHS);
287      BlkExprBV &= RHS.BlkExprBV;
288      return *this;
289    }
290
291    bool sizesEqual(const ValTy& RHS) const {
292      return ParentRef(*this).sizesEqual(ParentRef(RHS))
293          && BlkExprBV.size() == RHS.BlkExprBV.size();
294    }
295  };
296
297  //===--------------------------------------------------------------------===//
298  // Some useful merge operations.
299  //===--------------------------------------------------------------------===//
300
301  struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
302  struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
303
304};
305} // end namespace clang
306
307#endif
308