blob: 2e10f4a0a31811c765393362cb397fcb73bbeeb5 [file] [log] [blame]
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and 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/FlowSensitive/DataflowValues.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class Stmt;
class DeclRefExpr;
class SourceManager;
struct LiveVariables_ValueTypes {
//===-----------------------------------------------------===//
// AnalysisDataTy - Whole-function analysis meta data.
//===-----------------------------------------------------===//
class ObserverTy;
class AnalysisDataTy {
typedef llvm::DenseMap<const VarDecl*, unsigned> VMapTy;
VMapTy M;
unsigned NDecls;
public:
ObserverTy* Observer;
AnalysisDataTy() : NDecls(0), Observer(NULL) {}
bool Tracked(const VarDecl* VD) const { return M.find(VD) != M.end(); }
void RegisterDecl(const VarDecl* VD) { if (!Tracked(VD)) M[VD] = NDecls++; }
unsigned operator[](const VarDecl* VD) const {
VMapTy::const_iterator I = M.find(VD);
assert (I != M.end());
return I->second;
}
unsigned operator[](const ScopedDecl* S) const {
return (*this)[cast<VarDecl>(S)];
}
unsigned getNumDecls() const { return NDecls; }
typedef VMapTy::const_iterator iterator;
iterator begin() const { return M.begin(); }
iterator end() const { return M.end(); }
};
//===-----------------------------------------------------===//
// ValTy - Dataflow value.
//===-----------------------------------------------------===//
class ValTy {
llvm::BitVector V;
public:
void copyValues(const ValTy& RHS) { V = RHS.V; }
bool operator==(const ValTy& RHS) const { return V == RHS.V; }
void resetValues(const AnalysisDataTy& AD) {
V.resize(AD.getNumDecls());
V.reset();
}
llvm::BitVector::reference operator[](unsigned i) {
assert (i < V.size() && "Liveness bitvector access is out-of-bounds.");
return V[i];
}
const llvm::BitVector::reference operator[](unsigned i) const {
return const_cast<ValTy&>(*this)[i];
}
bool operator()(const AnalysisDataTy& AD, const ScopedDecl* D) const {
return (*this)[AD[D]];
}
ValTy& operator|=(ValTy& RHS) { V |= RHS.V; return *this; }
void set(unsigned i) { V.set(i); }
void reset(unsigned i) { V.reset(i); }
};
//===-----------------------------------------------------===//
// ObserverTy - Observer for uninitialized values queries.
//===-----------------------------------------------------===//
class ObserverTy {
public:
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() {}
/// IsLive - Return true if a variable is live at beginning of a
/// specified block.
bool isLive(const CFGBlock* B, const VarDecl* D) 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 - Create initial dataflow values and meta data for
/// a given CFG. This is intended to be called by the dataflow solver.
void InitializeValues(const CFG& cfg);
void runOnCFG(const CFG& cfg);
void runOnAllBlocks(const CFG& cfg, ObserverTy& Obs);
};
} // end namespace clang
#endif