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*> : struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
public DefaultDOTGraphTraits { public DefaultDOTGraphTraits {
static void PrintKindLabel(std::ostream& Out, ValueKey::Kind kind) { static void PrintKindLabel(std::ostream& Out, VarBindKey::Kind kind) {
switch (kind) { switch (kind) {
case ValueKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break; case VarBindKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
case ValueKey::IsDecl: Out << "Variables:\\l"; break; case VarBindKey::IsDecl: Out << "Variables:\\l"; break;
case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break; case VarBindKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
default: assert (false && "Unknown ValueKey type."); default: assert (false && "Unknown VarBindKey type.");
} }
} }
static void PrintKind(std::ostream& Out, GRConstants::StateTy M, static void PrintKind(std::ostream& Out, GRConstants::StateTy M,
ValueKey::Kind kind, bool isFirstGroup = false) { VarBindKey::Kind kind, bool isFirstGroup = false) {
bool isFirst = true; bool isFirst = true;
for (GRConstants::StateTy::iterator I=M.begin(), E=M.end();I!=E;++I) { 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(), VarBindKey::IsDecl, true);
PrintKind(Out, N->getState(), ValueKey::IsBlkExpr); PrintKind(Out, N->getState(), VarBindKey::IsBlkExpr);
PrintKind(Out, N->getState(), ValueKey::IsSubExpr); PrintKind(Out, N->getState(), VarBindKey::IsSubExpr);
Out << "\\l"; Out << "\\l";
return Out.str(); 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" #include "ValueState.h"
using namespace clang; using namespace clang;
@ -5,7 +18,9 @@ using namespace clang;
RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) { RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) {
switch (LV.getSubKind()) { switch (LV.getSubKind()) {
case LValueDeclKind: { 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(); return T ? T->getValue().second : InvalidValue();
} }
default: default:
@ -71,7 +86,8 @@ RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
break; break;
} }
StateTy::TreeTy* T = St.SlimFind(S); StateTy::VariableBindingsTy::TreeTy* T =
St.getImpl()->VariableBindings.SlimFind(S);
if (T) { if (T) {
if (hasVal) *hasVal = true; if (hasVal) *hasVal = true;
@ -100,7 +116,7 @@ ValueStateManager::SetValue(StateTy St, Stmt* S, bool isBlkExpr,
const RValue& V) { const RValue& V) {
assert (S); 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 ValueStateManager::StateTy
@ -108,8 +124,8 @@ ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
switch (LV.getSubKind()) { switch (LV.getSubKind()) {
case LValueDeclKind: case LValueDeclKind:
return V.isValid() ? Factory.Add(St, cast<LValueDecl>(LV).getDecl(), V) return V.isValid() ? Add(St, cast<LValueDecl>(LV).getDecl(), V)
: Factory.Remove(St, cast<LValueDecl>(LV).getDecl()); : Remove(St, cast<LValueDecl>(LV).getDecl());
default: default:
assert ("SetValue for given LValue type not yet implemented."); 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) { ValueStateManager::StateTy
return Factory.Remove(St, K); 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 { 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 /// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
class ValueKey { class VarBindKey {
uintptr_t Raw; uintptr_t Raw;
void operator=(const ValueKey& RHS); // Do not implement. void operator=(const VarBindKey& RHS); // Do not implement.
public: public:
enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings. enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings.
@ -64,17 +64,17 @@ public:
return Raw >> 2; return Raw >> 2;
} }
ValueKey(const ValueDecl* VD) VarBindKey(const ValueDecl* VD)
: Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) { : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
assert(VD && "ValueDecl cannot be NULL."); 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)){ : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){
assert(S && "Tracked statement cannot be NULL."); assert(S && "Tracked statement cannot be NULL.");
} }
ValueKey(SymbolID V) VarBindKey(SymbolID V)
: Raw((V << 2) | IsSymbol) {} : Raw((V << 2) | IsSymbol) {}
bool isSymbol() const { return getKind() == IsSymbol; } bool isSymbol() const { return getKind() == IsSymbol; }
@ -92,16 +92,16 @@ public:
ID.AddPointer(getPtr()); ID.AddPointer(getPtr());
} }
inline bool operator==(const ValueKey& X) const { inline bool operator==(const VarBindKey& X) const {
return isSymbol() ? getSymbolID() == X.getSymbolID() return isSymbol() ? getSymbolID() == X.getSymbolID()
: getPtr() == X.getPtr(); : getPtr() == X.getPtr();
} }
inline bool operator!=(const ValueKey& X) const { inline bool operator!=(const VarBindKey& X) const {
return !operator==(X); return !operator==(X);
} }
inline bool operator<(const ValueKey& X) const { inline bool operator<(const VarBindKey& X) const {
if (isSymbol()) if (isSymbol())
return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false; return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false;
@ -113,40 +113,97 @@ public:
// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues. // ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
typedef llvm::ImmutableMap<ValueKey,RValue> ValueState; namespace vstate {
typedef llvm::ImmutableMap<VarBindKey,RValue> VariableBindingsTy;
template<> }
struct GRTrait<ValueState> {
static inline void* toPtr(ValueState M) { struct ValueStateImpl : public llvm::FoldingSetNode {
return reinterpret_cast<void*>(M.getRoot()); vstate::VariableBindingsTy VariableBindings;
}
static inline ValueState toState(void* P) { ValueStateImpl(vstate::VariableBindingsTy VB)
return ValueState(static_cast<ValueState::TreeTy*>(P)); : 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 { class ValueStateManager {
public: public:
typedef ValueState StateTy; typedef ValueState StateTy;
private: private:
typedef ValueState::Factory FactoryTy; ValueState::VariableBindingsTy::Factory VBFactory;
FactoryTy Factory; llvm::FoldingSet<ValueStateImpl> StateSet;
/// ValueMgr - Object that manages the data for all created RValues. /// ValueMgr - Object that manages the data for all created RValues.
ValueManager ValMgr; ValueManager ValMgr;
/// SymMgr - Object that manages the symbol information. /// SymMgr - Object that manages the symbol information.
SymbolManager SymMgr; SymbolManager SymMgr;
/// Alloc - A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator& Alloc;
StateTy getPersistentState(const ValueState& St);
public: public:
ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& Alloc) ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
: ValMgr(Ctx, Alloc) {} : ValMgr(Ctx, alloc), Alloc(alloc) {}
StateTy getInitialState() { StateTy getInitialState();
return Factory.GetEmptyMap();
}
ValueManager& getValueManager() { return ValMgr; } ValueManager& getValueManager() { return ValMgr; }
SymbolManager& getSymbolManager() { return SymMgr; } SymbolManager& getSymbolManager() { return SymMgr; }
@ -158,40 +215,41 @@ public:
RValue GetValue(const StateTy& St, const LValue& LV); RValue GetValue(const StateTy& St, const LValue& LV);
LValue GetLValue(const StateTy& St, Stmt* S); 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 } // 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 { namespace llvm {
template<> inline bool template<> inline bool
isa<clang::ValueDecl,clang::ValueKey>(const clang::ValueKey& V) { isa<clang::ValueDecl,clang::VarBindKey>(const clang::VarBindKey& V) {
return V.getKind() == clang::ValueKey::IsDecl; return V.getKind() == clang::VarBindKey::IsDecl;
} }
template<> inline bool template<> inline bool
isa<clang::Stmt,clang::ValueKey>(const clang::ValueKey& V) { isa<clang::Stmt,clang::VarBindKey>(const clang::VarBindKey& V) {
return ((unsigned) V.getKind()) < clang::ValueKey::IsDecl; 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; 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; typedef const clang::Stmt* ret_type;
}; };
template<> struct simplify_type<clang::ValueKey> { template<> struct simplify_type<clang::VarBindKey> {
typedef void* SimpleType; typedef void* SimpleType;
static inline SimpleType getSimplifiedValue(const clang::ValueKey &V) { static inline SimpleType getSimplifiedValue(const clang::VarBindKey &V) {
return V.getPtr(); return V.getPtr();
} }
}; };