"git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "0311ade94c28b938e781aedd7ea19b7c95ff81c9"
Newer
Older
//= GRState*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 file defines SymbolID, ExprBindKey, and GRState*
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/GRState.h"
Ted Kremenek
committed
#include "llvm/ADT/SmallSet.h"
Ted Kremenek
committed
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
using namespace clang;
bool GRState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
// Retrieve the NE-set associated with the given symbol.
Ted Kremenek
committed
const ConstNotEqTy::data_type* T = ConstNotEq.lookup(sym);
// See if V is present in the NE-set.
Ted Kremenek
committed
return T ? T->contains(&V) : false;
Ted Kremenek
committed
}
bool GRState::isEqual(SymbolID sym, const llvm::APSInt& V) const {
Ted Kremenek
committed
// Retrieve the EQ-set associated with the given symbol.
const ConstEqTy::data_type* T = ConstEq.lookup(sym);
// See if V is present in the EQ-set.
return T ? **T == V : false;
}
const llvm::APSInt* GRState::getSymVal(SymbolID sym) const {
Ted Kremenek
committed
ConstEqTy::data_type* T = ConstEq.lookup(sym);
return T ? *T : NULL;
Ted Kremenek
committed
}
const GRState*
GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc,
const LiveVariables& Liveness,
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.
DRoots.clear();
StoreManager::LiveSymbolsTy LSymbols;
// FIXME: Put this in environment.
// Clean up the environment.
// Drop bindings for subexpressions.
NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
// Iterate over the block-expr bindings.
for (GRState::beb_iterator I = St->beb_begin(), E = St->beb_end();
I!=E ; ++I) {
Expr* BlkExpr = I.getKey();
if (Liveness.isLive(Loc, BlkExpr)) {
RVal X = I.getData();
Ted Kremenek
committed
if (isa<lval::DeclVal>(X)) {
lval::DeclVal LV = cast<lval::DeclVal>(X);
DRoots.push_back(LV.getDecl());
Ted Kremenek
committed
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
SI != SE; ++SI) {
LSymbols.insert(*SI);
}
else {
RVal X = I.getData();
Ted Kremenek
committed
if (X.isUndef() && cast<UndefinedVal>(X).getData())
continue;
NewSt.Env = EnvMgr.RemoveBlkExpr(NewSt.Env, BlkExpr);
}
// Clean up the store.
DSymbols.clear();
NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness, DRoots,
LSymbols, DSymbols);
// Remove the dead symbols from the symbol tracker.
for (GRState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) {
SymbolID sym = I.getKey();
if (!LSymbols.count(sym)) {
DSymbols.insert(sym);
NewSt.ConstEq = CEFactory.Remove(NewSt.ConstEq, sym);
}
}
for (GRState::cne_iterator I = St->cne_begin(), E=St->cne_end(); I!=E;++I){
SymbolID sym = I.getKey();
if (!LSymbols.count(sym)) {
DSymbols.insert(sym);
NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, sym);
}
}
Ted Kremenek
committed
return getPersistentState(NewSt);
Ted Kremenek
committed
const GRState* GRStateManager::SetRVal(const GRState* St, LVal LV,
RVal V) {
Store OldStore = St->getStore();
Store NewStore = StMgr->SetRVal(OldStore, LV, V);
if (NewStore == OldStore)
return St;
NewSt.St = NewStore;
return getPersistentState(NewSt);
}
Ted Kremenek
committed
const GRState* GRStateManager::Unbind(const GRState* St, LVal LV) {
Store OldStore = St->getStore();
Store NewStore = StMgr->Remove(OldStore, LV);
if (NewStore == OldStore)
return St;
NewSt.St = NewStore;
return getPersistentState(NewSt);
const GRState* GRStateManager::AddNE(const GRState* St, SymbolID sym,
const llvm::APSInt& V) {
Ted Kremenek
committed
// First, retrieve the NE-set associated with the given symbol.
GRState::ConstNotEqTy::data_type* T = St->ConstNotEq.lookup(sym);
GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
Ted Kremenek
committed
// Now add V to the NE set.
Ted Kremenek
committed
S = ISetFactory.Add(S, &V);
// Create a new state with the old binding replaced.
NewSt.ConstNotEq = CNEFactory.Add(NewSt.ConstNotEq, sym, S);
Ted Kremenek
committed
// Get the persistent copy.
return getPersistentState(NewSt);
Ted Kremenek
committed
}
const GRState* GRStateManager::AddEQ(const GRState* St, SymbolID sym,
const llvm::APSInt& V) {
Ted Kremenek
committed
// Create a new state with the old binding replaced.
NewSt.ConstEq = CEFactory.Add(NewSt.ConstEq, sym, &V);
Ted Kremenek
committed
// Get the persistent copy.
return getPersistentState(NewSt);
Ted Kremenek
committed
}
const GRState* GRStateManager::getInitialState() {
Ted Kremenek
committed
Ted Kremenek
committed
GRState StateImpl(EnvMgr.getInitialEnvironment(), StMgr->getInitialStore(),
GDMFactory.GetEmptyMap(), CNEFactory.GetEmptyMap(),
CEFactory.GetEmptyMap());
return getPersistentState(StateImpl);
}
const GRState* GRStateManager::getPersistentState(GRState& State) {
llvm::FoldingSetNodeID ID;
State.Profile(ID);
void* InsertPos;
if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
return I;
GRState* I = (GRState*) Alloc.Allocate<GRState>();
new (I) GRState(State);
StateSet.InsertNode(I, InsertPos);
return I;
}
void GRState::printDOT(std::ostream& Out,
Printer** Beg, Printer** End) const {
print(Out, Beg, End, "\\l", "\\|");
void GRState::printStdErr(Printer** Beg, Printer** End) const {
print(*llvm::cerr, Beg, End);
}
void GRState::print(std::ostream& Out, Printer** Beg, Printer** End,
const char* nl, const char* sep) const {
// Print Variable Bindings
bool isFirst = true;
for (vb_iterator I = vb_begin(), E = vb_end(); I != E; ++I) {
if (isFirst) isFirst = false;
Out << ' ' << I.getKey()->getName() << " : ";
I.getData().print(Out);
}
// Print Subexpression bindings.
isFirst = true;
for (seb_iterator I = seb_begin(), E = seb_end(); I != E; ++I) {
if (isFirst) {
Out << nl << nl << "Sub-Expressions:" << nl;
isFirst = false;
}
Out << " (" << (void*) I.getKey() << ") ";
I.getKey()->printPretty(Out);
Out << " : ";
I.getData().print(Out);
}
// Print block-expression bindings.
isFirst = true;
for (beb_iterator I = beb_begin(), E = beb_end(); I != E; ++I) {
if (isFirst) {
Out << nl << nl << "Block-level Expressions:" << nl;
isFirst = false;
}
Out << " (" << (void*) I.getKey() << ") ";
I.getKey()->printPretty(Out);
Out << " : ";
I.getData().print(Out);
}
// Print equality constraints.
// FIXME: Make just another printer do this.
if (!ConstEq.isEmpty()) {
Out << nl << sep << "'==' constraints:";
for (ConstEqTy::iterator I = ConstEq.begin(),
E = ConstEq.end(); I!=E; ++I) {
Out << nl << " $" << I.getKey()
<< " : " << I.getData()->toString();
}
}
// Print != constraints.
// FIXME: Make just another printer do this.
if (!ConstNotEq.isEmpty()) {
Out << nl << sep << "'!=' constraints:";
for (ConstNotEqTy::iterator I = ConstNotEq.begin(),
EI = ConstNotEq.end(); I != EI; ++I) {
Out << nl << " $" << I.getKey() << " : ";
isFirst = true;
IntSetTy::iterator J = I.getData().begin(), EJ = I.getData().end();
for ( ; J != EJ; ++J) {
if (isFirst) isFirst = false;
else Out << ", ";
Out << (*J)->toString();
}
}
}
// Print checker-specific data.
for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
Ted Kremenek
committed
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Generic Data Map.
//===----------------------------------------------------------------------===//
void* const* GRState::FindGDM(void* K) const {
return GDM.lookup(K);
}
const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){
GRState::GenericDataMap M1 = St->getGDM();
GRState::GenericDataMap M2 = GDMFactory.Add(M1, Key, Data);
if (M1 == M2)
return St;
GRState NewSt = *St;
NewSt.GDM = M2;
return getPersistentState(NewSt);
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Queries.
//===----------------------------------------------------------------------===//
bool GRStateManager::isEqual(const GRState* state, Expr* Ex,
Ted Kremenek
committed
const llvm::APSInt& Y) {
RVal V = GetRVal(state, Ex);
if (lval::ConcreteInt* X = dyn_cast<lval::ConcreteInt>(&V))
return X->getValue() == Y;
if (nonlval::ConcreteInt* X = dyn_cast<nonlval::ConcreteInt>(&V))
return X->getValue() == Y;
if (nonlval::SymbolVal* X = dyn_cast<nonlval::SymbolVal>(&V))
return state->isEqual(X->getSymbol(), Y);
if (lval::SymbolVal* X = dyn_cast<lval::SymbolVal>(&V))
return state->isEqual(X->getSymbol(), Y);
return false;
}
bool GRStateManager::isEqual(const GRState* state, Expr* Ex,
Ted Kremenek
committed
uint64_t x) {
return isEqual(state, Ex, BasicVals.getValue(x, Ex->getType()));
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// "Assume" logic.
//===----------------------------------------------------------------------===//
const GRState* GRStateManager::Assume(const GRState* St, LVal Cond,
Ted Kremenek
committed
bool Assumption, bool& isFeasible) {
St = AssumeAux(St, Cond, Assumption, isFeasible);
return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
: St;
}
const GRState* GRStateManager::AssumeAux(const GRState* St, LVal Cond,
Ted Kremenek
committed
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
bool Assumption, bool& isFeasible) {
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this LVal.");
return St;
case lval::SymbolValKind:
if (Assumption)
return AssumeSymNE(St, cast<lval::SymbolVal>(Cond).getSymbol(),
BasicVals.getZeroWithPtrWidth(), isFeasible);
else
return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
BasicVals.getZeroWithPtrWidth(), isFeasible);
case lval::DeclValKind:
case lval::FuncValKind:
case lval::GotoLabelKind:
case lval::StringLiteralValKind:
isFeasible = Assumption;
return St;
case lval::FieldOffsetKind:
return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
Assumption, isFeasible);
case lval::ArrayOffsetKind:
return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
Assumption, isFeasible);
case lval::ConcreteIntKind: {
bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
return St;
}
}
}
const GRState* GRStateManager::Assume(const GRState* St, NonLVal Cond,
Ted Kremenek
committed
bool Assumption, bool& isFeasible) {
St = AssumeAux(St, Cond, Assumption, isFeasible);
return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
: St;
}
const GRState* GRStateManager::AssumeAux(const GRState* St, NonLVal Cond,
Ted Kremenek
committed
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
bool Assumption, bool& isFeasible) {
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this NonLVal.");
return St;
case nonlval::SymbolValKind: {
nonlval::SymbolVal& SV = cast<nonlval::SymbolVal>(Cond);
SymbolID sym = SV.getSymbol();
if (Assumption)
return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
isFeasible);
else
return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
isFeasible);
}
case nonlval::SymIntConstraintValKind:
return
AssumeSymInt(St, Assumption,
cast<nonlval::SymIntConstraintVal>(Cond).getConstraint(),
isFeasible);
case nonlval::ConcreteIntKind: {
bool b = cast<nonlval::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
return St;
}
case nonlval::LValAsIntegerKind: {
return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
Assumption, isFeasible);
}
}
}
Ted Kremenek
committed
const GRState* GRStateManager::AssumeSymInt(const GRState* St,
Ted Kremenek
committed
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
bool Assumption,
const SymIntConstraint& C,
bool& isFeasible) {
switch (C.getOpcode()) {
default:
// No logic yet for other operators.
isFeasible = true;
return St;
case BinaryOperator::EQ:
if (Assumption)
return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
else
return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
case BinaryOperator::NE:
if (Assumption)
return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
else
return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
case BinaryOperator::GE:
if (Assumption)
return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
else
return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
case BinaryOperator::LE:
if (Assumption)
return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
else
return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
}
}
//===----------------------------------------------------------------------===//
// FIXME: This should go into a plug-in constraint engine.
//===----------------------------------------------------------------------===//
const GRState*
GRStateManager::AssumeSymNE(const GRState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
Ted Kremenek
committed
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = St->getSymVal(sym)) {
isFeasible = *X != V;
return St;
}
// Second, determine if sym != V.
if (St->isNotEqual(sym, V)) {
isFeasible = true;
return St;
}
// If we reach here, sym is not a constant and we don't know if it is != V.
// Make that assumption.
isFeasible = true;
return AddNE(St, sym, V);
}
const GRState*
GRStateManager::AssumeSymEQ(const GRState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
Ted Kremenek
committed
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = St->getSymVal(sym)) {
isFeasible = *X == V;
return St;
}
// Second, determine if sym != V.
if (St->isNotEqual(sym, V)) {
isFeasible = false;
return St;
}
// If we reach here, sym is not a constant and we don't know if it is == V.
// Make that assumption.
isFeasible = true;
return AddEQ(St, sym, V);
}
const GRState*
GRStateManager::AssumeSymLT(const GRState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
Ted Kremenek
committed
Ted Kremenek
committed
// FIXME: For now have assuming x < y be the same as assuming sym != V;
return AssumeSymNE(St, sym, V, isFeasible);
}
const GRState*
GRStateManager::AssumeSymGT(const GRState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
// FIXME: For now have assuming x > y be the same as assuming sym != V;
return AssumeSymNE(St, sym, V, isFeasible);
}
const GRState*
GRStateManager::AssumeSymGE(const GRState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
// FIXME: Primitive logic for now. Only reject a path if the value of
// sym is a constant X and !(X >= V).
if (const llvm::APSInt* X = St->getSymVal(sym)) {
isFeasible = *X >= V;
return St;
Ted Kremenek
committed
}
Ted Kremenek
committed
isFeasible = true;
return St;
Ted Kremenek
committed
}
Ted Kremenek
committed
const GRState*
GRStateManager::AssumeSymLE(const GRState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
// FIXME: Primitive logic for now. Only reject a path if the value of
// sym is a constant X and !(X <= V).
if (const llvm::APSInt* X = St->getSymVal(sym)) {
isFeasible = *X <= V;
return St;
}
isFeasible = true;
return St;
}