зеркало из https://github.com/microsoft/clang-1.git
Moved RemoveDeadBindings logic for the contents of 'Store' to a virtual RemoveDeadBindings method in StoreManager.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53726 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f242218fb9
Коммит
f59bf48ee7
|
@ -15,18 +15,33 @@
|
|||
#define LLVM_CLANG_ANALYSIS_STORE_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/RValues.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
typedef const void* Store;
|
||||
class LiveVariables;
|
||||
class Stmt;
|
||||
|
||||
class StoreManager {
|
||||
public:
|
||||
typedef llvm::SmallSet<SymbolID, 20> LiveSymbolsTy;
|
||||
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
|
||||
typedef std::vector<ValueDecl*> DeclRootsTy;
|
||||
|
||||
virtual ~StoreManager() {}
|
||||
virtual RVal GetRVal(Store St, LVal LV, QualType T) = 0;
|
||||
virtual RVal GetRVal(Store St, LVal LV, QualType T = QualType()) = 0;
|
||||
virtual Store SetRVal(Store St, LVal LV, RVal V) = 0;
|
||||
virtual Store Remove(Store St, LVal LV) = 0;
|
||||
virtual Store getInitialStore() = 0;
|
||||
|
||||
virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
|
||||
const LiveVariables& Live,
|
||||
DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
|
||||
DeadSymbolsTy& DSymbols) = 0;
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
@ -57,7 +56,7 @@ public:
|
|||
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
|
||||
typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstNotEqTy;
|
||||
typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstEqTy;
|
||||
|
||||
|
||||
private:
|
||||
void operator=(const ValueState& R) const;
|
||||
|
||||
|
@ -128,6 +127,7 @@ public:
|
|||
|
||||
// Iterators.
|
||||
|
||||
|
||||
// FIXME: We'll be removing the VarBindings iterator very soon. Right now
|
||||
// it assumes that Store is a VarBindingsTy.
|
||||
typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
|
||||
|
@ -140,6 +140,7 @@ public:
|
|||
VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
|
||||
return B.end();
|
||||
}
|
||||
|
||||
|
||||
typedef Environment::seb_iterator seb_iterator;
|
||||
seb_iterator seb_begin() const { return Env.seb_begin(); }
|
||||
|
@ -184,6 +185,7 @@ template<> struct GRTrait<ValueState*> {
|
|||
|
||||
|
||||
class ValueStateManager {
|
||||
|
||||
private:
|
||||
EnvironmentManager EnvMgr;
|
||||
llvm::OwningPtr<StoreManager> StMgr;
|
||||
|
@ -204,6 +206,10 @@ private:
|
|||
/// Alloc - A BumpPtrAllocator to allocate states.
|
||||
llvm::BumpPtrAllocator& Alloc;
|
||||
|
||||
/// DRoots - A vector to hold of worklist used by RemoveDeadSymbols.
|
||||
/// This vector is persistent because it is reused over and over.
|
||||
StoreManager::DeclRootsTy DRoots;
|
||||
|
||||
private:
|
||||
|
||||
Environment RemoveBlkExpr(const Environment& Env, Expr* E) {
|
||||
|
@ -232,11 +238,11 @@ public:
|
|||
BasicValueFactory& getBasicValueFactory() { return BasicVals; }
|
||||
SymbolManager& getSymbolManager() { return SymMgr; }
|
||||
|
||||
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
|
||||
typedef StoreManager::DeadSymbolsTy DeadSymbolsTy;
|
||||
|
||||
const ValueState* RemoveDeadBindings(const ValueState* St, Stmt* Loc,
|
||||
const LiveVariables& Liveness,
|
||||
DeadSymbolsTy& DeadSymbols);
|
||||
DeadSymbolsTy& DeadSyms);
|
||||
|
||||
const ValueState* RemoveSubExprBindings(const ValueState* St) {
|
||||
ValueState NewSt = *St;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
#include "clang/Analysis/PathSensitive/BasicStore.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
@ -34,6 +35,15 @@ public:
|
|||
virtual Store getInitialStore() {
|
||||
return VBFactory.GetEmptyMap().getRoot();
|
||||
}
|
||||
|
||||
virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
|
||||
const LiveVariables& Live,
|
||||
DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
|
||||
DeadSymbolsTy& DSymbols);
|
||||
|
||||
static inline VarBindingsTy GetVarBindings(Store store) {
|
||||
return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -108,34 +118,85 @@ RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
|
|||
return UnknownVal();
|
||||
}
|
||||
|
||||
Store BasicStoreManager::SetRVal(Store St, LVal LV, RVal V) {
|
||||
|
||||
VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
|
||||
|
||||
switch (LV.getSubKind()) {
|
||||
|
||||
case lval::DeclValKind:
|
||||
Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
|
||||
switch (LV.getSubKind()) {
|
||||
case lval::DeclValKind: {
|
||||
VarBindingsTy B = GetVarBindings(store);
|
||||
return V.isUnknown()
|
||||
? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
|
||||
: VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
|
||||
|
||||
}
|
||||
default:
|
||||
assert ("SetRVal for given LVal type not yet implemented.");
|
||||
return St;
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
||||
Store BasicStoreManager::Remove(Store St, LVal LV) {
|
||||
|
||||
VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
|
||||
|
||||
Store BasicStoreManager::Remove(Store store, LVal LV) {
|
||||
switch (LV.getSubKind()) {
|
||||
|
||||
case lval::DeclValKind:
|
||||
case lval::DeclValKind: {
|
||||
VarBindingsTy B = GetVarBindings(store);
|
||||
return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
|
||||
|
||||
}
|
||||
default:
|
||||
assert ("Remove for given LVal type not yet implemented.");
|
||||
return St;
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
||||
Store BasicStoreManager::RemoveDeadBindings(Store store,
|
||||
Stmt* Loc,
|
||||
const LiveVariables& Liveness,
|
||||
DeclRootsTy& DRoots,
|
||||
LiveSymbolsTy& LSymbols,
|
||||
DeadSymbolsTy& DSymbols) {
|
||||
|
||||
VarBindingsTy B = GetVarBindings(store);
|
||||
typedef RVal::symbol_iterator symbol_iterator;
|
||||
|
||||
// Iterate over the variable bindings.
|
||||
for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
|
||||
if (Liveness.isLive(Loc, I.getKey())) {
|
||||
DRoots.push_back(I.getKey());
|
||||
RVal X = I.getData();
|
||||
|
||||
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
|
||||
LSymbols.insert(*SI);
|
||||
}
|
||||
|
||||
// Scan for live variables and live symbols.
|
||||
llvm::SmallPtrSet<ValueDecl*, 10> Marked;
|
||||
|
||||
while (!DRoots.empty()) {
|
||||
ValueDecl* V = DRoots.back();
|
||||
DRoots.pop_back();
|
||||
|
||||
if (Marked.count(V))
|
||||
continue;
|
||||
|
||||
Marked.insert(V);
|
||||
|
||||
RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());
|
||||
|
||||
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
|
||||
LSymbols.insert(*SI);
|
||||
|
||||
if (!isa<lval::DeclVal>(X))
|
||||
continue;
|
||||
|
||||
const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
|
||||
DRoots.push_back(LVD.getDecl());
|
||||
}
|
||||
|
||||
// Remove dead variable bindings.
|
||||
for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
|
||||
if (!Marked.count(I.getKey())) {
|
||||
store = Remove(store, lval::DeclVal(I.getKey()));
|
||||
RVal X = I.getData();
|
||||
|
||||
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
|
||||
if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
|
|
@ -33,20 +33,21 @@ const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const {
|
|||
const ValueState*
|
||||
ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc,
|
||||
const LiveVariables& Liveness,
|
||||
DeadSymbolsTy& DeadSymbols) {
|
||||
DeadSymbolsTy& DSymbols) {
|
||||
|
||||
// This code essentially performs a "mark-and-sweep" of the VariableBindings.
|
||||
// The roots are any Block-level exprs and Decls that our liveness algorithm
|
||||
// tells us are live. We then see what Decls they may reference, and keep
|
||||
// those around. This code more than likely can be made faster, and the
|
||||
// frequency of which this method is called should be experimented with
|
||||
// for optimum performance.
|
||||
|
||||
llvm::SmallVector<ValueDecl*, 10> WList;
|
||||
llvm::SmallPtrSet<ValueDecl*, 10> Marked;
|
||||
llvm::SmallSet<SymbolID, 20> MarkedSymbols;
|
||||
// for optimum performance.
|
||||
DRoots.clear();
|
||||
StoreManager::LiveSymbolsTy LSymbols;
|
||||
|
||||
ValueState NewSt = *St;
|
||||
|
||||
// FIXME: Put this in environment.
|
||||
// Clean up the environment.
|
||||
|
||||
// Drop bindings for subexpressions.
|
||||
NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
|
||||
|
@ -62,12 +63,12 @@ ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc,
|
|||
|
||||
if (isa<lval::DeclVal>(X)) {
|
||||
lval::DeclVal LV = cast<lval::DeclVal>(X);
|
||||
WList.push_back(LV.getDecl());
|
||||
DRoots.push_back(LV.getDecl());
|
||||
}
|
||||
|
||||
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
||||
SI != SE; ++SI) {
|
||||
MarkedSymbols.insert(*SI);
|
||||
LSymbols.insert(*SI);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -80,69 +81,18 @@ ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc,
|
|||
}
|
||||
}
|
||||
|
||||
// Iterate over the variable bindings.
|
||||
|
||||
for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I)
|
||||
if (Liveness.isLive(Loc, I.getKey())) {
|
||||
WList.push_back(I.getKey());
|
||||
|
||||
RVal X = I.getData();
|
||||
|
||||
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
||||
SI != SE; ++SI) {
|
||||
MarkedSymbols.insert(*SI);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the mark-and-sweep.
|
||||
|
||||
while (!WList.empty()) {
|
||||
|
||||
ValueDecl* V = WList.back();
|
||||
WList.pop_back();
|
||||
|
||||
if (Marked.count(V))
|
||||
continue;
|
||||
|
||||
Marked.insert(V);
|
||||
|
||||
RVal X = GetRVal(St, lval::DeclVal(cast<VarDecl>(V)));
|
||||
|
||||
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
||||
SI != SE; ++SI) {
|
||||
MarkedSymbols.insert(*SI);
|
||||
}
|
||||
|
||||
if (!isa<lval::DeclVal>(X))
|
||||
continue;
|
||||
|
||||
const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
|
||||
WList.push_back(LVD.getDecl());
|
||||
}
|
||||
// Clean up the store.
|
||||
DSymbols.clear();
|
||||
NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness, DRoots,
|
||||
LSymbols, DSymbols);
|
||||
|
||||
// Remove dead variable bindings.
|
||||
|
||||
DeadSymbols.clear();
|
||||
|
||||
for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I)
|
||||
if (!Marked.count(I.getKey())) {
|
||||
NewSt.St = StMgr->Remove(NewSt.St, lval::DeclVal(I.getKey()));
|
||||
|
||||
RVal X = I.getData();
|
||||
|
||||
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
||||
SI != SE; ++SI)
|
||||
if (!MarkedSymbols.count(*SI)) DeadSymbols.insert(*SI);
|
||||
}
|
||||
|
||||
// Remove dead symbols.
|
||||
|
||||
// Remove the dead symbols from the symbol tracker.
|
||||
for (ValueState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) {
|
||||
|
||||
SymbolID sym = I.getKey();
|
||||
|
||||
if (!MarkedSymbols.count(sym)) {
|
||||
DeadSymbols.insert(sym);
|
||||
if (!LSymbols.count(sym)) {
|
||||
DSymbols.insert(sym);
|
||||
NewSt.ConstEq = CEFactory.Remove(NewSt.ConstEq, sym);
|
||||
}
|
||||
}
|
||||
|
@ -151,8 +101,8 @@ ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc,
|
|||
|
||||
SymbolID sym = I.getKey();
|
||||
|
||||
if (!MarkedSymbols.count(sym)) {
|
||||
DeadSymbols.insert(sym);
|
||||
if (!LSymbols.count(sym)) {
|
||||
DSymbols.insert(sym);
|
||||
NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, sym);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче