forked from OSchip/llvm-project
Removed "ObserverTy" from core DataflowValues types. The observer
mechanism can be implemented simply by affixing the Observer to an analysis meta data, so it doesn't need to be a required type. This also permits analyses not to implement an Observer if it doesn't make sense. Changed "DataflowValues::MetaDataTy" to "DataflowValues::AnalysisDataTy" to reflect that the type enscapsulated the data associated with analyzing a given CFG. Changed CFGStmtVisitor::BlockStmt_VisitImplicitControlFlowStmt(Stmt*) to ...VisitImplicitControlFlowExpr(Expr*). The type narrowing is more precise and more useful to clients. Added CFGStmtVisitor::BlockStmt_VisitExpr to reflect the visitation of expressions at the block statement level. This captures all implicit control-flow statements as well as other expressions that are hoisted to the block level (such as conditions for terminators and function calls). This is especially useful for dataflow analysis. llvm-svn: 42034
This commit is contained in:
parent
c3fddac8e7
commit
789ea076a8
|
@ -62,14 +62,13 @@ public:
|
||||||
typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
|
typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
|
||||||
typedef typename _DFValuesTy::ValTy ValTy;
|
typedef typename _DFValuesTy::ValTy ValTy;
|
||||||
typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
|
typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
|
||||||
typedef typename _DFValuesTy::ObserverTy ObserverTy;
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// External interface: constructing and running the solver.
|
// External interface: constructing and running the solver.
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataflowSolver(DFValuesTy& d, ObserverTy* o = NULL) : D(d), O(o) {}
|
DataflowSolver(DFValuesTy& d) : D(d) {}
|
||||||
~DataflowSolver() {}
|
~DataflowSolver() {}
|
||||||
|
|
||||||
/// runOnCFG - Computes dataflow values for all blocks in a CFG.
|
/// runOnCFG - Computes dataflow values for all blocks in a CFG.
|
||||||
|
@ -86,7 +85,7 @@ public:
|
||||||
/// only be used for querying the dataflow values within a block with
|
/// only be used for querying the dataflow values within a block with
|
||||||
/// and Observer object.
|
/// and Observer object.
|
||||||
void runOnBlock(const CFGBlock* B) {
|
void runOnBlock(const CFGBlock* B) {
|
||||||
TransferFuncsTy TF (D.getMetaData(),O);
|
TransferFuncsTy TF (D.getAnalysisData());
|
||||||
ProcessBlock(B,TF,AnalysisDirTag());
|
ProcessBlock(B,TF,AnalysisDirTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +105,7 @@ private:
|
||||||
WorkList.enqueue(&cfg.getEntry());
|
WorkList.enqueue(&cfg.getEntry());
|
||||||
|
|
||||||
// Create the state for transfer functions.
|
// Create the state for transfer functions.
|
||||||
TransferFuncsTy TF(D.getMetaData(),O);
|
TransferFuncsTy TF(D.getAnalysisData());
|
||||||
|
|
||||||
// Process the worklist until it is empty.
|
// Process the worklist until it is empty.
|
||||||
while (!WorkList.isEmpty()) {
|
while (!WorkList.isEmpty()) {
|
||||||
|
@ -131,7 +130,7 @@ private:
|
||||||
WorkList.enqueue(&cfg.getExit());
|
WorkList.enqueue(&cfg.getExit());
|
||||||
|
|
||||||
// Create the state for transfer functions.
|
// Create the state for transfer functions.
|
||||||
TransferFuncsTy TF(D.getMetaData(),O);
|
TransferFuncsTy TF(D.getAnalysisData());
|
||||||
|
|
||||||
// Process the worklist until it is empty.
|
// Process the worklist until it is empty.
|
||||||
while (!WorkList.isEmpty()) {
|
while (!WorkList.isEmpty()) {
|
||||||
|
@ -213,7 +212,6 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DFValuesTy& D;
|
DFValuesTy& D;
|
||||||
ObserverTy* O;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,26 +24,30 @@ using namespace clang;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class RegisterDecls : public CFGVarDeclVisitor<RegisterDecls> {
|
class RegisterDeclsAndExprs : public CFGVarDeclVisitor<RegisterDeclsAndExprs> {
|
||||||
UninitializedValues::MetaDataTy& M;
|
UninitializedValues::AnalysisDataTy& AD;
|
||||||
public:
|
public:
|
||||||
RegisterDecls(const CFG& cfg, UninitializedValues::MetaDataTy& m) :
|
RegisterDeclsAndExprs(const CFG& cfg, UninitializedValues::AnalysisDataTy& ad)
|
||||||
CFGVarDeclVisitor<RegisterDecls>(cfg), M(m) {}
|
: CFGVarDeclVisitor<RegisterDeclsAndExprs>(cfg), AD(ad)
|
||||||
|
{}
|
||||||
|
|
||||||
void VisitVarDecl(VarDecl* D) {
|
void VisitVarDecl(VarDecl* D) {
|
||||||
if (M.Map.find(D) == M.Map.end()) {
|
if (AD.VMap.find(D) == AD.VMap.end())
|
||||||
M.Map[D] = M.NumDecls++;
|
AD.VMap[D] = AD.Counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockStmt_VisitExpr(Expr* E) {
|
||||||
|
if (AD.EMap.find(E) == AD.EMap.end())
|
||||||
|
AD.EMap[E] = AD.Counter++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
void UninitializedValues::InitializeValues(const CFG& cfg) {
|
void UninitializedValues::InitializeValues(const CFG& cfg) {
|
||||||
RegisterDecls R(cfg,this->getMetaData());
|
RegisterDeclsAndExprs R(cfg,this->getAnalysisData());
|
||||||
R.VisitAllDecls();
|
R.VisitAllDecls();
|
||||||
|
getBlockDataMap()[ &cfg.getEntry() ].resize( getAnalysisData().Counter );
|
||||||
getBlockDataMap()[ &cfg.getEntry() ].resize( getMetaData().NumDecls );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -53,15 +57,17 @@ void UninitializedValues::InitializeValues(const CFG& cfg) {
|
||||||
namespace {
|
namespace {
|
||||||
class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
|
class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
|
||||||
UninitializedValues::ValTy V;
|
UninitializedValues::ValTy V;
|
||||||
UninitializedValues::MetaDataTy& M;
|
UninitializedValues::AnalysisDataTy& AD;
|
||||||
UninitializedValues::ObserverTy* O;
|
|
||||||
public:
|
public:
|
||||||
TransferFuncs(UninitializedValues::MetaDataTy& m,
|
TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
|
||||||
UninitializedValues::ObserverTy* o) : M(m), O(o) {
|
V.resize(AD.Counter);
|
||||||
V.resize(M.NumDecls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UninitializedValues::ValTy& getVal() { return V; }
|
UninitializedValues::ValTy& getVal() { return V; }
|
||||||
|
|
||||||
|
// bool VisitDeclRefExpr(DeclRefExpr* DR);
|
||||||
|
// bool VisitBinaryOperator(BinaryOperator* B);
|
||||||
|
// bool VisitUnaryOperator(UnaryOperator* U);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
|
||||||
|
|
||||||
#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\
|
#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\
|
||||||
{ return\
|
{ return\
|
||||||
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowStmt(S); }
|
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\
|
||||||
|
cast<Expr>(S)); }
|
||||||
|
|
||||||
template <typename ImplClass, typename RetTy=void>
|
template <typename ImplClass, typename RetTy=void>
|
||||||
class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
|
class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
|
||||||
|
@ -54,6 +55,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (isa<Expr>(S))
|
||||||
|
return
|
||||||
|
static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S));
|
||||||
|
else
|
||||||
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
|
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +67,12 @@ public:
|
||||||
DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
|
DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
|
||||||
DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
|
DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
|
||||||
|
|
||||||
RetTy BlockStmt_VisitImplicitControlFlowStmt(Stmt* S) {
|
RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) {
|
||||||
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
|
return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
RetTy BlockStmt_VisitExpr(Expr* E) {
|
||||||
|
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
RetTy BlockStmt_VisitStmt(Stmt* S) {
|
RetTy BlockStmt_VisitStmt(Stmt* S) {
|
||||||
|
@ -72,12 +81,12 @@ public:
|
||||||
|
|
||||||
RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) {
|
RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) {
|
||||||
return
|
return
|
||||||
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowStmt(B);
|
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
|
||||||
}
|
}
|
||||||
|
|
||||||
RetTy BlockStmt_VisitComma(BinaryOperator* B) {
|
RetTy BlockStmt_VisitComma(BinaryOperator* B) {
|
||||||
return
|
return
|
||||||
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowStmt(B);
|
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#ifndef LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
|
#ifndef LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
|
||||||
#define LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
|
#define LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
|
||||||
|
|
||||||
#include "clang/AST/StmtVisitor.h"
|
#include "clang/Analysis/CFGStmtVisitor.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/Stmt.h"
|
#include "clang/AST/Stmt.h"
|
||||||
#include "clang/AST/CFG.h"
|
#include "clang/AST/CFG.h"
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
template <typename ImplClass>
|
template <typename ImplClass>
|
||||||
class CFGVarDeclVisitor : public StmtVisitor<ImplClass> {
|
class CFGVarDeclVisitor : public CFGStmtVisitor<ImplClass> {
|
||||||
const CFG& cfg;
|
const CFG& cfg;
|
||||||
public:
|
public:
|
||||||
CFGVarDeclVisitor(const CFG& c) : cfg(c) {}
|
CFGVarDeclVisitor(const CFG& c) : cfg(c) {}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace dataflow {
|
||||||
} // end namespace dataflow
|
} // end namespace dataflow
|
||||||
|
|
||||||
|
|
||||||
template <typename TypeClass,
|
template <typename ValueTypes,
|
||||||
typename _AnalysisDirTag = dataflow::forward_analysis_tag >
|
typename _AnalysisDirTag = dataflow::forward_analysis_tag >
|
||||||
class DataflowValues {
|
class DataflowValues {
|
||||||
|
|
||||||
|
@ -44,10 +44,8 @@ class DataflowValues {
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename TypeClass::ValTy ValTy;
|
typedef typename ValueTypes::ValTy ValTy;
|
||||||
typedef typename TypeClass::MetaDataTy MetaDataTy;
|
typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
|
||||||
typedef typename TypeClass::ObserverTy ObserverTy;
|
|
||||||
|
|
||||||
typedef _AnalysisDirTag AnalysisDirTag;
|
typedef _AnalysisDirTag AnalysisDirTag;
|
||||||
typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
|
typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
|
||||||
|
|
||||||
|
@ -101,11 +99,12 @@ public:
|
||||||
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
|
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
|
||||||
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
|
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
|
||||||
|
|
||||||
/// getMetaData - Retrieves the meta data associated with a dataflow analysis.
|
/// getAnalysisData - Retrieves the meta data associated with a
|
||||||
|
/// dataflow analysis for analyzing a particular CFG.
|
||||||
/// This is typically consumed by transfer function code (via the solver).
|
/// This is typically consumed by transfer function code (via the solver).
|
||||||
/// This can also be used by subclasses to interpret the dataflow values.
|
/// This can also be used by subclasses to interpret the dataflow values.
|
||||||
MetaDataTy& getMetaData() { return Meta; }
|
AnalysisDataTy& getAnalysisData() { return AnalysisData; }
|
||||||
const MetaDataTy& getMetaData() const { return Meta; }
|
const AnalysisDataTy& getAnalysisData() const { return AnalysisData; }
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Internal data.
|
// Internal data.
|
||||||
|
@ -113,7 +112,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BlockDataMapTy BlockDataMap;
|
BlockDataMapTy BlockDataMap;
|
||||||
MetaDataTy Meta;
|
AnalysisDataTy AnalysisData;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
|
@ -21,10 +21,12 @@
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
class VarDecl;
|
class VarDecl;
|
||||||
|
class Expr;
|
||||||
|
|
||||||
/// UninitializedValuesTypes - Utility class to wrap type declarations
|
/// UninitializedValues_ValueTypes - Utility class to wrap type declarations
|
||||||
/// used for defining the UninitializedValues class.
|
/// for dataflow values and dataflow analysis state for the
|
||||||
class UninitializedValuesTypes {
|
/// Unitialized Values analysis.
|
||||||
|
class UninitializedValues_ValueTypes {
|
||||||
public:
|
public:
|
||||||
class ValTy {
|
class ValTy {
|
||||||
llvm::BitVector BV;
|
llvm::BitVector BV;
|
||||||
|
@ -41,25 +43,20 @@ public:
|
||||||
void copyValues(ValTy& RHS) { BV = RHS.BV; }
|
void copyValues(ValTy& RHS) { BV = RHS.BV; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MetaDataTy {
|
struct AnalysisDataTy {
|
||||||
llvm::DenseMap<const VarDecl*, unsigned > Map;
|
llvm::DenseMap<const VarDecl*, unsigned > VMap;
|
||||||
unsigned NumDecls;
|
llvm::DenseMap<const Expr*, unsigned > EMap;
|
||||||
|
unsigned Counter;
|
||||||
|
|
||||||
MetaDataTy() : NumDecls(0) {}
|
AnalysisDataTy() : Counter(0) {}
|
||||||
};
|
|
||||||
|
|
||||||
class ObserverTy {
|
|
||||||
virtual ~ObserverTy();
|
|
||||||
virtual void ObserveStmt(Stmt* S, MetaDataTy& M, ValTy& V) {}
|
|
||||||
virtual void ObserveBlockExit(const CFGBlock* B, MetaDataTy& M, ValTy& V) {}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// UninitializedValues - Objects of this class encapsulate dataflow analysis
|
/// UninitializedValues - Objects of this class encapsulate dataflow analysis
|
||||||
/// information regarding what variable declarations in a function are
|
/// information regarding what variable declarations in a function are
|
||||||
/// potentially unintialized.
|
/// potentially unintialized.
|
||||||
class UninitializedValues : public DataflowValues<UninitializedValuesTypes> {
|
class UninitializedValues :
|
||||||
|
public DataflowValues<UninitializedValues_ValueTypes> {
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Public interface.
|
// Public interface.
|
||||||
|
|
Loading…
Reference in New Issue