//===-- 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;
ExprBuilder::ExprBuilder() {
}
ExprBuilder::~ExprBuilder() {
}
namespace {
class DefaultExprBuilder : public ExprBuilder {
virtual ref<Expr> Constant(const llvm::APInt &Value) {
return ConstantExpr::alloc(Value);
}
virtual ref<Expr> NotOptimized(const ref<Expr> &Index) {
return NotOptimizedExpr::alloc(Index);
}
virtual ref<Expr> Read(const UpdateList &Updates,
const ref<Expr> &Index) {
return ReadExpr::alloc(Updates, Index);
}
virtual ref<Expr> Select(const ref<Expr> &Cond,
const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SelectExpr::alloc(Cond, LHS, RHS);
}
virtual ref<Expr> Concat(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return ConcatExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Extract(const ref<Expr> &LHS,
unsigned Offset, Expr::Width W) {
return ExtractExpr::alloc(LHS, Offset, W);
}
virtual ref<Expr> ZExt(const ref<Expr> &LHS, Expr::Width W) {
return ZExtExpr::alloc(LHS, W);
}
virtual ref<Expr> SExt(const ref<Expr> &LHS, Expr::Width W) {
return SExtExpr::alloc(LHS, W);
}
virtual ref<Expr> Add(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return AddExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Sub(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SubExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Mul(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return MulExpr::alloc(LHS, RHS);
}
virtual ref<Expr> UDiv(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return UDivExpr::alloc(LHS, RHS);
}
virtual ref<Expr> SDiv(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SDivExpr::alloc(LHS, RHS);
}
virtual ref<Expr> URem(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return URemExpr::alloc(LHS, RHS);
}
virtual ref<Expr> SRem(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SRemExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Not(const ref<Expr> &LHS) {
return NotExpr::alloc(LHS);
}
virtual ref<Expr> And(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return AndExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Or(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return OrExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Xor(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return XorExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Shl(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return ShlExpr::alloc(LHS, RHS);
}
virtual ref<Expr> LShr(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return LShrExpr::alloc(LHS, RHS);
}
virtual ref<Expr> AShr(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return AShrExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Eq(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return EqExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Ne(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return NeExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Ult(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return UltExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Ule(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return UleExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Ugt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return UgtExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Uge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return UgeExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Slt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SltExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Sle(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SleExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Sgt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SgtExpr::alloc(LHS, RHS);
}
virtual ref<Expr> Sge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return SgeExpr::alloc(LHS, RHS);
}
};
/// ChainedBuilder - Helper class for construct specialized expression
/// builders, which implements (non-virtual) methods which forward to a base
/// expression builder, for all expressions.
class ChainedBuilder {
protected:
/// Builder - The builder that this specialized builder is contained
/// within. Provided for convenience to clients.
ExprBuilder *Builder;
/// Base - The base builder class for constructing expressions.
ExprBuilder *Base;
public:
ChainedBuilder(ExprBuilder *_Builder, ExprBuilder *_Base)
: Builder(_Builder), Base(_Base) {}
~ChainedBuilder() { delete Base; }
ref<Expr> Constant(const llvm::APInt &Value) {
return Base->Constant(Value);
}
ref<Expr> NotOptimized(const ref<Expr> &Index) {
return Base->NotOptimized(Index);
}
ref<Expr> Read(const UpdateList &Updates,
const ref<Expr> &Index) {
return Base->Read(Updates, Index);
}
ref<Expr> Select(const ref<Expr> &Cond,
const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Select(Cond, LHS, RHS);
}
ref<Expr> Concat(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Concat(LHS, RHS);
}
ref<Expr> Extract(const ref<Expr> &LHS,
unsigned Offset, Expr::Width W) {
return Base->Extract(LHS, Offset, W);
}
ref<Expr> ZExt(const ref<Expr> &LHS, Expr::Width W) {
return Base->ZExt(LHS, W);
}
ref<Expr> SExt(const ref<Expr> &LHS, Expr::Width W) {
return Base->SExt(LHS, W);
}
ref<Expr> Add(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Add(LHS, RHS);
}
ref<Expr> Sub(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Sub(LHS, RHS);
}
ref<Expr> Mul(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Mul(LHS, RHS);
}
ref<Expr> UDiv(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->UDiv(LHS, RHS);
}
ref<Expr> SDiv(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->SDiv(LHS, RHS);
}
ref<Expr> URem(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->URem(LHS, RHS);
}
ref<Expr> SRem(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->SRem(LHS, RHS);
}
ref<Expr> Not(const ref<Expr> &LHS) {
return Base->Not(LHS);
}
ref<Expr> And(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->And(LHS, RHS);
}
ref<Expr> Or(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Or(LHS, RHS);
}
ref<Expr> Xor(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Xor(LHS, RHS);
}
ref<Expr> Shl(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Shl(LHS, RHS);
}
ref<Expr> LShr(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->LShr(LHS, RHS);
}
ref<Expr> AShr(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->AShr(LHS, RHS);
}
ref<Expr> Eq(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Eq(LHS, RHS);
}
ref<Expr> Ne(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Ne(LHS, RHS);
}
ref<Expr> Ult(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Ult(LHS, RHS);
}
ref<Expr> Ule(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Ule(LHS, RHS);
}
ref<Expr> Ugt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Ugt(LHS, RHS);
}
ref<Expr> Uge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Uge(LHS, RHS);
}
ref<Expr> Slt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Slt(LHS, RHS);
}
ref<Expr> Sle(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Sle(LHS, RHS);
}
ref<Expr> Sgt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Sgt(LHS, RHS);
}
ref<Expr> Sge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
return Base->Sge(LHS, RHS);
}
};
/// ConstantSpecializedExprBuilder - A base expression builder class which
/// handles dispatching to a helper class, based on whether the arguments are
/// constant or not.
///
/// The SpecializedBuilder template argument should be a helper class which
/// implements methods for all the expression construction functions. These
/// methods can be specialized to take [Non]ConstantExpr when desired.
template<typename SpecializedBuilder>
class ConstantSpecializedExprBuilder : public ExprBuilder {
SpecializedBuilder Builder;
public:
ConstantSpecializedExprBuilder(ExprBuilder *Base) : Builder(this, Base) {}
~ConstantSpecializedExprBuilder() {}
virtual ref<Expr> Constant(const llvm::APInt &Value) {
return Builder.Constant(Value);
}
virtual ref<Expr> NotOptimized(const ref<Expr> &Index) {
return Builder.NotOptimized(Index);
}
virtual ref<Expr> Read(const UpdateList &Updates,
const ref<Expr> &Index) {
// Roll back through writes when possible.
const UpdateNode *UN = Updates.head;
while (UN && Eq(Index, UN->index)->isFalse())
UN = UN->next;
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Index))
return Builder.Read(UpdateList(Updates.root, UN), CE);
return Builder.Read(UpdateList(Updates.root, UN), Index);
}
virtual ref<Expr> Select(const ref<Expr> &Cond,
const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Cond))
return CE->isTrue() ? LHS : RHS;
return Builder.Select(cast<NonConstantExpr>(Cond), LHS, RHS);
}
virtual ref<Expr> Concat(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Concat(RCE);
return Builder.Concat(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Concat(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Concat(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Extract(const ref<Expr> &LHS,
unsigned Offset, Expr::Width W) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(LHS))
return CE->Extract(Offset, W);
return Builder.Extract(cast<NonConstantExpr>(LHS), Offset, W);
}
virtual ref<Expr> ZExt(const ref<Expr> &LHS, Expr::Width W) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(LHS))
return CE->ZExt(W);
return Builder.ZExt(cast<NonConstantExpr>(LHS), W);
}
virtual ref<Expr> SExt(const ref<Expr> &LHS, Expr::Width W) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(LHS))
return CE->SExt(W);
return Builder.SExt(cast<NonConstantExpr>(LHS), W);
}
virtual ref<Expr> Add(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Add(RCE);
return Builder.Add(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Add(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Add(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Sub(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Sub(RCE);
return Builder.Sub(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Sub(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Sub(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Mul(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Mul(RCE);
return Builder.Mul(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Mul(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Mul(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> UDiv(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->UDiv(RCE);
return Builder.UDiv(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.UDiv(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.UDiv(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> SDiv(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->SDiv(RCE);
return Builder.SDiv(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.SDiv(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.SDiv(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> URem(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->URem(RCE);
return Builder.URem(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.URem(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.URem(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> SRem(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->SRem(RCE);
return Builder.SRem(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.SRem(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.SRem(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Not(const ref<Expr> &LHS) {
// !!X ==> X
if (NotExpr *DblNot = dyn_cast<NotExpr>(LHS))
return DblNot->getKid(0);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(LHS))
return CE->Not();
return Builder.Not(cast<NonConstantExpr>(LHS));
}
virtual ref<Expr> And(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->And(RCE);
return Builder.And(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.And(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.And(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Or(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Or(RCE);
return Builder.Or(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Or(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Or(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Xor(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Xor(RCE);
return Builder.Xor(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Xor(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Xor(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Shl(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Shl(RCE);
return Builder.Shl(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Shl(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Shl(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> LShr(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->LShr(RCE);
return Builder.LShr(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.LShr(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.LShr(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> AShr(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->AShr(RCE);
return Builder.AShr(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.AShr(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.AShr(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Eq(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Eq(RCE);
return Builder.Eq(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Eq(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Eq(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Ne(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Ne(RCE);
return Builder.Ne(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Ne(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Ne(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Ult(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Ult(RCE);
return Builder.Ult(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Ult(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Ult(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Ule(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Ule(RCE);
return Builder.Ule(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Ule(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Ule(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Ugt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Ugt(RCE);
return Builder.Ugt(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Ugt(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Ugt(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Uge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Uge(RCE);
return Builder.Uge(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Uge(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Uge(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Slt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Slt(RCE);
return Builder.Slt(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Slt(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Slt(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Sle(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Sle(RCE);
return Builder.Sle(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Sle(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Sle(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Sgt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Sgt(RCE);
return Builder.Sgt(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Sgt(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Sgt(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
virtual ref<Expr> Sge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
if (ConstantExpr *LCE = dyn_cast<ConstantExpr>(LHS)) {
if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS))
return LCE->Sge(RCE);
return Builder.Sge(LCE, cast<NonConstantExpr>(RHS));
} else if (ConstantExpr *RCE = dyn_cast<ConstantExpr>(RHS)) {
return Builder.Sge(cast<NonConstantExpr>(LHS), RCE);
}
return Builder.Sge(cast<NonConstantExpr>(LHS),
cast<NonConstantExpr>(RHS));
}
};
class ConstantFoldingBuilder :
public ChainedBuilder {
public:
ConstantFoldingBuilder(ExprBuilder *Builder, ExprBuilder *Base)
: ChainedBuilder(Builder, Base) {}
ref<Expr> Add(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
// 0 + X ==> X
if (LHS->isZero())
return RHS;
switch (RHS->getKind()) {
default: break;
case Expr::Add: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// C_0 + (C_1 + X) ==> (C_0 + C1) + X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Add(LHS->Add(CE), BE->right);
// C_0 + (X + C_1) ==> (C_0 + C1) + X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Add(LHS->Add(CE), BE->left);
break;
}
case Expr::Sub: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// C_0 + (C_1 - X) ==> (C_0 + C1) - X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Sub(LHS->Add(CE), BE->right);
// C_0 + (X - C_1) ==> (C_0 - C1) + X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Add(LHS->Sub(CE), BE->left);
break;
}
}
return Base->Add(LHS, RHS);
}
ref<Expr> Add(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return Add(RHS, LHS);
}
ref<Expr> Add(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
switch (LHS->getKind()) {
default: break;
case Expr::Add: {
BinaryExpr *BE = cast<BinaryExpr>(LHS);
// (X + Y) + Z ==> X + (Y + Z)
return Builder->Add(BE->left,
Builder->Add(BE->right, RHS));
}
case Expr::Sub: {
BinaryExpr *BE = cast<BinaryExpr>(LHS);
// (X - Y) + Z ==> X + (Z - Y)
return Builder->Add(BE->left,
Builder->Sub(RHS, BE->right));
}
}
switch (RHS->getKind()) {
default: break;
case Expr::Add: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// X + (C_0 + Y) ==> C_0 + (X + Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Add(CE, Builder->Add(LHS, BE->right));
// X + (Y + C_0) ==> C_0 + (X + Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Add(CE, Builder->Add(LHS, BE->left));
break;
}
case Expr::Sub: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// X + (C_0 - Y) ==> C_0 + (X - Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Add(CE, Builder->Sub(LHS, BE->right));
// X + (Y - C_0) ==> -C_0 + (X + Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Add(CE->Neg(), Builder->Add(LHS, BE->left));
break;
}
}
return Base->Add(LHS, RHS);
}
ref<Expr> Sub(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
switch (RHS->getKind()) {
default: break;
case Expr::Add: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// C_0 - (C_1 + X) ==> (C_0 - C1) - X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Sub(LHS->Sub(CE), BE->right);
// C_0 - (X + C_1) ==> (C_0 + C1) + X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Sub(LHS->Sub(CE), BE->left);
break;
}
case Expr::Sub: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// C_0 - (C_1 - X) ==> (C_0 - C1) + X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Add(LHS->Sub(CE), BE->right);
// C_0 - (X - C_1) ==> (C_0 + C1) - X
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Sub(LHS->Add(CE), BE->left);
break;
}
}
return Base->Sub(LHS, RHS);
}
ref<Expr> Sub(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
// X - C_0 ==> -C_0 + X
return Add(RHS->Neg(), LHS);
}
ref<Expr> Sub(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
switch (LHS->getKind()) {
default: break;
case Expr::Add: {
BinaryExpr *BE = cast<BinaryExpr>(LHS);
// (X + Y) - Z ==> X + (Y - Z)
return Builder->Add(BE->left, Builder->Sub(BE->right, RHS));
}
case Expr::Sub: {
BinaryExpr *BE = cast<BinaryExpr>(LHS);
// (X - Y) - Z ==> X - (Y + Z)
return Builder->Sub(BE->left, Builder->Add(BE->right, RHS));
}
}
switch (RHS->getKind()) {
default: break;
case Expr::Add: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// X - (C + Y) ==> -C + (X - Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Add(CE->Neg(), Builder->Sub(LHS, BE->right));
// X - (Y + C) ==> -C + (X + Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Add(CE->Neg(), Builder->Sub(LHS, BE->left));
break;
}
case Expr::Sub: {
BinaryExpr *BE = cast<BinaryExpr>(RHS);
// X - (C - Y) ==> -C + (X + Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
return Builder->Add(CE->Neg(), Builder->Add(LHS, BE->right));
// X - (Y - C) ==> C + (X - Y)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
return Builder->Add(CE, Builder->Sub(LHS, BE->left));
break;
}
}
return Base->Sub(LHS, RHS);
}
ref<Expr> Mul(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
if (LHS->isZero())
return LHS;
if (LHS->isOne())
return RHS;
// FIXME: Unbalance nested muls, fold constants through
// {sub,add}-with-constant, etc.
return Base->Mul(LHS, RHS);
}
ref<Expr> Mul(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return Mul(RHS, LHS);
}
ref<Expr> Mul(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
return Base->Mul(LHS, RHS);
}
ref<Expr> And(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
if (LHS->isZero())
return LHS;
if (LHS->isAllOnes())
return RHS;
// FIXME: Unbalance nested ands, fold constants through
// {and,or}-with-constant, etc.
return Base->And(LHS, RHS);
}
ref<Expr> And(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return And(RHS, LHS);
}
ref<Expr> And(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
return Base->And(LHS, RHS);
}
ref<Expr> Or(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
if (LHS->isZero())
return RHS;
if (LHS->isAllOnes())
return LHS;
// FIXME: Unbalance nested ors, fold constants through
// {and,or}-with-constant, etc.
return Base->Or(LHS, RHS);
}
ref<Expr> Or(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return Or(RHS, LHS);
}
ref<Expr> Or(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
return Base->Or(LHS, RHS);
}
ref<Expr> Xor(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
if (LHS->isZero())
return RHS;
// FIXME: Unbalance nested ors, fold constants through
// {and,or}-with-constant, etc.
return Base->Xor(LHS, RHS);
}
ref<Expr> Xor(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return Xor(RHS, LHS);
}
ref<Expr> Xor(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
return Base->Xor(LHS, RHS);
}
ref<Expr> Eq(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
Expr::Width Width = LHS->getWidth();
if (Width == Expr::Bool) {
// true == X ==> X
if (LHS->isTrue())
return RHS;
// false == ... (not)
return Base->Not(RHS);
}
return Base->Eq(LHS, RHS);
}
ref<Expr> Eq(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return Eq(RHS, LHS);
}
ref<Expr> Eq(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
return Base->Eq(LHS, RHS);
}
};
typedef ConstantSpecializedExprBuilder<ConstantFoldingBuilder>
ConstantFoldingExprBuilder;
class SimplifyingBuilder : public ChainedBuilder {
public:
SimplifyingBuilder(ExprBuilder *Builder, ExprBuilder *Base)
: ChainedBuilder(Builder, Base) {}
ref<Expr> Eq(const ref<ConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
Expr::Width Width = LHS->getWidth();
if (Width == Expr::Bool) {
// true == X ==> X
if (LHS->isTrue())
return RHS;
// false == X (not)
return Base->Not(RHS);
}
return Base->Eq(LHS, RHS);
}
ref<Expr> Eq(const ref<NonConstantExpr> &LHS,
const ref<ConstantExpr> &RHS) {
return Eq(RHS, LHS);
}
ref<Expr> Eq(const ref<NonConstantExpr> &LHS,
const ref<NonConstantExpr> &RHS) {
// X == X ==> true
if (LHS == RHS)
return Builder->True();
return Base->Eq(LHS, RHS);
}
ref<Expr> Not(const ref<NonConstantExpr> &LHS) {
// Transform !(a or b) ==> !a and !b.
if (const OrExpr *OE = dyn_cast<OrExpr>(LHS))
return Builder->And(Builder->Not(OE->left),
Builder->Not(OE->right));
return Base->Not(LHS);
}
ref<Expr> Ne(const ref<Expr> &LHS, const ref<Expr> &RHS) {
// X != Y ==> !(X == Y)
return Builder->Not(Builder->Eq(LHS, RHS));
}
ref<Expr> Ugt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
// X u> Y ==> Y u< X
return Builder->Ult(RHS, LHS);
}
ref<Expr> Uge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
// X u>= Y ==> Y u<= X
return Builder->Ule(RHS, LHS);
}
ref<Expr> Sgt(const ref<Expr> &LHS, const ref<Expr> &RHS) {
// X s> Y ==> Y s< X
return Builder->Slt(RHS, LHS);
}
ref<Expr> Sge(const ref<Expr> &LHS, const ref<Expr> &RHS) {
// X s>= Y ==> Y s<= X
return Builder->Sle(RHS, LHS);
}
};
typedef ConstantSpecializedExprBuilder<SimplifyingBuilder>
SimplifyingExprBuilder;
}
ExprBuilder *klee::createDefaultExprBuilder() {
return new DefaultExprBuilder();
}
ExprBuilder *klee::createConstantFoldingExprBuilder(ExprBuilder *Base) {
return new ConstantFoldingExprBuilder(Base);
}
ExprBuilder *klee::createSimplifyingExprBuilder(ExprBuilder *Base) {
return new SimplifyingExprBuilder(Base);
}