9#include "klee/Config/config.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Support/CommandLine.h"
25llvm::cl::opt<bool> UseConstructHashZ3(
26 "use-construct-hash-z3",
27 llvm::cl::desc(
"Use hash-consing during Z3 query construction (default=true)"),
32bool Z3InterationLogOpen =
false;
39 llvm::errs() <<
"Z3SortHandle:\n" << ::Z3_sort_to_string(context, node)
43 llvm::errs() <<
"Z3ASTHandle:\n" << ::Z3_ast_to_string(context, as_ast())
47void custom_z3_error_handler(Z3_context ctx, Z3_error_code ec) {
48 ::Z3_string errorMsg =
49#ifdef HAVE_Z3_GET_ERROR_MSG_NEEDS_CONTEXT
51 Z3_get_error_msg(ctx, ec);
58 if (strcmp(errorMsg,
"canceled") == 0) {
62 llvm::errs() <<
"Error: Incorrect use of Z3. [" << ec <<
"] " << errorMsg
78 : autoClearConstructCache(autoClearConstructCache), z3LogInteractionFile(
"") {
79 if (z3LogInteractionFileArg)
80 this->z3LogInteractionFile = std::string(z3LogInteractionFileArg);
81 if (z3LogInteractionFile.length() > 0) {
83 z3LogInteractionFile.c_str());
84 assert(!Z3InterationLogOpen &&
"interaction log should not already be open");
85 Z3_open_log(z3LogInteractionFile.c_str());
86 Z3InterationLogOpen =
true;
89 Z3_config cfg = Z3_mk_config();
92 ctx = Z3_mk_context_rc(cfg);
94 Z3_set_error_handler(ctx, custom_z3_error_handler);
96 Z3_set_ast_print_mode(ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
100Z3Builder::~Z3Builder() {
109 Z3InterationLogOpen =
false;
125 unsigned valueWidth) {
129 Z3_symbol s = Z3_mk_string_symbol(
ctx,
const_cast<char *
>(name));
161 for (width -= 64; width > 64; width -= 64)
199 }
else if (shift >= width) {
214 }
else if (shift >= width) {
230 for (
int i = width - 1; i >= 0; i--) {
249 for (
int i = width - 1; i >= 0; i--) {
276 for (
int i = width - 2; i >= 0; i--) {
296 ::Z3_ast args[2] = {lhs, rhs};
305 ::Z3_ast args[2] = {lhs, rhs};
316 assert(Z3_get_sort_kind(
ctx, lhsSort) == Z3_get_sort_kind(
ctx, rhsSort) &&
317 "lhs and rhs sorts must match");
318 assert(Z3_get_sort_kind(
ctx, lhsSort) == Z3_BOOL_SORT &&
"args must have BOOL sort");
329 assert(src_width <= width &&
"attempted to extend longer data");
374 }
else if (shift >= width) {
396 std::string unique_name = root->
name + unique_id;
402 std::vector<Z3ASTHandle> array_assertions;
403 for (
unsigned i = 0, e = root->
size; i != e; ++i) {
409 assert(width_out == (
int)root->
getRange() &&
410 "Value doesn't match root range");
411 array_assertions.push_back(
453 if (!UseConstructHashZ3 || isa<ConstantExpr>(e)) {
460 *width_out = it->second.second;
461 return it->second.first;
467 constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
492 if (*width_out <= 32)
494 if (*width_out <= 64)
499 while (Tmp->getWidth() > 64) {
500 Tmp = Tmp->Extract(64, Tmp->getWidth() - 64);
501 unsigned Width = std::min(64U, Tmp->getWidth());
504 bvConst64(Width, Tmp->Extract(0, Width)->getZExtValue()),
530 return iteExpr(cond, tExpr, fExpr);
537 for (
int i = numKids - 2; i >= 0; i--) {
549 if (*width_out == 1) {
566 assert(*width_out > srcWidth &&
"Invalid width_out");
586 AddExpr *ae = cast<AddExpr>(e);
589 assert(*width_out != 1 &&
"uncanonicalized add");
591 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
597 SubExpr *se = cast<SubExpr>(e);
600 assert(*width_out != 1 &&
"uncanonicalized sub");
602 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
608 MulExpr *me = cast<MulExpr>(e);
610 assert(*width_out != 1 &&
"uncanonicalized mul");
613 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
619 UDivExpr *de = cast<UDivExpr>(e);
621 assert(*width_out != 1 &&
"uncanonicalized udiv");
623 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
633 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
639 SDivExpr *de = cast<SDivExpr>(e);
641 assert(*width_out != 1 &&
"uncanonicalized sdiv");
644 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
650 URemExpr *de = cast<URemExpr>(e);
652 assert(*width_out != 1 &&
"uncanonicalized urem");
654 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
665 return bvZero(*width_out);
667 assert(*width_out > bits &&
"invalid width_out");
678 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
684 SRemExpr *de = cast<SRemExpr>(e);
687 assert(*width_out != 1 &&
"uncanonicalized srem");
692 assert(
getBVLength(result) ==
static_cast<unsigned>(*width_out) &&
701 if (*width_out == 1) {
709 AndExpr *ae = cast<AndExpr>(e);
712 if (*width_out == 1) {
720 OrExpr *oe = cast<OrExpr>(e);
723 if (*width_out == 1) {
724 return orExpr(left, right);
731 XorExpr *xe = cast<XorExpr>(e);
735 if (*width_out == 1) {
744 ShlExpr *se = cast<ShlExpr>(e);
746 assert(*width_out != 1 &&
"uncanonicalized shl");
748 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
758 LShrExpr *lse = cast<LShrExpr>(e);
760 assert(*width_out != 1 &&
"uncanonicalized lshr");
762 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
772 AShrExpr *ase = cast<AShrExpr>(e);
774 assert(*width_out != 1 &&
"uncanonicalized ashr");
776 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
790 EqExpr *ee = cast<EqExpr>(e);
793 if (*width_out == 1) {
794 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
803 return eqExpr(left, right);
808 UltExpr *ue = cast<UltExpr>(e);
811 assert(*width_out != 1 &&
"uncanonicalized ult");
817 UleExpr *ue = cast<UleExpr>(e);
820 assert(*width_out != 1 &&
"uncanonicalized ule");
826 SltExpr *se = cast<SltExpr>(e);
829 assert(*width_out != 1 &&
"uncanonicalized slt");
835 SleExpr *se = cast<SleExpr>(e);
838 assert(*width_out != 1 &&
"uncanonicalized sle");
853 assert(0 &&
"unhandled Expr type");
void hashArrayExpr(const Array *array, T &exp)
bool lookupUpdateNodeExpr(const UpdateNode *un, T &exp) const
void hashUpdateNodeExpr(const UpdateNode *un, T &exp)
bool lookupArrayExpr(const Array *array, T &exp) const
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
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.
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
virtual ~Z3ArrayExprHash()
Z3ASTHandle bvSignExtend(Z3ASTHandle src, unsigned width)
Z3ASTHandle bvXorExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3ASTHandle bvVarArithRightShift(Z3ASTHandle expr, Z3ASTHandle shift)
Z3ASTHandle iffExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3ASTHandle sbvLeExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3ASTHandle bvVarLeftShift(Z3ASTHandle expr, Z3ASTHandle shift)
Z3ASTHandle buildArray(const char *name, unsigned indexWidth, unsigned valueWidth)
Z3ASTHandle iteExpr(Z3ASTHandle condition, Z3ASTHandle whenTrue, Z3ASTHandle whenFalse)
Z3ASTHandle bvConst32(unsigned width, uint32_t value)
Z3ASTHandle getInitialArray(const Array *os)
Z3ASTHandle bvZExtConst(unsigned width, uint64_t value)
Z3ASTHandle bvLeExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3SortHandle getArraySort(Z3SortHandle domainSort, Z3SortHandle rangeSort)
Z3ASTHandle bvExtract(Z3ASTHandle expr, unsigned top, unsigned bottom)
Z3ASTHandle bvMinusOne(unsigned width)
Z3SortHandle getBvSort(unsigned width)
Z3ASTHandle bvNotExpr(Z3ASTHandle expr)
Z3ASTHandle bvOne(unsigned width)
Z3ASTHandle bvLtExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
unsigned getBVLength(Z3ASTHandle expr)
Z3ASTHandle eqExpr(Z3ASTHandle a, Z3ASTHandle b)
Z3ASTHandle bvBoolExtract(Z3ASTHandle expr, int bit)
Z3ASTHandle sbvLtExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3ASTHandle bvRightShift(Z3ASTHandle expr, unsigned shift)
Z3ASTHandle constructAShrByConstant(Z3ASTHandle expr, unsigned shift, Z3ASTHandle isSigned)
Z3ASTHandle writeExpr(Z3ASTHandle array, Z3ASTHandle index, Z3ASTHandle value)
std::unordered_map< const Array *, std::vector< Z3ASTHandle > > constant_array_assertions
Z3ASTHandle bvSExtConst(unsigned width, uint64_t value)
Z3ASTHandle getInitialRead(const Array *os, unsigned index)
Z3ASTHandle bvVarRightShift(Z3ASTHandle expr, Z3ASTHandle shift)
Z3ASTHandle bvOrExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
ExprHashMap< std::pair< Z3ASTHandle, unsigned > > constructed
std::string z3LogInteractionFile
Z3ASTHandle construct(ref< Expr > e, int *width_out)
Z3ASTHandle bvAndExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3ASTHandle bvZero(unsigned width)
Z3ASTHandle readExpr(Z3ASTHandle array, Z3ASTHandle index)
Z3ASTHandle bvConst64(unsigned width, uint64_t value)
Z3ASTHandle orExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3ASTHandle bvLeftShift(Z3ASTHandle expr, unsigned shift)
void clearConstructCache()
Z3ASTHandle andExpr(Z3ASTHandle lhs, Z3ASTHandle rhs)
Z3Builder(bool autoClearConstructCache, const char *z3LogInteractionFile)
Z3ASTHandle notExpr(Z3ASTHandle expr)
Z3ASTHandle constructActual(ref< Expr > e, int *width_out)
Z3ArrayExprHash _arr_hash
Z3ASTHandle getArrayForUpdate(const Array *root, const UpdateNode *un)
unsigned indexOfSingleBit(uint64_t x)
uint64_t isPowerOfTwo(uint64_t x)
uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth)
Statistic queryConstructs
void klee_message(const char *msg,...) __attribute__((format(printf
Z3NodeHandle< Z3_ast > Z3ASTHandle
llvm::cl::OptionCategory ExprCat
Z3NodeHandle< Z3_sort > Z3SortHandle