klee
Z3Builder.cpp
Go to the documentation of this file.
1//===-- Z3Builder.cpp ------------------------------------------*- C++ -*-====//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "klee/Config/config.h"
10#ifdef ENABLE_Z3
11#include "Z3Builder.h"
12
13#include "klee/ADT/Bits.h"
14#include "klee/Expr/Expr.h"
15#include "klee/Solver/Solver.h"
18
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Support/CommandLine.h"
21
22using namespace klee;
23
24namespace {
25llvm::cl::opt<bool> UseConstructHashZ3(
26 "use-construct-hash-z3",
27 llvm::cl::desc("Use hash-consing during Z3 query construction (default=true)"),
28 llvm::cl::init(true),
29 llvm::cl::cat(klee::ExprCat));
30
31// FIXME: This should be std::atomic<bool>. Need C++11 for that.
32bool Z3InterationLogOpen = false;
33}
34
35namespace klee {
36
37// Declared here rather than `Z3Builder.h` so they can be called in gdb.
38template <> void Z3NodeHandle<Z3_sort>::dump() {
39 llvm::errs() << "Z3SortHandle:\n" << ::Z3_sort_to_string(context, node)
40 << "\n";
41}
42template <> void Z3NodeHandle<Z3_ast>::dump() {
43 llvm::errs() << "Z3ASTHandle:\n" << ::Z3_ast_to_string(context, as_ast())
44 << "\n";
45}
46
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
50 // Z3 > 4.4.1
51 Z3_get_error_msg(ctx, ec);
52#else
53 // Z3 4.4.1
54 Z3_get_error_msg(ec);
55#endif
56 // FIXME: This is kind of a hack. The value comes from the enum
57 // Z3_CANCELED_MSG but this isn't currently exposed by Z3's C API
58 if (strcmp(errorMsg, "canceled") == 0) {
59 // Solver timeout is not a fatal error
60 return;
61 }
62 llvm::errs() << "Error: Incorrect use of Z3. [" << ec << "] " << errorMsg
63 << "\n";
64 // NOTE: The current implementation of `Z3_close_log()` can be safely
65 // called even if the log isn't open.
66 Z3_close_log();
67 abort();
68}
69
71
73 _update_node_hash.clear();
74 _array_hash.clear();
75}
76
77Z3Builder::Z3Builder(bool autoClearConstructCache, const char* z3LogInteractionFileArg)
78 : autoClearConstructCache(autoClearConstructCache), z3LogInteractionFile("") {
79 if (z3LogInteractionFileArg)
80 this->z3LogInteractionFile = std::string(z3LogInteractionFileArg);
81 if (z3LogInteractionFile.length() > 0) {
82 klee_message("Logging Z3 API interaction to \"%s\"",
83 z3LogInteractionFile.c_str());
84 assert(!Z3InterationLogOpen && "interaction log should not already be open");
85 Z3_open_log(z3LogInteractionFile.c_str());
86 Z3InterationLogOpen = true;
87 }
88 // FIXME: Should probably let the client pass in a Z3_config instead
89 Z3_config cfg = Z3_mk_config();
90 // It is very important that we ask Z3 to let us manage memory so that
91 // we are able to cache expressions and sorts.
92 ctx = Z3_mk_context_rc(cfg);
93 // Make sure we handle any errors reported by Z3.
94 Z3_set_error_handler(ctx, custom_z3_error_handler);
95 // When emitting Z3 expressions make them SMT-LIBv2 compliant
96 Z3_set_ast_print_mode(ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
97 Z3_del_config(cfg);
98}
99
100Z3Builder::~Z3Builder() {
101 // Clear caches so exprs/sorts gets freed before the destroying context
102 // they aren associated with.
106 Z3_del_context(ctx);
107 if (z3LogInteractionFile.length() > 0) {
108 Z3_close_log();
109 Z3InterationLogOpen = false;
110 }
111}
112
113Z3SortHandle Z3Builder::getBvSort(unsigned width) {
114 // FIXME: cache these
115 return Z3SortHandle(Z3_mk_bv_sort(ctx, width), ctx);
116}
117
119 Z3SortHandle rangeSort) {
120 // FIXME: cache these
121 return Z3SortHandle(Z3_mk_array_sort(ctx, domainSort, rangeSort), ctx);
122}
123
124Z3ASTHandle Z3Builder::buildArray(const char *name, unsigned indexWidth,
125 unsigned valueWidth) {
126 Z3SortHandle domainSort = getBvSort(indexWidth);
127 Z3SortHandle rangeSort = getBvSort(valueWidth);
128 Z3SortHandle t = getArraySort(domainSort, rangeSort);
129 Z3_symbol s = Z3_mk_string_symbol(ctx, const_cast<char *>(name));
130 return Z3ASTHandle(Z3_mk_const(ctx, s, t), ctx);
131}
132
133Z3ASTHandle Z3Builder::getTrue() { return Z3ASTHandle(Z3_mk_true(ctx), ctx); }
134
135Z3ASTHandle Z3Builder::getFalse() { return Z3ASTHandle(Z3_mk_false(ctx), ctx); }
136
137Z3ASTHandle Z3Builder::bvOne(unsigned width) { return bvZExtConst(width, 1); }
138
139Z3ASTHandle Z3Builder::bvZero(unsigned width) { return bvZExtConst(width, 0); }
140
141Z3ASTHandle Z3Builder::bvMinusOne(unsigned width) {
142 return bvSExtConst(width, (int64_t)-1);
143}
144
145Z3ASTHandle Z3Builder::bvConst32(unsigned width, uint32_t value) {
146 Z3SortHandle t = getBvSort(width);
147 return Z3ASTHandle(Z3_mk_unsigned_int(ctx, value, t), ctx);
148}
149
150Z3ASTHandle Z3Builder::bvConst64(unsigned width, uint64_t value) {
151 Z3SortHandle t = getBvSort(width);
152 return Z3ASTHandle(Z3_mk_unsigned_int64(ctx, value, t), ctx);
153}
154
155Z3ASTHandle Z3Builder::bvZExtConst(unsigned width, uint64_t value) {
156 if (width <= 64)
157 return bvConst64(width, value);
158
159 Z3ASTHandle expr = Z3ASTHandle(bvConst64(64, value), ctx);
160 Z3ASTHandle zero = Z3ASTHandle(bvConst64(64, 0), ctx);
161 for (width -= 64; width > 64; width -= 64)
162 expr = Z3ASTHandle(Z3_mk_concat(ctx, zero, expr), ctx);
163 return Z3ASTHandle(Z3_mk_concat(ctx, bvConst64(width, 0), expr), ctx);
164}
165
166Z3ASTHandle Z3Builder::bvSExtConst(unsigned width, uint64_t value) {
167 if (width <= 64)
168 return bvConst64(width, value);
169
170 Z3SortHandle t = getBvSort(width - 64);
171 if (value >> 63) {
172 Z3ASTHandle r = Z3ASTHandle(Z3_mk_int64(ctx, -1, t), ctx);
173 return Z3ASTHandle(Z3_mk_concat(ctx, r, bvConst64(64, value)), ctx);
174 }
175
176 Z3ASTHandle r = Z3ASTHandle(Z3_mk_int64(ctx, 0, t), ctx);
177 return Z3ASTHandle(Z3_mk_concat(ctx, r, bvConst64(64, value)), ctx);
178}
179
181 return Z3ASTHandle(Z3_mk_eq(ctx, bvExtract(expr, bit, bit), bvOne(1)), ctx);
182}
183
185 unsigned bottom) {
186 return Z3ASTHandle(Z3_mk_extract(ctx, top, bottom, expr), ctx);
187}
188
190 return Z3ASTHandle(Z3_mk_eq(ctx, a, b), ctx);
191}
192
193// logical right shift
194Z3ASTHandle Z3Builder::bvRightShift(Z3ASTHandle expr, unsigned shift) {
195 unsigned width = getBVLength(expr);
196
197 if (shift == 0) {
198 return expr;
199 } else if (shift >= width) {
200 return bvZero(width); // Overshift to zero
201 } else {
202 return Z3ASTHandle(
203 Z3_mk_concat(ctx, bvZero(shift), bvExtract(expr, width - 1, shift)),
204 ctx);
205 }
206}
207
208// logical left shift
209Z3ASTHandle Z3Builder::bvLeftShift(Z3ASTHandle expr, unsigned shift) {
210 unsigned width = getBVLength(expr);
211
212 if (shift == 0) {
213 return expr;
214 } else if (shift >= width) {
215 return bvZero(width); // Overshift to zero
216 } else {
217 return Z3ASTHandle(
218 Z3_mk_concat(ctx, bvExtract(expr, width - shift - 1, 0), bvZero(shift)),
219 ctx);
220 }
221}
222
223// left shift by a variable amount on an expression of the specified width
225 unsigned width = getBVLength(expr);
226 Z3ASTHandle res = bvZero(width);
227
228 // construct a big if-then-elif-elif-... with one case per possible shift
229 // amount
230 for (int i = width - 1; i >= 0; i--) {
231 res =
232 iteExpr(eqExpr(shift, bvConst32(width, i)), bvLeftShift(expr, i), res);
233 }
234
235 // If overshifting, shift to zero
236 Z3ASTHandle ex = bvLtExpr(shift, bvConst32(getBVLength(shift), width));
237 res = iteExpr(ex, res, bvZero(width));
238 return res;
239}
240
241// logical right shift by a variable amount on an expression of the specified
242// width
244 unsigned width = getBVLength(expr);
245 Z3ASTHandle res = bvZero(width);
246
247 // construct a big if-then-elif-elif-... with one case per possible shift
248 // amount
249 for (int i = width - 1; i >= 0; i--) {
250 res =
251 iteExpr(eqExpr(shift, bvConst32(width, i)), bvRightShift(expr, i), res);
252 }
253
254 // If overshifting, shift to zero
255 Z3ASTHandle ex = bvLtExpr(shift, bvConst32(getBVLength(shift), width));
256 res = iteExpr(ex, res, bvZero(width));
257 return res;
258}
259
260// arithmetic right shift by a variable amount on an expression of the specified
261// width
263 Z3ASTHandle shift) {
264 unsigned width = getBVLength(expr);
265
266 // get the sign bit to fill with
267 Z3ASTHandle signedBool = bvBoolExtract(expr, width - 1);
268
269 // start with the result if shifting by width-1
270 Z3ASTHandle res = constructAShrByConstant(expr, width - 1, signedBool);
271
272 // construct a big if-then-elif-elif-... with one case per possible shift
273 // amount
274 // XXX more efficient to move the ite on the sign outside all exprs?
275 // XXX more efficient to sign extend, right shift, then extract lower bits?
276 for (int i = width - 2; i >= 0; i--) {
277 res = iteExpr(eqExpr(shift, bvConst32(width, i)),
278 constructAShrByConstant(expr, i, signedBool), res);
279 }
280
281 // If overshifting, shift to zero
282 Z3ASTHandle ex = bvLtExpr(shift, bvConst32(getBVLength(shift), width));
283 res = iteExpr(ex, res, bvZero(width));
284 return res;
285}
286
288 return Z3ASTHandle(Z3_mk_not(ctx, expr), ctx);
289}
290
292 return Z3ASTHandle(Z3_mk_bvnot(ctx, expr), ctx);
293}
294
296 ::Z3_ast args[2] = {lhs, rhs};
297 return Z3ASTHandle(Z3_mk_and(ctx, 2, args), ctx);
298}
299
301 return Z3ASTHandle(Z3_mk_bvand(ctx, lhs, rhs), ctx);
302}
303
305 ::Z3_ast args[2] = {lhs, rhs};
306 return Z3ASTHandle(Z3_mk_or(ctx, 2, args), ctx);
307}
308
310 return Z3ASTHandle(Z3_mk_bvor(ctx, lhs, rhs), ctx);
311}
312
314 Z3SortHandle lhsSort = Z3SortHandle(Z3_get_sort(ctx, lhs), ctx);
315 Z3SortHandle rhsSort = Z3SortHandle(Z3_get_sort(ctx, rhs), ctx);
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");
319 return Z3ASTHandle(Z3_mk_iff(ctx, lhs, rhs), ctx);
320}
321
323 return Z3ASTHandle(Z3_mk_bvxor(ctx, lhs, rhs), ctx);
324}
325
327 unsigned src_width =
328 Z3_get_bv_sort_size(ctx, Z3SortHandle(Z3_get_sort(ctx, src), ctx));
329 assert(src_width <= width && "attempted to extend longer data");
330
331 return Z3ASTHandle(Z3_mk_sign_ext(ctx, width - src_width, src), ctx);
332}
333
335 Z3ASTHandle value) {
336 return Z3ASTHandle(Z3_mk_store(ctx, array, index, value), ctx);
337}
338
340 return Z3ASTHandle(Z3_mk_select(ctx, array, index), ctx);
341}
342
344 Z3ASTHandle whenFalse) {
345 return Z3ASTHandle(Z3_mk_ite(ctx, condition, whenTrue, whenFalse), ctx);
346}
347
348unsigned Z3Builder::getBVLength(Z3ASTHandle expr) {
349 return Z3_get_bv_sort_size(ctx, Z3SortHandle(Z3_get_sort(ctx, expr), ctx));
350}
351
353 return Z3ASTHandle(Z3_mk_bvult(ctx, lhs, rhs), ctx);
354}
355
357 return Z3ASTHandle(Z3_mk_bvule(ctx, lhs, rhs), ctx);
358}
359
361 return Z3ASTHandle(Z3_mk_bvslt(ctx, lhs, rhs), ctx);
362}
363
365 return Z3ASTHandle(Z3_mk_bvsle(ctx, lhs, rhs), ctx);
366}
367
369 Z3ASTHandle isSigned) {
370 unsigned width = getBVLength(expr);
371
372 if (shift == 0) {
373 return expr;
374 } else if (shift >= width) {
375 return bvZero(width); // Overshift to zero
376 } else {
377 // FIXME: Is this really the best way to interact with Z3?
378 return iteExpr(isSigned,
379 Z3ASTHandle(Z3_mk_concat(ctx, bvMinusOne(shift),
380 bvExtract(expr, width - 1, shift)),
381 ctx),
382 bvRightShift(expr, shift));
383 }
384}
385
387
388 assert(root);
389 Z3ASTHandle array_expr;
390 bool hashed = _arr_hash.lookupArrayExpr(root, array_expr);
391
392 if (!hashed) {
393 // Unique arrays by name, so we make sure the name is unique by
394 // using the size of the array hash as a counter.
395 std::string unique_id = llvm::utostr(_arr_hash._array_hash.size());
396 std::string unique_name = root->name + unique_id;
397
398 array_expr = buildArray(unique_name.c_str(), root->getDomain(),
399 root->getRange());
400
401 if (root->isConstantArray() && constant_array_assertions.count(root) == 0) {
402 std::vector<Z3ASTHandle> array_assertions;
403 for (unsigned i = 0, e = root->size; i != e; ++i) {
404 // construct(= (select i root) root->value[i]) to be asserted in
405 // Z3Solver.cpp
406 int width_out;
407 Z3ASTHandle array_value =
408 construct(root->constantValues[i], &width_out);
409 assert(width_out == (int)root->getRange() &&
410 "Value doesn't match root range");
411 array_assertions.push_back(
412 eqExpr(readExpr(array_expr, bvConst32(root->getDomain(), i)),
413 array_value));
414 }
415 constant_array_assertions[root] = std::move(array_assertions);
416 }
417
418 _arr_hash.hashArrayExpr(root, array_expr);
419 }
420
421 return (array_expr);
422}
423
424Z3ASTHandle Z3Builder::getInitialRead(const Array *root, unsigned index) {
425 return readExpr(getInitialArray(root), bvConst32(32, index));
426}
427
429 const UpdateNode *un) {
430 if (!un) {
431 return (getInitialArray(root));
432 } else {
433 // FIXME: This really needs to be non-recursive.
434 Z3ASTHandle un_expr;
435 bool hashed = _arr_hash.lookupUpdateNodeExpr(un, un_expr);
436
437 if (!hashed) {
438 un_expr = writeExpr(getArrayForUpdate(root, un->next.get()),
439 construct(un->index, 0), construct(un->value, 0));
440
441 _arr_hash.hashUpdateNodeExpr(un, un_expr);
442 }
443
444 return (un_expr);
445 }
446}
447
450Z3ASTHandle Z3Builder::construct(ref<Expr> e, int *width_out) {
451 // TODO: We could potentially use Z3_simplify() here
452 // to store simpler expressions.
453 if (!UseConstructHashZ3 || isa<ConstantExpr>(e)) {
454 return constructActual(e, width_out);
455 } else {
457 constructed.find(e);
458 if (it != constructed.end()) {
459 if (width_out)
460 *width_out = it->second.second;
461 return it->second.first;
462 } else {
463 int width;
464 if (!width_out)
465 width_out = &width;
466 Z3ASTHandle res = constructActual(e, width_out);
467 constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
468 return res;
469 }
470 }
471}
472
476 int width;
477 if (!width_out)
478 width_out = &width;
479
481
482 switch (e->getKind()) {
483 case Expr::Constant: {
484 ConstantExpr *CE = cast<ConstantExpr>(e);
485 *width_out = CE->getWidth();
486
487 // Coerce to bool if necessary.
488 if (*width_out == 1)
489 return CE->isTrue() ? getTrue() : getFalse();
490
491 // Fast path.
492 if (*width_out <= 32)
493 return bvConst32(*width_out, CE->getZExtValue(32));
494 if (*width_out <= 64)
495 return bvConst64(*width_out, CE->getZExtValue());
496
497 ref<ConstantExpr> Tmp = CE;
498 Z3ASTHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue());
499 while (Tmp->getWidth() > 64) {
500 Tmp = Tmp->Extract(64, Tmp->getWidth() - 64);
501 unsigned Width = std::min(64U, Tmp->getWidth());
502 Res = Z3ASTHandle(
503 Z3_mk_concat(ctx,
504 bvConst64(Width, Tmp->Extract(0, Width)->getZExtValue()),
505 Res),
506 ctx);
507 }
508 return Res;
509 }
510
511 // Special
512 case Expr::NotOptimized: {
513 NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
514 return construct(noe->src, width_out);
515 }
516
517 case Expr::Read: {
518 ReadExpr *re = cast<ReadExpr>(e);
519 assert(re && re->updates.root);
520 *width_out = re->updates.root->getRange();
521 return readExpr(getArrayForUpdate(re->updates.root, re->updates.head.get()),
522 construct(re->index, 0));
523 }
524
525 case Expr::Select: {
526 SelectExpr *se = cast<SelectExpr>(e);
527 Z3ASTHandle cond = construct(se->cond, 0);
528 Z3ASTHandle tExpr = construct(se->trueExpr, width_out);
529 Z3ASTHandle fExpr = construct(se->falseExpr, width_out);
530 return iteExpr(cond, tExpr, fExpr);
531 }
532
533 case Expr::Concat: {
534 ConcatExpr *ce = cast<ConcatExpr>(e);
535 unsigned numKids = ce->getNumKids();
536 Z3ASTHandle res = construct(ce->getKid(numKids - 1), 0);
537 for (int i = numKids - 2; i >= 0; i--) {
538 res =
539 Z3ASTHandle(Z3_mk_concat(ctx, construct(ce->getKid(i), 0), res), ctx);
540 }
541 *width_out = ce->getWidth();
542 return res;
543 }
544
545 case Expr::Extract: {
546 ExtractExpr *ee = cast<ExtractExpr>(e);
547 Z3ASTHandle src = construct(ee->expr, width_out);
548 *width_out = ee->getWidth();
549 if (*width_out == 1) {
550 return bvBoolExtract(src, ee->offset);
551 } else {
552 return bvExtract(src, ee->offset + *width_out - 1, ee->offset);
553 }
554 }
555
556 // Casting
557
558 case Expr::ZExt: {
559 int srcWidth;
560 CastExpr *ce = cast<CastExpr>(e);
561 Z3ASTHandle src = construct(ce->src, &srcWidth);
562 *width_out = ce->getWidth();
563 if (srcWidth == 1) {
564 return iteExpr(src, bvOne(*width_out), bvZero(*width_out));
565 } else {
566 assert(*width_out > srcWidth && "Invalid width_out");
567 return Z3ASTHandle(Z3_mk_concat(ctx, bvZero(*width_out - srcWidth), src),
568 ctx);
569 }
570 }
571
572 case Expr::SExt: {
573 int srcWidth;
574 CastExpr *ce = cast<CastExpr>(e);
575 Z3ASTHandle src = construct(ce->src, &srcWidth);
576 *width_out = ce->getWidth();
577 if (srcWidth == 1) {
578 return iteExpr(src, bvMinusOne(*width_out), bvZero(*width_out));
579 } else {
580 return bvSignExtend(src, *width_out);
581 }
582 }
583
584 // Arithmetic
585 case Expr::Add: {
586 AddExpr *ae = cast<AddExpr>(e);
587 Z3ASTHandle left = construct(ae->left, width_out);
588 Z3ASTHandle right = construct(ae->right, width_out);
589 assert(*width_out != 1 && "uncanonicalized add");
590 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvadd(ctx, left, right), ctx);
591 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
592 "width mismatch");
593 return result;
594 }
595
596 case Expr::Sub: {
597 SubExpr *se = cast<SubExpr>(e);
598 Z3ASTHandle left = construct(se->left, width_out);
599 Z3ASTHandle right = construct(se->right, width_out);
600 assert(*width_out != 1 && "uncanonicalized sub");
601 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvsub(ctx, left, right), ctx);
602 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
603 "width mismatch");
604 return result;
605 }
606
607 case Expr::Mul: {
608 MulExpr *me = cast<MulExpr>(e);
609 Z3ASTHandle right = construct(me->right, width_out);
610 assert(*width_out != 1 && "uncanonicalized mul");
611 Z3ASTHandle left = construct(me->left, width_out);
612 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvmul(ctx, left, right), ctx);
613 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
614 "width mismatch");
615 return result;
616 }
617
618 case Expr::UDiv: {
619 UDivExpr *de = cast<UDivExpr>(e);
620 Z3ASTHandle left = construct(de->left, width_out);
621 assert(*width_out != 1 && "uncanonicalized udiv");
622
623 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
624 if (CE->getWidth() <= 64) {
625 uint64_t divisor = CE->getZExtValue();
626 if (bits64::isPowerOfTwo(divisor))
627 return bvRightShift(left, bits64::indexOfSingleBit(divisor));
628 }
629 }
630
631 Z3ASTHandle right = construct(de->right, width_out);
632 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvudiv(ctx, left, right), ctx);
633 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
634 "width mismatch");
635 return result;
636 }
637
638 case Expr::SDiv: {
639 SDivExpr *de = cast<SDivExpr>(e);
640 Z3ASTHandle left = construct(de->left, width_out);
641 assert(*width_out != 1 && "uncanonicalized sdiv");
642 Z3ASTHandle right = construct(de->right, width_out);
643 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvsdiv(ctx, left, right), ctx);
644 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
645 "width mismatch");
646 return result;
647 }
648
649 case Expr::URem: {
650 URemExpr *de = cast<URemExpr>(e);
651 Z3ASTHandle left = construct(de->left, width_out);
652 assert(*width_out != 1 && "uncanonicalized urem");
653
654 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
655 if (CE->getWidth() <= 64) {
656 uint64_t divisor = CE->getZExtValue();
657
658 if (bits64::isPowerOfTwo(divisor)) {
659 // FIXME: This should be unsigned but currently needs to be signed to
660 // avoid signed-unsigned comparison in assert.
661 int bits = bits64::indexOfSingleBit(divisor);
662
663 // special case for modding by 1 or else we bvExtract -1:0
664 if (bits == 0) {
665 return bvZero(*width_out);
666 } else {
667 assert(*width_out > bits && "invalid width_out");
668 return Z3ASTHandle(Z3_mk_concat(ctx, bvZero(*width_out - bits),
669 bvExtract(left, bits - 1, 0)),
670 ctx);
671 }
672 }
673 }
674 }
675
676 Z3ASTHandle right = construct(de->right, width_out);
677 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvurem(ctx, left, right), ctx);
678 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
679 "width mismatch");
680 return result;
681 }
682
683 case Expr::SRem: {
684 SRemExpr *de = cast<SRemExpr>(e);
685 Z3ASTHandle left = construct(de->left, width_out);
686 Z3ASTHandle right = construct(de->right, width_out);
687 assert(*width_out != 1 && "uncanonicalized srem");
688 // LLVM's srem instruction says that the sign follows the dividend
689 // (``left``).
690 // Z3's C API says ``Z3_mk_bvsrem()`` does this so these seem to match.
691 Z3ASTHandle result = Z3ASTHandle(Z3_mk_bvsrem(ctx, left, right), ctx);
692 assert(getBVLength(result) == static_cast<unsigned>(*width_out) &&
693 "width mismatch");
694 return result;
695 }
696
697 // Bitwise
698 case Expr::Not: {
699 NotExpr *ne = cast<NotExpr>(e);
700 Z3ASTHandle expr = construct(ne->expr, width_out);
701 if (*width_out == 1) {
702 return notExpr(expr);
703 } else {
704 return bvNotExpr(expr);
705 }
706 }
707
708 case Expr::And: {
709 AndExpr *ae = cast<AndExpr>(e);
710 Z3ASTHandle left = construct(ae->left, width_out);
711 Z3ASTHandle right = construct(ae->right, width_out);
712 if (*width_out == 1) {
713 return andExpr(left, right);
714 } else {
715 return bvAndExpr(left, right);
716 }
717 }
718
719 case Expr::Or: {
720 OrExpr *oe = cast<OrExpr>(e);
721 Z3ASTHandle left = construct(oe->left, width_out);
722 Z3ASTHandle right = construct(oe->right, width_out);
723 if (*width_out == 1) {
724 return orExpr(left, right);
725 } else {
726 return bvOrExpr(left, right);
727 }
728 }
729
730 case Expr::Xor: {
731 XorExpr *xe = cast<XorExpr>(e);
732 Z3ASTHandle left = construct(xe->left, width_out);
733 Z3ASTHandle right = construct(xe->right, width_out);
734
735 if (*width_out == 1) {
736 // XXX check for most efficient?
737 return iteExpr(left, Z3ASTHandle(notExpr(right)), right);
738 } else {
739 return bvXorExpr(left, right);
740 }
741 }
742
743 case Expr::Shl: {
744 ShlExpr *se = cast<ShlExpr>(e);
745 Z3ASTHandle left = construct(se->left, width_out);
746 assert(*width_out != 1 && "uncanonicalized shl");
747
748 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
749 return bvLeftShift(left, (unsigned)CE->getLimitedValue());
750 } else {
751 int shiftWidth;
752 Z3ASTHandle amount = construct(se->right, &shiftWidth);
753 return bvVarLeftShift(left, amount);
754 }
755 }
756
757 case Expr::LShr: {
758 LShrExpr *lse = cast<LShrExpr>(e);
759 Z3ASTHandle left = construct(lse->left, width_out);
760 assert(*width_out != 1 && "uncanonicalized lshr");
761
762 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
763 return bvRightShift(left, (unsigned)CE->getLimitedValue());
764 } else {
765 int shiftWidth;
766 Z3ASTHandle amount = construct(lse->right, &shiftWidth);
767 return bvVarRightShift(left, amount);
768 }
769 }
770
771 case Expr::AShr: {
772 AShrExpr *ase = cast<AShrExpr>(e);
773 Z3ASTHandle left = construct(ase->left, width_out);
774 assert(*width_out != 1 && "uncanonicalized ashr");
775
776 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
777 unsigned shift = (unsigned)CE->getLimitedValue();
778 Z3ASTHandle signedBool = bvBoolExtract(left, *width_out - 1);
779 return constructAShrByConstant(left, shift, signedBool);
780 } else {
781 int shiftWidth;
782 Z3ASTHandle amount = construct(ase->right, &shiftWidth);
783 return bvVarArithRightShift(left, amount);
784 }
785 }
786
787 // Comparison
788
789 case Expr::Eq: {
790 EqExpr *ee = cast<EqExpr>(e);
791 Z3ASTHandle left = construct(ee->left, width_out);
792 Z3ASTHandle right = construct(ee->right, width_out);
793 if (*width_out == 1) {
794 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
795 if (CE->isTrue())
796 return right;
797 return notExpr(right);
798 } else {
799 return iffExpr(left, right);
800 }
801 } else {
802 *width_out = 1;
803 return eqExpr(left, right);
804 }
805 }
806
807 case Expr::Ult: {
808 UltExpr *ue = cast<UltExpr>(e);
809 Z3ASTHandle left = construct(ue->left, width_out);
810 Z3ASTHandle right = construct(ue->right, width_out);
811 assert(*width_out != 1 && "uncanonicalized ult");
812 *width_out = 1;
813 return bvLtExpr(left, right);
814 }
815
816 case Expr::Ule: {
817 UleExpr *ue = cast<UleExpr>(e);
818 Z3ASTHandle left = construct(ue->left, width_out);
819 Z3ASTHandle right = construct(ue->right, width_out);
820 assert(*width_out != 1 && "uncanonicalized ule");
821 *width_out = 1;
822 return bvLeExpr(left, right);
823 }
824
825 case Expr::Slt: {
826 SltExpr *se = cast<SltExpr>(e);
827 Z3ASTHandle left = construct(se->left, width_out);
828 Z3ASTHandle right = construct(se->right, width_out);
829 assert(*width_out != 1 && "uncanonicalized slt");
830 *width_out = 1;
831 return sbvLtExpr(left, right);
832 }
833
834 case Expr::Sle: {
835 SleExpr *se = cast<SleExpr>(e);
836 Z3ASTHandle left = construct(se->left, width_out);
837 Z3ASTHandle right = construct(se->right, width_out);
838 assert(*width_out != 1 && "uncanonicalized sle");
839 *width_out = 1;
840 return sbvLeExpr(left, right);
841 }
842
843// unused due to canonicalization
844#if 0
845 case Expr::Ne:
846 case Expr::Ugt:
847 case Expr::Uge:
848 case Expr::Sgt:
849 case Expr::Sge:
850#endif
851
852 default:
853 assert(0 && "unhandled Expr type");
854 return getTrue();
855 }
856}
857}
858#endif // ENABLE_Z3
void hashArrayExpr(const Array *array, T &exp)
Definition: ArrayExprHash.h:94
bool lookupUpdateNodeExpr(const UpdateNode *un, T &exp) const
void hashUpdateNodeExpr(const UpdateNode *un, T &exp)
bool lookupArrayExpr(const Array *array, T &exp) const
Definition: ArrayExprHash.h:77
Expr::Width getRange() const
Definition: Expr.h:530
bool isConstantArray() const
Definition: Expr.h:525
const unsigned size
Definition: Expr.h:489
const std::vector< ref< ConstantExpr > > constantValues
Definition: Expr.h:498
const std::string name
Definition: Expr.h:486
Expr::Width getDomain() const
Definition: Expr.h:529
Width getWidth() const
Definition: Expr.h:849
ref< Expr > src
Definition: Expr.h:843
ref< Expr > getKid(unsigned i) const
Definition: Expr.h:697
Width getWidth() const
Definition: Expr.h:691
unsigned getNumKids() const
Definition: Expr.h:696
bool isTrue() const
isTrue - Is this the true expression.
Definition: Expr.h:1099
Width getWidth() const
Definition: Expr.h:1009
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
Definition: Expr.h:1037
uint64_t getZExtValue(unsigned bits=64) const
Definition: Expr.h:1030
virtual Kind getKind() const =0
@ Xor
Definition: Expr.h:149
@ Not
Definition: Expr.h:133
@ Ule
Definition: Expr.h:158
@ LShr
Definition: Expr.h:151
@ Sge
Not used in canonical form.
Definition: Expr.h:164
@ Add
Definition: Expr.h:138
@ Select
Definition: Expr.h:124
@ Ne
Not used in canonical form.
Definition: Expr.h:156
@ And
Definition: Expr.h:147
@ ZExt
Definition: Expr.h:129
@ URem
Definition: Expr.h:143
@ SDiv
Definition: Expr.h:142
@ NotOptimized
Definition: Expr.h:120
@ Mul
Definition: Expr.h:140
@ AShr
Definition: Expr.h:152
@ Extract
Definition: Expr.h:126
@ Read
Definition: Expr.h:123
@ Constant
Definition: Expr.h:113
@ Ugt
Not used in canonical form.
Definition: Expr.h:159
@ Sub
Definition: Expr.h:139
@ Ult
Definition: Expr.h:157
@ Shl
Definition: Expr.h:150
@ SRem
Definition: Expr.h:144
@ Concat
Definition: Expr.h:125
@ Or
Definition: Expr.h:148
@ Sle
Definition: Expr.h:162
@ Sgt
Not used in canonical form.
Definition: Expr.h:163
@ Slt
Definition: Expr.h:161
@ Uge
Not used in canonical form.
Definition: Expr.h:160
@ SExt
Definition: Expr.h:130
@ UDiv
Definition: Expr.h:141
@ Eq
Definition: Expr.h:155
unsigned offset
Definition: Expr.h:746
Width getWidth() const
Definition: Expr.h:759
ref< Expr > expr
Definition: Expr.h:745
ref< Expr > src
Definition: Expr.h:415
Class representing a one byte read from an array.
Definition: Expr.h:565
ref< Expr > index
Definition: Expr.h:572
UpdateList updates
Definition: Expr.h:571
Class representing an if-then-else expression.
Definition: Expr.h:610
ref< Expr > cond
Definition: Expr.h:616
ref< Expr > trueExpr
Definition: Expr.h:616
ref< Expr > falseExpr
Definition: Expr.h:616
ref< UpdateNode > head
pointer to the most recent update node
Definition: Expr.h:546
const Array * root
Definition: Expr.h:543
Class representing a byte update of an array.
Definition: Expr.h:451
ref< Expr > index
Definition: Expr.h:459
const ref< UpdateNode > next
Definition: Expr.h:458
ref< Expr > value
Definition: Expr.h:459
virtual ~Z3ArrayExprHash()
Z3ASTHandle getFalse()
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
Definition: Z3Builder.h:175
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
Definition: Z3Builder.h:105
std::string z3LogInteractionFile
Definition: Z3Builder.h:170
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()
Definition: Z3Builder.h:190
Z3ASTHandle getTrue()
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
Definition: Z3Builder.h:106
Z3ASTHandle getArrayForUpdate(const Array *root, const UpdateNode *un)
Z3_context ctx
Definition: Z3Builder.h:173
unsigned indexOfSingleBit(uint64_t x)
Definition: Bits.h:98
uint64_t isPowerOfTwo(uint64_t x)
Definition: Bits.h:91
uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth)
Statistic queryConstructs
Definition: main.cpp:291
void klee_message(const char *msg,...) __attribute__((format(printf
Z3NodeHandle< Z3_ast > Z3ASTHandle
Definition: Z3Builder.h:91
llvm::cl::OptionCategory ExprCat
Z3NodeHandle< Z3_sort > Z3SortHandle
Definition: Z3Builder.h:86