9#include "klee/Config/config.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/Support/CommandLine.h"
25#define vc_bvBoolExtract IAMTHESPAWNOFSATAN
27#define vc_bvLeftShiftExpr IAMTHESPAWNOFSATAN
28#define vc_bvRightShiftExpr IAMTHESPAWNOFSATAN
30#define vc_bvVar32LeftShiftExpr IAMTHESPAWNOFSATAN
31#define vc_bvVar32RightShiftExpr IAMTHESPAWNOFSATAN
32#define vc_bvVar32DivByPowOfTwoExpr IAMTHESPAWNOFSATAN
33#define vc_bvCreateMemoryArray IAMTHESPAWNOFSATAN
34#define vc_bvReadMemoryArray IAMTHESPAWNOFSATAN
35#define vc_bvWriteToMemoryArray IAMTHESPAWNOFSATAN
47 UseConstructHash(
"use-construct-hash-stp",
48 llvm::cl::desc(
"Use hash-consing during STP query construction (default=true)"),
56STPArrayExprHash::~STPArrayExprHash() {
58 ::VCExpr array_expr = it->second;
68 ::VCExpr un_expr = it->second;
79 : vc(_vc), optimizeDivides(_optimizeDivides) {
83STPBuilder::~STPBuilder() {
95 ::Type t = (width==1) ? vc_boolType(
vc) : vc_bvType(
vc, width);
96 ::VCExpr res = vc_varExpr(
vc,
const_cast<char*
>(name), t);
103 ::Type t1 = vc_bvType(
vc, indexWidth);
104 ::Type t2 = vc_bvType(
vc, valueWidth);
105 ::Type t = vc_arrayType(
vc, t1, t2);
106 ::VCExpr res = vc_varExpr(
vc,
const_cast<char*
>(name), t);
114 return vc_trueExpr(
vc);
117 return vc_falseExpr(
vc);
129 return vc_bvConstExprFromInt(
vc, width, value);
132 return vc_bvConstExprFromLL(
vc, width, value);
139 for (width -= 64; width > 64; width -= 64)
140 expr = vc_bvConcatExpr(
vc, zero, expr);
141 return vc_bvConcatExpr(
vc,
bvConst64(width, 0), expr);
146 return vc_bvSignExtend(
vc,
bvConst64(64, value), width);
153 return vc_bvExtract(
vc, expr, top, bottom);
156 assert((vc_getBVLength(
vc, a) == vc_getBVLength(
vc, b)) &&
"a and b should be same type");
157 return vc_eqExpr(
vc, a, b);
162 unsigned width = vc_getBVLength(
vc, expr);
166 }
else if (shift>=width) {
169 return vc_bvConcatExpr(
vc,
177 unsigned width = vc_getBVLength(
vc, expr);
181 }
else if (shift>=width) {
186 return vc_bvConcatExpr(
vc,
194 unsigned &shiftBits) {
196 llvm::APInt sw(32, width);
197 shiftBits = sw.getActiveBits();
201 return vc_bvExtract(
vc, shift, shiftBits - 1, 0);
206 unsigned width = vc_getBVLength(
vc, expr);
209 unsigned shiftBits = 0;
214 for (
int i = width - 1; i >= 0; i--) {
221 vc_bvLtExpr(
vc, shift,
bvConst32(vc_getBVLength(
vc, shift), width));
223 res = vc_iteExpr(
vc, ex, res,
bvZero(width));
230 unsigned width = vc_getBVLength(
vc, expr);
233 unsigned shiftBits = 0;
238 for (
int i = width - 1; i >= 0; i--) {
246 vc_bvLtExpr(
vc, shift,
bvConst32(vc_getBVLength(
vc, shift), width));
247 res = vc_iteExpr(
vc, ex, res,
bvZero(width));
255 unsigned width = vc_getBVLength(
vc, expr);
257 unsigned shiftBits = 0;
270 for (
int i = width - 2; i >= 0; i--) {
277 vc_bvLtExpr(
vc, shift,
bvConst32(vc_getBVLength(
vc, shift), width));
278 res = vc_iteExpr(
vc, ex, res,
bvZero(width));
285 unsigned width = vc_getBVLength(
vc, expr);
289 }
else if (shift>=width) {
292 return vc_iteExpr(
vc,
312 for (
int j=63; j>=0; j--) {
313 uint64_t bit = 1LL << j;
315 if ((
add&bit) || (
sub&bit)) {
316 assert(!((
add&bit) && (
sub&bit)) &&
"invalid mult constants");
321 res = vc_bvPlusExpr(
vc, width, res, op);
327 res = vc_bvMinusExpr(
vc, width, res, op);
329 res = vc_bvUMinusExpr(
vc, op);
355 assert(width==32 &&
"can only compute udiv constants for 32-bit division");
359 uint32_t mprime, sh1, sh2;
370 ExprHandle n_minus_t1 = vc_bvMinusExpr(
vc, width, expr_n, t1 );
372 ExprHandle plus_t1 = vc_bvPlusExpr(
vc, width, shift_sh1, t1 );
393 assert(width==32 &&
"can only compute udiv constants for 32-bit division");
396 int32_t mprime, dsign, shpost;
402 int64_t mprime_64 = (int64_t)mprime;
404 ExprHandle expr_n_64 = vc_bvSignExtend(
vc, expr_n, 64 );
407 ExprHandle n_plus_mulsh = vc_bvPlusExpr(
vc, width, expr_n, mulsh );
411 ExprHandle extend_npm = vc_bvSignExtend(
vc, n_plus_mulsh, 64 );
413 ExprHandle shift_shpost = vc_bvExtract(
vc, shift_npm, 31, 0 );
421 ExprHandle q0 = vc_bvMinusExpr(
vc, width, shift_shpost, xsign_of_n );
424 ExprHandle q0_xor_dsign = vc_bvXorExpr(
vc, q0, expr_dsign );
425 ExprHandle res = vc_bvMinusExpr(
vc, width, q0_xor_dsign, expr_dsign );
440 std::string unique_name = root->
name + unique_id;
449 for (
unsigned i = 0, e = root->
size; i != e; ++i) {
450 ::VCExpr prev = array_expr;
451 array_expr = vc_writeExpr(
vc, prev,
493 if (!UseConstructHash || isa<ConstantExpr>(e)) {
500 *width_out = it->second.second;
501 return it->second.first;
504 if (!width_out) width_out = &width;
506 constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
517 if (!width_out) width_out = &width;
531 if (*width_out <= 32)
533 if (*width_out <= 64)
538 while (Tmp->getWidth() > 64) {
539 Tmp = Tmp->Extract(64, Tmp->getWidth()-64);
540 unsigned Width = std::min(64U, Tmp->getWidth());
542 Tmp->Extract(0, Width)->getZExtValue()),
568 return vc_iteExpr(
vc, cond, tExpr, fExpr);
575 for (
int i=numKids-2; i>=0; i--) {
589 return vc_bvExtract(
vc, src, ee->
offset + *width_out - 1, ee->
offset);
601 return vc_iteExpr(
vc, src,
bvOne(*width_out),
bvZero(*width_out));
603 return vc_bvConcatExpr(
vc,
bvZero(*width_out-srcWidth), src);
615 return vc_bvSignExtend(
vc, src, *width_out);
622 AddExpr *ae = cast<AddExpr>(e);
625 assert(*width_out!=1 &&
"uncanonicalized add");
626 return vc_bvPlusExpr(
vc, *width_out, left, right);
630 SubExpr *se = cast<SubExpr>(e);
633 assert(*width_out!=1 &&
"uncanonicalized sub");
634 return vc_bvMinusExpr(
vc, *width_out, left, right);
638 MulExpr *me = cast<MulExpr>(e);
640 assert(*width_out!=1 &&
"uncanonicalized mul");
642 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left))
648 return vc_bvMultExpr(
vc, *width_out, left, right);
652 UDivExpr *de = cast<UDivExpr>(e);
654 assert(*width_out!=1 &&
"uncanonicalized udiv");
656 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
664 if (*width_out == 32)
672 return vc_bvDivExpr(
vc, *width_out, left, right);
676 SDivExpr *de = cast<SDivExpr>(e);
678 assert(*width_out!=1 &&
"uncanonicalized sdiv");
680 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right))
683 if (divisor != llvm::APInt(CE->
getWidth(),1,
false ) &&
684 divisor != llvm::APInt(CE->
getWidth(), -1,
true ))
685 if (*width_out == 32)
692 return vc_sbvDivExpr(
vc, *width_out, left, right);
696 URemExpr *de = cast<URemExpr>(e);
698 assert(*width_out!=1 &&
"uncanonicalized urem");
700 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
709 return bvZero(*width_out);
711 return vc_bvConcatExpr(
vc,
712 bvZero(*width_out - bits),
721 if (*width_out == 32) {
724 ExprHandle rem = vc_bvMinusExpr(
vc, *width_out, left, quot_times_divisor );
732 return vc_bvModExpr(
vc, *width_out, left, right);
736 SRemExpr *de = cast<SRemExpr>(e);
739 assert(*width_out!=1 &&
"uncanonicalized srem");
744 uint64_t divisor = cre->asUInt64;
747 if( *width_out == 32 ) {
750 ExprHandle rem = vc_bvMinusExpr(
vc, *width_out, left, quot_times_divisor );
758 return vc_sbvRemExpr(
vc, *width_out, left, right);
767 return vc_notExpr(
vc, expr);
769 return vc_bvNotExpr(
vc, expr);
774 AndExpr *ae = cast<AndExpr>(e);
778 return vc_andExpr(
vc, left, right);
780 return vc_bvAndExpr(
vc, left, right);
785 OrExpr *oe = cast<OrExpr>(e);
789 return vc_orExpr(
vc, left, right);
791 return vc_bvOrExpr(
vc, left, right);
796 XorExpr *xe = cast<XorExpr>(e);
802 return vc_iteExpr(
vc, left,
805 return vc_bvXorExpr(
vc, left, right);
810 ShlExpr *se = cast<ShlExpr>(e);
812 assert(*width_out!=1 &&
"uncanonicalized shl");
814 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
824 LShrExpr *lse = cast<LShrExpr>(e);
826 assert(*width_out!=1 &&
"uncanonicalized lshr");
828 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
838 AShrExpr *ase = cast<AShrExpr>(e);
840 assert(*width_out!=1 &&
"uncanonicalized ashr");
842 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
856 EqExpr *ee = cast<EqExpr>(e);
860 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
863 return vc_notExpr(
vc, right);
865 return vc_iffExpr(
vc, left, right);
869 return vc_eqExpr(
vc, left, right);
874 UltExpr *ue = cast<UltExpr>(e);
877 assert(*width_out!=1 &&
"uncanonicalized ult");
879 return vc_bvLtExpr(
vc, left, right);
883 UleExpr *ue = cast<UleExpr>(e);
886 assert(*width_out!=1 &&
"uncanonicalized ule");
888 return vc_bvLeExpr(
vc, left, right);
892 SltExpr *se = cast<SltExpr>(e);
895 assert(*width_out!=1 &&
"uncanonicalized slt");
897 return vc_sbvLtExpr(
vc, left, right);
901 SleExpr *se = cast<SleExpr>(e);
904 assert(*width_out!=1 &&
"uncanonicalized sle");
906 return vc_sbvLeExpr(
vc, left, right);
919 assert(0 &&
"unhandled Expr type");
920 return vc_trueExpr(
vc);
#define add(name, handler, ret)
void vc_DeleteExpr(void *)
void hashArrayExpr(const Array *array, T &exp)
bool lookupUpdateNodeExpr(const UpdateNode *un, T &exp) const
void hashUpdateNodeExpr(const UpdateNode *un, T &exp)
UpdateNodeHash::const_iterator UpdateNodeHashConstIter
bool lookupArrayExpr(const Array *array, T &exp) const
ArrayHash::iterator ArrayHashIter
UpdateNodeHash _update_node_hash
Expr::Width getRange() const
bool isConstantArray() const
const std::vector< ref< ConstantExpr > > constantValues
Expr::Width getDomain() const
ref< Expr > getKid(unsigned i) const
unsigned getNumKids() const
bool isTrue() const
isTrue - Is this the true expression.
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
static ref< ConstantExpr > alloc(const llvm::APInt &v)
const llvm::APInt & getAPValue() const
uint64_t getZExtValue(unsigned bits=64) const
virtual Kind getKind() const =0
@ Sge
Not used in canonical form.
@ Ne
Not used in canonical form.
@ Ugt
Not used in canonical form.
@ Sgt
Not used in canonical form.
@ Uge
Not used in canonical form.
Class representing a one byte read from an array.
ExprHandle constructUDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d)
ExprHandle bvOne(unsigned width)
ExprHandle bvMinusOne(unsigned width)
ExprHandle eqExpr(ExprHandle a, ExprHandle b)
ExprHandle bvRightShift(ExprHandle expr, unsigned shift)
ExprHandle extractPartialShiftValue(ExprHandle shift, unsigned width, unsigned &shiftBits)
ExprHandle getInitialRead(const Array *os, unsigned index)
ExprHandle bvZExtConst(unsigned width, uint64_t value)
ExprHandle bvConst64(unsigned width, uint64_t value)
::VCExpr getArrayForUpdate(const Array *root, const UpdateNode *un)
ExprHandle constructAShrByConstant(ExprHandle expr, unsigned shift, ExprHandle isSigned)
ExprHandle constructSDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d)
::VCExpr buildVar(const char *name, unsigned width)
ExprHandle bvExtract(ExprHandle expr, unsigned top, unsigned bottom)
ExprHandle bvZero(unsigned width)
ExprHandle bvVarLeftShift(ExprHandle expr, ExprHandle shift)
STPArrayExprHash _arr_hash
::VCExpr getInitialArray(const Array *os)
ExprHandle bvLeftShift(ExprHandle expr, unsigned shift)
ExprHandle bvVarRightShift(ExprHandle expr, ExprHandle shift)
ExprHandle bvSExtConst(unsigned width, uint64_t value)
ExprHandle bvBoolExtract(ExprHandle expr, int bit)
ExprHandle construct(ref< Expr > e, int *width_out)
ExprHandle constructMulByConstant(ExprHandle expr, unsigned width, uint64_t x)
ExprHandle bvConst32(unsigned width, uint32_t value)
::VCExpr buildArray(const char *name, unsigned indexWidth, unsigned valueWidth)
STPBuilder(::VC _vc, bool _optimizeDivides=true)
ExprHandle constructActual(ref< Expr > e, int *width_out)
ExprHandle bvVarArithRightShift(ExprHandle expr, ExprHandle shift)
ExprHashMap< std::pair< ExprHandle, unsigned > > constructed
Class representing an if-then-else expression.
ref< UpdateNode > head
pointer to the most recent update node
Class representing a byte update of an array.
const ref< UpdateNode > next
uint64_t truncateToNBits(uint64_t x, unsigned N)
unsigned indexOfSingleBit(uint64_t x)
uint64_t isPowerOfTwo(uint64_t x)
uint64_t sub(uint64_t l, uint64_t r, unsigned inWidth)
uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth)
Statistic queryConstructs
void ComputeMultConstants64(uint64_t multiplicand, uint64_t &add, uint64_t &sub)
void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1, uint32_t &sh2)
void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign, int32_t &shpost)
llvm::cl::OptionCategory ExprCat