//===-- ExprBuilder.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/ExprBuilder.h" using namespace klee; namespace { class DefaultExprBuilder : public ExprBuilder { virtual ref Constant(uint64_t Value, Expr::Width W) { return ConstantExpr::alloc(Value, W); } virtual ref NotOptimized(const ref &Index) { return NotOptimizedExpr::alloc(Index); } virtual ref Read(const UpdateList &Updates, const ref &Index) { return ReadExpr::alloc(Updates, Index); } virtual ref Select(const ref &Cond, const ref &LHS, const ref &RHS) { return SelectExpr::alloc(Cond, LHS, RHS); } virtual ref Concat(const ref &LHS, const ref &RHS) { return ConcatExpr::alloc(LHS, RHS); } virtual ref Extract(const ref &LHS, unsigned Offset, Expr::Width W) { return ExtractExpr::alloc(LHS, Offset, W); } virtual ref ZExt(const ref &LHS, Expr::Width W) { return ZExtExpr::alloc(LHS, W); } virtual ref SExt(const ref &LHS, Expr::Width W) { return SExtExpr::alloc(LHS, W); } virtual ref Add(const ref &LHS, const ref &RHS) { return AddExpr::alloc(LHS, RHS); } virtual ref Sub(const ref &LHS, const ref &RHS) { return SubExpr::alloc(LHS, RHS); } virtual ref Mul(const ref &LHS, const ref &RHS) { return MulExpr::alloc(LHS, RHS); } virtual ref UDiv(const ref &LHS, const ref &RHS) { return UDivExpr::alloc(LHS, RHS); } virtual ref SDiv(const ref &LHS, const ref &RHS) { return SDivExpr::alloc(LHS, RHS); } virtual ref URem(const ref &LHS, const ref &RHS) { return URemExpr::alloc(LHS, RHS); } virtual ref SRem(const ref &LHS, const ref &RHS) { return SRemExpr::alloc(LHS, RHS); } virtual ref And(const ref &LHS, const ref &RHS) { return AndExpr::alloc(LHS, RHS); } virtual ref Or(const ref &LHS, const ref &RHS) { return OrExpr::alloc(LHS, RHS); } virtual ref Xor(const ref &LHS, const ref &RHS) { return XorExpr::alloc(LHS, RHS); } virtual ref Shl(const ref &LHS, const ref &RHS) { return ShlExpr::alloc(LHS, RHS); } virtual ref LShr(const ref &LHS, const ref &RHS) { return LShrExpr::alloc(LHS, RHS); } virtual ref AShr(const ref &LHS, const ref &RHS) { return AShrExpr::alloc(LHS, RHS); } virtual ref Eq(const ref &LHS, const ref &RHS) { return EqExpr::alloc(LHS, RHS); } virtual ref Ne(const ref &LHS, const ref &RHS) { return NeExpr::alloc(LHS, RHS); } virtual ref Ult(const ref &LHS, const ref &RHS) { return UltExpr::alloc(LHS, RHS); } virtual ref Ule(const ref &LHS, const ref &RHS) { return UleExpr::alloc(LHS, RHS); } virtual ref Ugt(const ref &LHS, const ref &RHS) { return UgtExpr::alloc(LHS, RHS); } virtual ref Uge(const ref &LHS, const ref &RHS) { return UgeExpr::alloc(LHS, RHS); } virtual ref Slt(const ref &LHS, const ref &RHS) { return SltExpr::alloc(LHS, RHS); } virtual ref Sle(const ref &LHS, const ref &RHS) { return SleExpr::alloc(LHS, RHS); } virtual ref Sgt(const ref &LHS, const ref &RHS) { return SgtExpr::alloc(LHS, RHS); } virtual ref Sge(const ref &LHS, const ref &RHS) { return SgeExpr::alloc(LHS, RHS); } }; class ConstantFoldingExprBuilder : public ExprBuilder { ExprBuilder *Base; public: ConstantFoldingExprBuilder(ExprBuilder *_Base) : Base(_Base) {} ~ConstantFoldingExprBuilder() { delete Base; } virtual ref Constant(uint64_t Value, Expr::Width W) { return Base->Constant(Value, W); } virtual ref NotOptimized(const ref &Index) { return Base->NotOptimized(Index); } virtual ref Read(const UpdateList &Updates, const ref &Index) { // Roll back through writes when possible. const UpdateNode *UN = Updates.head; while (UN && Eq(Index, UN->index)->isFalse()) UN = UN->next; return Base->Read(UpdateList(Updates.root, UN), Index); } virtual ref Select(const ref &Cond, const ref &LHS, const ref &RHS) { if (ConstantExpr *CE = dyn_cast(Cond)) return CE->isTrue() ? LHS : RHS; return Base->Select(Cond, LHS, RHS); } virtual ref Concat(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Concat(RCE); return Base->Concat(LHS, RHS); } virtual ref Extract(const ref &LHS, unsigned Offset, Expr::Width W) { if (ConstantExpr *CE = dyn_cast(LHS)) return CE->Extract(Offset, W); return Base->Extract(LHS, Offset, W); } virtual ref ZExt(const ref &LHS, Expr::Width W) { if (ConstantExpr *CE = dyn_cast(LHS)) return CE->ZExt(W); return Base->ZExt(LHS, W); } virtual ref SExt(const ref &LHS, Expr::Width W) { if (ConstantExpr *CE = dyn_cast(LHS)) return CE->SExt(W); return Base->SExt(LHS, W); } virtual ref Add(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Add(RCE); return Base->Add(LHS, RHS); } virtual ref Sub(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sub(RCE); return Base->Sub(LHS, RHS); } virtual ref Mul(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Mul(RCE); return Base->Mul(LHS, RHS); } virtual ref UDiv(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->UDiv(RCE); return Base->UDiv(LHS, RHS); } virtual ref SDiv(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->SDiv(RCE); return Base->SDiv(LHS, RHS); } virtual ref URem(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->URem(RCE); return Base->URem(LHS, RHS); } virtual ref SRem(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->SRem(RCE); return Base->SRem(LHS, RHS); } virtual ref And(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->And(RCE); return Base->And(LHS, RHS); } virtual ref Or(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Or(RCE); return Base->Or(LHS, RHS); } virtual ref Xor(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Xor(RCE); return Base->Xor(LHS, RHS); } virtual ref Shl(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Shl(RCE); return Base->Shl(LHS, RHS); } virtual ref LShr(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->LShr(RCE); return Base->LShr(LHS, RHS); } virtual ref AShr(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->AShr(RCE); return Base->AShr(LHS, RHS); } virtual ref Eq(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Eq(RCE); return Base->Eq(LHS, RHS); } virtual ref Ne(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ne(RCE); return Base->Ne(LHS, RHS); } virtual ref Ult(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ult(RCE); return Base->Ult(LHS, RHS); } virtual ref Ule(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ule(RCE); return Base->Ule(LHS, RHS); } virtual ref Ugt(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ugt(RCE); return Base->Ugt(LHS, RHS); } virtual ref Uge(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Uge(RCE); return Base->Uge(LHS, RHS); } virtual ref Slt(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Slt(RCE); return Base->Slt(LHS, RHS); } virtual ref Sle(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sle(RCE); return Base->Sle(LHS, RHS); } virtual ref Sgt(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sgt(RCE); return Base->Sgt(LHS, RHS); } virtual ref Sge(const ref &LHS, const ref &RHS) { if (ConstantExpr *LCE = dyn_cast(LHS)) if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sge(RCE); return Base->Sge(LHS, RHS); } }; class FoldingExprBuilder : public ExprBuilder { ExprBuilder *Base; public: FoldingExprBuilder(ExprBuilder *_Base) : Base(_Base) {} ~FoldingExprBuilder() { delete Base; } virtual ref Constant(uint64_t Value, Expr::Width W) { return Base->Constant(Value, W); } virtual ref NotOptimized(const ref &Index) { return Base->NotOptimized(Index); } virtual ref Read(const UpdateList &Updates, const ref &Index) { return Base->Read(Updates, Index); } virtual ref Select(const ref &Cond, const ref &LHS, const ref &RHS) { return Base->Select(Cond, LHS, RHS); } virtual ref Concat(const ref &LHS, const ref &RHS) { return Base->Concat(LHS, RHS); } virtual ref Extract(const ref &LHS, unsigned Offset, Expr::Width W) { return Base->Extract(LHS, Offset, W); } virtual ref ZExt(const ref &LHS, Expr::Width W) { return Base->ZExt(LHS, W); } virtual ref SExt(const ref &LHS, Expr::Width W) { return Base->SExt(LHS, W); } virtual ref Add(const ref &LHS, const ref &RHS) { return Base->Add(LHS, RHS); } virtual ref Sub(const ref &LHS, const ref &RHS) { return Base->Sub(LHS, RHS); } virtual ref Mul(const ref &LHS, const ref &RHS) { return Base->Mul(LHS, RHS); } virtual ref UDiv(const ref &LHS, const ref &RHS) { return Base->UDiv(LHS, RHS); } virtual ref SDiv(const ref &LHS, const ref &RHS) { return Base->SDiv(LHS, RHS); } virtual ref URem(const ref &LHS, const ref &RHS) { return Base->URem(LHS, RHS); } virtual ref SRem(const ref &LHS, const ref &RHS) { return Base->SRem(LHS, RHS); } virtual ref And(const ref &LHS, const ref &RHS) { return Base->And(LHS, RHS); } virtual ref Or(const ref &LHS, const ref &RHS) { return Base->Or(LHS, RHS); } virtual ref Xor(const ref &LHS, const ref &RHS) { return Base->Xor(LHS, RHS); } virtual ref Shl(const ref &LHS, const ref &RHS) { return Base->Shl(LHS, RHS); } virtual ref LShr(const ref &LHS, const ref &RHS) { return Base->LShr(LHS, RHS); } virtual ref AShr(const ref &LHS, const ref &RHS) { return Base->AShr(LHS, RHS); } virtual ref Eq(const ref &LHS, const ref &RHS) { return Base->Eq(LHS, RHS); } virtual ref Ne(const ref &LHS, const ref &RHS) { return Base->Ne(LHS, RHS); } virtual ref Ult(const ref &LHS, const ref &RHS) { return Base->Ult(LHS, RHS); } virtual ref Ule(const ref &LHS, const ref &RHS) { return Base->Ule(LHS, RHS); } virtual ref Ugt(const ref &LHS, const ref &RHS) { return Base->Ugt(LHS, RHS); } virtual ref Uge(const ref &LHS, const ref &RHS) { return Base->Uge(LHS, RHS); } virtual ref Slt(const ref &LHS, const ref &RHS) { return Base->Slt(LHS, RHS); } virtual ref Sle(const ref &LHS, const ref &RHS) { return Base->Sle(LHS, RHS); } virtual ref Sgt(const ref &LHS, const ref &RHS) { return Base->Sgt(LHS, RHS); } virtual ref Sge(const ref &LHS, const ref &RHS) { return Base->Sge(LHS, RHS); } }; } ExprBuilder *klee::createDefaultExprBuilder() { return new DefaultExprBuilder(); } ExprBuilder *klee::createConstantFoldingExprBuilder(ExprBuilder *Base) { return new ConstantFoldingExprBuilder(Base); } ExprBuilder *klee::createFoldingExprBuilder(ExprBuilder *Base) { return new FoldingExprBuilder(Base); }