//===-- ExprVisitor.cpp ---------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "klee/Expr.h" #include "klee/util/ExprVisitor.h" #include "llvm/Support/CommandLine.h" namespace { llvm::cl::opt UseVisitorHash("use-visitor-hash", llvm::cl::desc("Use hash-consing during expr visitation."), llvm::cl::init(true)); } using namespace klee; ref ExprVisitor::visit(const ref &e) { if (!UseVisitorHash || isa(e)) { return visitActual(e); } else { visited_ty::iterator it = visited.find(e); if (it!=visited.end()) { return it->second; } else { ref res = visitActual(e); visited.insert(std::make_pair(e, res)); return res; } } } ref ExprVisitor::visitActual(const ref &e) { if (isa(e)) { return e; } else { Expr &ep = *e.get(); Action res = visitExpr(ep); switch(res.kind) { case Action::DoChildren: // continue with normal action break; case Action::SkipChildren: return e; case Action::ChangeTo: return res.argument; } switch(ep.getKind()) { case Expr::NotOptimized: res = visitNotOptimized(static_cast(ep)); break; case Expr::Read: res = visitRead(static_cast(ep)); break; case Expr::Select: res = visitSelect(static_cast(ep)); break; case Expr::Concat: res = visitConcat(static_cast(ep)); break; case Expr::Extract: res = visitExtract(static_cast(ep)); break; case Expr::ZExt: res = visitZExt(static_cast(ep)); break; case Expr::SExt: res = visitSExt(static_cast(ep)); break; case Expr::Add: res = visitAdd(static_cast(ep)); break; case Expr::Sub: res = visitSub(static_cast(ep)); break; case Expr::Mul: res = visitMul(static_cast(ep)); break; case Expr::UDiv: res = visitUDiv(static_cast(ep)); break; case Expr::SDiv: res = visitSDiv(static_cast(ep)); break; case Expr::URem: res = visitURem(static_cast(ep)); break; case Expr::SRem: res = visitSRem(static_cast(ep)); break; case Expr::And: res = visitAnd(static_cast(ep)); break; case Expr::Or: res = visitOr(static_cast(ep)); break; case Expr::Xor: res = visitXor(static_cast(ep)); break; case Expr::Shl: res = visitShl(static_cast(ep)); break; case Expr::LShr: res = visitLShr(static_cast(ep)); break; case Expr::AShr: res = visitAShr(static_cast(ep)); break; case Expr::Eq: res = visitEq(static_cast(ep)); break; case Expr::Ne: res = visitNe(static_cast(ep)); break; case Expr::Ult: res = visitUlt(static_cast(ep)); break; case Expr::Ule: res = visitUle(static_cast(ep)); break; case Expr::Ugt: res = visitUgt(static_cast(ep)); break; case Expr::Uge: res = visitUge(static_cast(ep)); break; case Expr::Slt: res = visitSlt(static_cast(ep)); break; case Expr::Sle: res = visitSle(static_cast(ep)); break; case Expr::Sgt: res = visitSgt(static_cast(ep)); break; case Expr::Sge: res = visitSge(static_cast(ep)); break; case Expr::Constant: default: assert(0 && "invalid expression kind"); } switch(res.kind) { default: assert(0 && "invalid kind"); case Action::DoChildren: { bool rebuild = false; ref e(&ep), kids[8]; unsigned count = ep.getNumKids(); for (unsigned i=0; i kid = ep.getKid(i); kids[i] = visit(kid); if (kids[i] != kid) rebuild = true; } if (rebuild) { e = ep.rebuild(kids); if (recursive) e = visit(e); } if (!isa(e)) { res = visitExprPost(*e.get()); if (res.kind==Action::ChangeTo) e = res.argument; } return e; } case Action::SkipChildren: return e; case Action::ChangeTo: return res.argument; } } } ExprVisitor::Action ExprVisitor::visitExpr(const Expr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitExprPost(const Expr&) { return Action::skipChildren(); } ExprVisitor::Action ExprVisitor::visitNotOptimized(const NotOptimizedExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitRead(const ReadExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSelect(const SelectExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitConcat(const ConcatExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitExtract(const ExtractExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitZExt(const ZExtExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSExt(const SExtExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitAdd(const AddExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSub(const SubExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitMul(const MulExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitUDiv(const UDivExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSDiv(const SDivExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitURem(const URemExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSRem(const SRemExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitAnd(const AndExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitOr(const OrExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitXor(const XorExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitShl(const ShlExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitLShr(const LShrExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitAShr(const AShrExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitEq(const EqExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitNe(const NeExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitUlt(const UltExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitUle(const UleExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitUgt(const UgtExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitUge(const UgeExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSlt(const SltExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSle(const SleExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSgt(const SgtExpr&) { return Action::doChildren(); } ExprVisitor::Action ExprVisitor::visitSge(const SgeExpr&) { return Action::doChildren(); }