Created ValueStateManager, a full-blown class to manage the states

created for GRConstants.  Moved instances of ValueManager and SymbolManager
inside this class.  The goal is to gradually separate more of the state
management from the state transformation.

llvm-svn: 46721
This commit is contained in:
Ted Kremenek 2008-02-04 21:59:01 +00:00
parent ef14d5f926
commit 723fe3f863
2 changed files with 92 additions and 140 deletions

View File

@ -63,7 +63,7 @@ namespace {
class VISIBILITY_HIDDEN GRConstants {
public:
typedef ValueState StateTy;
typedef ValueStateManager::StateTy StateTy;
typedef GRStmtNodeBuilder<GRConstants> StmtNodeBuilder;
typedef GRBranchNodeBuilder<GRConstants> BranchNodeBuilder;
typedef ExplodedGraph<GRConstants> GraphTy;
@ -105,13 +105,13 @@ protected:
StmtNodeBuilder* Builder;
/// StateMgr - Object that manages the data for all created states.
StateTy::Factory StateMgr;
ValueStateManager StateMgr;
/// ValueMgr - Object that manages the data for all created RValues.
ValueManager ValMgr;
ValueManager& ValMgr;
/// SymMgr - Object that manages the symbol information.
SymbolManager SymMgr;
SymbolManager& SymMgr;
/// StmtEntryNode - The immediate predecessor node.
NodeTy* StmtEntryNode;
@ -130,8 +130,11 @@ protected:
public:
GRConstants(GraphTy& g) : G(g), Liveness(G.getCFG(), G.getFunctionDecl()),
Builder(NULL), ValMgr(G.getContext()), StmtEntryNode(NULL),
CurrentStmt(NULL) {
Builder(NULL),
StateMgr(G.getContext()),
ValMgr(StateMgr.getValueManager()),
SymMgr(StateMgr.getSymbolManager()),
StmtEntryNode(NULL), CurrentStmt(NULL) {
// Compute liveness information.
Liveness.runOnCFG(G.getCFG());
@ -144,7 +147,7 @@ public:
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
StateTy getInitialState() {
StateTy St = StateMgr.GetEmptyMap();
StateTy St = StateMgr.getInitialState();
// Iterate the parameters.
FunctionDecl& F = G.getFunctionDecl();
@ -182,13 +185,21 @@ public:
StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
RValue GetValue(const StateTy& St, Stmt* S);
inline RValue GetValue(const StateTy& St, Stmt* S) {
return StateMgr.GetValue(St, S);
}
inline RValue GetValue(const StateTy& St, const Stmt* S) {
return GetValue(St, const_cast<Stmt*>(S));
}
RValue GetValue(const StateTy& St, const LValue& LV);
LValue GetLValue(const StateTy& St, Stmt* S);
inline RValue GetValue(const StateTy& St, const LValue& LV) {
return StateMgr.GetValue(St, LV);
}
inline LValue GetLValue(const StateTy& St, Stmt* S) {
return StateMgr.GetLValue(St, S);
}
/// Assume - Create new state by assuming that a given expression
/// is true or false.
@ -224,6 +235,40 @@ public:
} // end anonymous namespace
GRConstants::StateTy
GRConstants::SetValue(StateTy St, Stmt* S, const RValue& V) {
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
bool isBlkExpr = false;
if (S == CurrentStmt) {
isBlkExpr = getCFG().isBlkExpr(S);
if (!isBlkExpr)
return St;
}
return StateMgr.SetValue(St, S, isBlkExpr, V);
}
GRConstants::StateTy
GRConstants::SetValue(StateTy St, const LValue& LV, const RValue& V) {
if (!LV.isValid())
return St;
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
return StateMgr.SetValue(St, LV, V);
}
void GRConstants::ProcessBranch(Stmt* Condition, Stmt* Term,
BranchNodeBuilder& builder) {
@ -298,135 +343,6 @@ void GRConstants::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
Builder = NULL;
}
RValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
switch (LV.getSubKind()) {
case LValueDeclKind: {
StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
return T ? T->getValue().second : InvalidValue();
}
default:
assert (false && "Invalid LValue.");
break;
}
return InvalidValue();
}
RValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
for (;;) {
switch (S->getStmtClass()) {
// ParenExprs are no-ops.
case Stmt::ParenExprClass:
S = cast<ParenExpr>(S)->getSubExpr();
continue;
// DeclRefExprs can either evaluate to an LValue or a Non-LValue
// (assuming an implicit "load") depending on the context. In this
// context we assume that we are retrieving the value contained
// within the referenced variables.
case Stmt::DeclRefExprClass:
return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
// Integer literals evaluate to an RValue. Simply retrieve the
// RValue for the literal.
case Stmt::IntegerLiteralClass:
return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
// Casts where the source and target type are the same
// are no-ops. We blast through these to get the descendant
// subexpression that has a value.
case Stmt::ImplicitCastExprClass: {
ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
if (C->getType() == C->getSubExpr()->getType()) {
S = C->getSubExpr();
continue;
}
break;
}
case Stmt::CastExprClass: {
CastExpr* C = cast<CastExpr>(S);
if (C->getType() == C->getSubExpr()->getType()) {
S = C->getSubExpr();
continue;
}
break;
}
// Handle all other Stmt* using a lookup.
default:
break;
};
break;
}
StateTy::TreeTy* T = St.SlimFind(S);
return T ? T->getValue().second : InvalidValue();
}
LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
while (ParenExpr* P = dyn_cast<ParenExpr>(S))
S = P->getSubExpr();
if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
return LValueDecl(DR->getDecl());
return cast<LValue>(GetValue(St, S));
}
GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
const RValue& V) {
assert (S);
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
bool isBlkExpr = false;
if (S == CurrentStmt) {
isBlkExpr = getCFG().isBlkExpr(S);
if (!isBlkExpr)
return St;
}
return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
: St;
}
GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
const RValue& V) {
if (!LV.isValid())
return St;
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
switch (LV.getSubKind()) {
case LValueDeclKind:
return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
: StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
default:
assert ("SetValue for given LValue type not yet implemented.");
return St;
}
}
GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
// Note: in the code below, we can assign a new map to M since the
// iterators are iterating over the tree of the *original* map.

View File

@ -125,6 +125,42 @@ struct GRTrait<ValueState> {
}
};
class ValueStateManager {
public:
typedef ValueState StateTy;
private:
typedef ValueState::Factory FactoryTy;
FactoryTy Factory;
/// ValueMgr - Object that manages the data for all created RValues.
ValueManager ValMgr;
/// SymMgr - Object that manages the symbol information.
SymbolManager SymMgr;
public:
ValueStateManager(ASTContext& Ctx) : ValMgr(Ctx) {}
StateTy getInitialState() {
return Factory.GetEmptyMap();
}
ValueManager& getValueManager() { return ValMgr; }
SymbolManager& getSymbolManager() { return SymMgr; }
StateTy SetValue(StateTy St, Stmt* S, bool isBlkExpr, const RValue& V);
StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
RValue GetValue(const StateTy& St, Stmt* S);
RValue GetValue(const StateTy& St, const LValue& LV);
LValue GetLValue(const StateTy& St, Stmt* S);
StateTy Remove(StateTy St, ValueKey K);
};
} // end clang namespace
//==------------------------------------------------------------------------==//