Overhauling of "ValueState" so that it represents its own functional data

structure that can contain several maps, not just one.

llvm-svn: 46744
This commit is contained in:
Ted Kremenek 2008-02-05 07:17:49 +00:00
parent 86964a9653
commit d8902e06ba
3 changed files with 175 additions and 56 deletions

View File

@ -874,17 +874,17 @@ template<>
struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
public DefaultDOTGraphTraits {
static void PrintKindLabel(std::ostream& Out, ValueKey::Kind kind) {
static void PrintKindLabel(std::ostream& Out, VarBindKey::Kind kind) {
switch (kind) {
case ValueKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
case ValueKey::IsDecl: Out << "Variables:\\l"; break;
case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
default: assert (false && "Unknown ValueKey type.");
case VarBindKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
case VarBindKey::IsDecl: Out << "Variables:\\l"; break;
case VarBindKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
default: assert (false && "Unknown VarBindKey type.");
}
}
static void PrintKind(std::ostream& Out, GRConstants::StateTy M,
ValueKey::Kind kind, bool isFirstGroup = false) {
VarBindKey::Kind kind, bool isFirstGroup = false) {
bool isFirst = true;
for (GRConstants::StateTy::iterator I=M.begin(), E=M.end();I!=E;++I) {
@ -968,11 +968,11 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
}
}
Out << "\\|StateID: " << (void*) N->getState().getRoot() << "\\|";
Out << "\\|StateID: " << (void*) N->getState().getImpl() << "\\|";
PrintKind(Out, N->getState(), ValueKey::IsDecl, true);
PrintKind(Out, N->getState(), ValueKey::IsBlkExpr);
PrintKind(Out, N->getState(), ValueKey::IsSubExpr);
PrintKind(Out, N->getState(), VarBindKey::IsDecl, true);
PrintKind(Out, N->getState(), VarBindKey::IsBlkExpr);
PrintKind(Out, N->getState(), VarBindKey::IsSubExpr);
Out << "\\l";
return Out.str();

View File

@ -1,3 +1,16 @@
//= ValueState.cpp - Path-Sens. "State" for tracking valuues -----*- C++ -*--=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This files defines SymbolID, VarBindKey, and ValueState.
//
//===----------------------------------------------------------------------===//
#include "ValueState.h"
using namespace clang;
@ -5,7 +18,9 @@ using namespace clang;
RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) {
switch (LV.getSubKind()) {
case LValueDeclKind: {
StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
StateTy::VariableBindingsTy::TreeTy* T =
St.getImpl()->VariableBindings.SlimFind(cast<LValueDecl>(LV).getDecl());
return T ? T->getValue().second : InvalidValue();
}
default:
@ -71,7 +86,8 @@ RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
break;
}
StateTy::TreeTy* T = St.SlimFind(S);
StateTy::VariableBindingsTy::TreeTy* T =
St.getImpl()->VariableBindings.SlimFind(S);
if (T) {
if (hasVal) *hasVal = true;
@ -100,7 +116,7 @@ ValueStateManager::SetValue(StateTy St, Stmt* S, bool isBlkExpr,
const RValue& V) {
assert (S);
return V.isValid() ? Factory.Add(St, ValueKey(S, isBlkExpr), V) : St;
return V.isValid() ? Add(St, VarBindKey(S, isBlkExpr), V) : St;
}
ValueStateManager::StateTy
@ -108,8 +124,8 @@ ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
switch (LV.getSubKind()) {
case LValueDeclKind:
return V.isValid() ? Factory.Add(St, cast<LValueDecl>(LV).getDecl(), V)
: Factory.Remove(St, cast<LValueDecl>(LV).getDecl());
return V.isValid() ? Add(St, cast<LValueDecl>(LV).getDecl(), V)
: Remove(St, cast<LValueDecl>(LV).getDecl());
default:
assert ("SetValue for given LValue type not yet implemented.");
@ -117,7 +133,52 @@ ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
}
}
ValueStateManager::StateTy ValueStateManager::Remove(StateTy St, ValueKey K) {
return Factory.Remove(St, K);
ValueStateManager::StateTy
ValueStateManager::Remove(StateTy St, VarBindKey K) {
// Create a new state with the old binding removed.
ValueStateImpl NewStateImpl = *St.getImpl();
NewStateImpl.VariableBindings =
VBFactory.Remove(NewStateImpl.VariableBindings, K);
// Get the persistent copy.
return getPersistentState(NewStateImpl);
}
ValueStateManager::StateTy
ValueStateManager::Add(StateTy St, VarBindKey K, const RValue& V) {
// Create a new state with the old binding removed.
ValueStateImpl NewStateImpl = *St.getImpl();
NewStateImpl.VariableBindings =
VBFactory.Add(NewStateImpl.VariableBindings, K, V);
// Get the persistent copy.
return getPersistentState(NewStateImpl);
}
ValueStateManager::StateTy
ValueStateManager::getInitialState() {
// Create a state with empty variable bindings.
ValueStateImpl StateImpl(VBFactory.GetEmptyMap());
return getPersistentState(StateImpl);
}
ValueStateManager::StateTy
ValueStateManager::getPersistentState(const ValueStateImpl &State) {
llvm::FoldingSetNodeID ID;
State.Profile(ID);
void* InsertPos;
if (ValueStateImpl* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
return I;
ValueStateImpl* I = (ValueStateImpl*) Alloc.Allocate<ValueState>();
new (I) ValueStateImpl(State);
StateSet.InsertNode(I, InsertPos);
return I;
}

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// This files defines SymbolID, ValueKey, and ValueState.
// This files defines SymbolID, VarBindKey, and ValueState.
//
//===----------------------------------------------------------------------===//
@ -39,11 +39,11 @@
namespace clang {
/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a
/// VarBindKey - A variant smart pointer that wraps either a ValueDecl* or a
/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
class ValueKey {
class VarBindKey {
uintptr_t Raw;
void operator=(const ValueKey& RHS); // Do not implement.
void operator=(const VarBindKey& RHS); // Do not implement.
public:
enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings.
@ -64,17 +64,17 @@ public:
return Raw >> 2;
}
ValueKey(const ValueDecl* VD)
VarBindKey(const ValueDecl* VD)
: Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
assert(VD && "ValueDecl cannot be NULL.");
}
ValueKey(Stmt* S, bool isBlkExpr = false)
VarBindKey(Stmt* S, bool isBlkExpr = false)
: Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
assert(S && "Tracked statement cannot be NULL.");
}
ValueKey(SymbolID V)
VarBindKey(SymbolID V)
: Raw((V << 2) | IsSymbol) {}
bool isSymbol() const { return getKind() == IsSymbol; }
@ -92,16 +92,16 @@ public:
ID.AddPointer(getPtr());
}
inline bool operator==(const ValueKey& X) const {
inline bool operator==(const VarBindKey& X) const {
return isSymbol() ? getSymbolID() == X.getSymbolID()
: getPtr() == X.getPtr();
}
inline bool operator!=(const ValueKey& X) const {
inline bool operator!=(const VarBindKey& X) const {
return !operator==(X);
}
inline bool operator<(const ValueKey& X) const {
inline bool operator<(const VarBindKey& X) const {
if (isSymbol())
return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false;
@ -113,40 +113,97 @@ public:
// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
//===----------------------------------------------------------------------===//
typedef llvm::ImmutableMap<ValueKey,RValue> ValueState;
template<>
struct GRTrait<ValueState> {
static inline void* toPtr(ValueState M) {
return reinterpret_cast<void*>(M.getRoot());
}
static inline ValueState toState(void* P) {
return ValueState(static_cast<ValueState::TreeTy*>(P));
namespace vstate {
typedef llvm::ImmutableMap<VarBindKey,RValue> VariableBindingsTy;
}
struct ValueStateImpl : public llvm::FoldingSetNode {
vstate::VariableBindingsTy VariableBindings;
ValueStateImpl(vstate::VariableBindingsTy VB)
: VariableBindings(VB) {}
ValueStateImpl(const ValueStateImpl& RHS)
: llvm::FoldingSetNode(), VariableBindings(RHS.VariableBindings) {}
static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
V.VariableBindings.Profile(ID);
}
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, *this);
}
};
class ValueState : public llvm::FoldingSetNode {
ValueStateImpl* Data;
public:
typedef vstate::VariableBindingsTy VariableBindingsTy;
typedef VariableBindingsTy::iterator iterator;
iterator begin() { return Data->VariableBindings.begin(); }
iterator end() { return Data->VariableBindings.end(); }
bool operator==(const ValueState& RHS) const {
return Data == RHS.Data;
}
static void Profile(llvm::FoldingSetNodeID& ID, const ValueState& V) {
ID.AddPointer(V.getImpl());
}
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, *this);
}
ValueState(ValueStateImpl* D) : Data(D) {}
ValueState() : Data(0) {}
void operator=(ValueStateImpl* D) {
Data = D;
}
ValueStateImpl* getImpl() const { return Data; }
};
template<> struct GRTrait<ValueState> {
static inline void* toPtr(ValueState St) {
return reinterpret_cast<void*>(St.getImpl());
}
static inline ValueState toState(void* P) {
return ValueState(static_cast<ValueStateImpl*>(P));
}
};
class ValueStateManager {
public:
typedef ValueState StateTy;
private:
typedef ValueState::Factory FactoryTy;
FactoryTy Factory;
ValueState::VariableBindingsTy::Factory VBFactory;
llvm::FoldingSet<ValueStateImpl> StateSet;
/// ValueMgr - Object that manages the data for all created RValues.
ValueManager ValMgr;
/// SymMgr - Object that manages the symbol information.
SymbolManager SymMgr;
/// Alloc - A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator& Alloc;
StateTy getPersistentState(const ValueState& St);
public:
ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& Alloc)
: ValMgr(Ctx, Alloc) {}
ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
: ValMgr(Ctx, alloc), Alloc(alloc) {}
StateTy getInitialState() {
return Factory.GetEmptyMap();
}
StateTy getInitialState();
ValueManager& getValueManager() { return ValMgr; }
SymbolManager& getSymbolManager() { return SymMgr; }
@ -158,40 +215,41 @@ public:
RValue GetValue(const StateTy& St, const LValue& LV);
LValue GetLValue(const StateTy& St, Stmt* S);
StateTy Remove(StateTy St, ValueKey K);
StateTy Add(StateTy St, VarBindKey K, const RValue& V);
StateTy Remove(StateTy St, VarBindKey K);
StateTy getPersistentState(const ValueStateImpl& Impl);
};
} // end clang namespace
//==------------------------------------------------------------------------==//
// Casting machinery to get cast<> and dyn_cast<> working with ValueKey.
// Casting machinery to get cast<> and dyn_cast<> working with VarBindKey.
//==------------------------------------------------------------------------==//
namespace llvm {
template<> inline bool
isa<clang::ValueDecl,clang::ValueKey>(const clang::ValueKey& V) {
return V.getKind() == clang::ValueKey::IsDecl;
isa<clang::ValueDecl,clang::VarBindKey>(const clang::VarBindKey& V) {
return V.getKind() == clang::VarBindKey::IsDecl;
}
template<> inline bool
isa<clang::Stmt,clang::ValueKey>(const clang::ValueKey& V) {
return ((unsigned) V.getKind()) < clang::ValueKey::IsDecl;
isa<clang::Stmt,clang::VarBindKey>(const clang::VarBindKey& V) {
return ((unsigned) V.getKind()) < clang::VarBindKey::IsDecl;
}
template<> struct cast_retty_impl<clang::ValueDecl,clang::ValueKey> {
template<> struct cast_retty_impl<clang::ValueDecl,clang::VarBindKey> {
typedef const clang::ValueDecl* ret_type;
};
template<> struct cast_retty_impl<clang::Stmt,clang::ValueKey> {
template<> struct cast_retty_impl<clang::Stmt,clang::VarBindKey> {
typedef const clang::Stmt* ret_type;
};
template<> struct simplify_type<clang::ValueKey> {
template<> struct simplify_type<clang::VarBindKey> {
typedef void* SimpleType;
static inline SimpleType getSimplifiedValue(const clang::ValueKey &V) {
static inline SimpleType getSimplifiedValue(const clang::VarBindKey &V) {
return V.getPtr();
}
};