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*> :
|
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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue