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:
parent
86964a9653
commit
d8902e06ba
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue