summaryrefslogtreecommitdiff
path: root/include/clang/Analysis/Analyses/LiveVariables.h
blob: 17f772da0c6dae7db933fd0c27ad403fb14172ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Live Variables analysis for source-level CFGs.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIVEVARIABLES_H
#define LLVM_CLANG_LIVEVARIABLES_H

#include "clang/AST/Decl.h"
#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
#include "clang/Analysis/FlowSensitive/DataflowValues.h"

namespace clang {

class Stmt;
class DeclRefExpr;
class SourceManager;

struct LiveVariables_ValueTypes {

  struct ObserverTy;

  // We keep dataflow state for declarations and block-level expressions;
  typedef StmtDeclBitVector_Types::ValTy ValTy;

  // We need to keep track of both declarations and CFGBlock-level expressions,
  // (so that we don't explore such expressions twice).  We also want
  // to compute liveness information for block-level expressions, since these
  // act as "temporary" values.

  struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
    ObserverTy* Observer;
    ValTy AlwaysLive;

    AnalysisDataTy() : Observer(NULL) {}
  };

  //===-----------------------------------------------------===//
  // ObserverTy - Observer for uninitialized values queries.
  //===-----------------------------------------------------===//

  struct ObserverTy {
    virtual ~ObserverTy() {}

    /// ObserveStmt - A callback invoked right before invoking the
    ///  liveness transfer function on the given statement.
    virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD,
                             const ValTy& V) {}

    virtual void ObserverKill(DeclRefExpr* DR) {}
  };
};

class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
                                            dataflow::backward_analysis_tag> {


public:
  typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;

  LiveVariables(ASTContext& Ctx, CFG& cfg);

  /// IsLive - Return true if a variable is live at beginning of a
  /// specified block.
  bool isLive(const CFGBlock* B, const VarDecl* D) const;

  /// IsLive - Returns true if a variable is live at the beginning of the
  ///  the statement.  This query only works if liveness information
  ///  has been recorded at the statement level (see runOnAllBlocks), and
  ///  only returns liveness information for block-level expressions.
  bool isLive(const Stmt* S, const VarDecl* D) const;

  /// IsLive - Returns true the block-level expression "value" is live
  ///  before the given block-level expression (see runOnAllBlocks).
  bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;

  /// IsLive - Return true if a variable is live according to the
  ///  provided livness bitvector.
  bool isLive(const ValTy& V, const VarDecl* D) const;

  /// dumpLiveness - Print to stderr the liveness information encoded
  ///  by a specified bitvector.
  void dumpLiveness(const ValTy& V, SourceManager& M) const;

  /// dumpBlockLiveness - Print to stderr the liveness information
  ///  associated with each basic block.
  void dumpBlockLiveness(SourceManager& M) const;

  /// getNumDecls - Return the number of variables (declarations) that
  ///  whose liveness status is being tracked by the dataflow
  ///  analysis.
  unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }

  /// IntializeValues - This routine can perform extra initialization, but
  ///  for LiveVariables this does nothing since all that logic is in
  ///  the constructor.
  void InitializeValues(const CFG& cfg) {}

  void runOnCFG(CFG& cfg);

  /// runOnAllBlocks - Propagate the dataflow values once for each block,
  ///  starting from the current dataflow values.  'recordStmtValues' indicates
  ///  whether the method should store dataflow values per each individual
  ///  block-level expression.
  void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs,
                      bool recordStmtValues=false);
};

} // end namespace clang

#endif