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