From: Ted Kremenek Date: Tue, 5 Feb 2008 07:17:49 +0000 (+0000) Subject: Overhauling of "ValueState" so that it represents its own functional data X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9153f73d1035ddcaac5a253ac2a0570e04e22b1f;p=clang Overhauling of "ValueState" so that it represents its own functional data structure that can contain several maps, not just one. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46744 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp index 1143ad2a25..6a1c771b22 100644 --- a/Analysis/GRConstants.cpp +++ b/Analysis/GRConstants.cpp @@ -874,17 +874,17 @@ template<> struct VISIBILITY_HIDDEN DOTGraphTraits : 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 : } } - 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(); diff --git a/Analysis/ValueState.cpp b/Analysis/ValueState.cpp index f323fd4f90..2166a8699f 100644 --- a/Analysis/ValueState.cpp +++ b/Analysis/ValueState.cpp @@ -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(LV).getDecl()); + StateTy::VariableBindingsTy::TreeTy* T = + St.getImpl()->VariableBindings.SlimFind(cast(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(LV).getDecl(), V) - : Factory.Remove(St, cast(LV).getDecl()); + return V.isValid() ? Add(St, cast(LV).getDecl(), V) + : Remove(St, cast(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(); + new (I) ValueStateImpl(State); + StateSet.InsertNode(I, InsertPos); + return I; +} diff --git a/Analysis/ValueState.h b/Analysis/ValueState.h index c686a48f20..b0f0496e04 100644 --- a/Analysis/ValueState.h +++ b/Analysis/ValueState.h @@ -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(VD) | IsDecl) { assert(VD && "ValueDecl cannot be NULL."); } - ValueKey(Stmt* S, bool isBlkExpr = false) + VarBindKey(Stmt* S, bool isBlkExpr = false) : Raw(reinterpret_cast(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 ValueState; +namespace vstate { + typedef llvm::ImmutableMap 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; + -template<> -struct GRTrait { - static inline void* toPtr(ValueState M) { - return reinterpret_cast(M.getRoot()); + + 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 { + static inline void* toPtr(ValueState St) { + return reinterpret_cast(St.getImpl()); } - static inline ValueState toState(void* P) { - return ValueState(static_cast(P)); + static inline ValueState toState(void* P) { + return ValueState(static_cast(P)); } }; - + class ValueStateManager { public: typedef ValueState StateTy; private: - typedef ValueState::Factory FactoryTy; - FactoryTy Factory; + ValueState::VariableBindingsTy::Factory VBFactory; + llvm::FoldingSet 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(const clang::ValueKey& V) { - return V.getKind() == clang::ValueKey::IsDecl; + isa(const clang::VarBindKey& V) { + return V.getKind() == clang::VarBindKey::IsDecl; } template<> inline bool - isa(const clang::ValueKey& V) { - return ((unsigned) V.getKind()) < clang::ValueKey::IsDecl; + isa(const clang::VarBindKey& V) { + return ((unsigned) V.getKind()) < clang::VarBindKey::IsDecl; } - template<> struct cast_retty_impl { + template<> struct cast_retty_impl { typedef const clang::ValueDecl* ret_type; }; - template<> struct cast_retty_impl { + template<> struct cast_retty_impl { typedef const clang::Stmt* ret_type; }; - template<> struct simplify_type { + template<> struct simplify_type { typedef void* SimpleType; - static inline SimpleType getSimplifiedValue(const clang::ValueKey &V) { + static inline SimpleType getSimplifiedValue(const clang::VarBindKey &V) { return V.getPtr(); } };