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"
16 #include "klee/Solver/SolverStats.h"
17 #include "klee/Support/ErrorHandling.h"
18
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/Support/CommandLine.h"
21
22 using namespace klee;
23
24 namespace {
25 llvm::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.
32 bool Z3InterationLogOpen = false;
33 }
34
35 namespace klee {
36
37 // Declared here rather than `Z3Builder.h` so they can be called in gdb.
dump()38 template <> void Z3NodeHandle<Z3_sort>::dump() {
39 llvm::errs() << "Z3SortHandle:\n" << ::Z3_sort_to_string(context, node)
40 << "\n";
41 }
dump()42 template <> void Z3NodeHandle<Z3_ast>::dump() {
43 llvm::errs() << "Z3ASTHandle:\n" << ::Z3_ast_to_string(context, as_ast())
44 << "\n";
45 }
46
custom_z3_error_handler(Z3_context ctx,Z3_error_code ec)47 void 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
~Z3ArrayExprHash()70 Z3ArrayExprHash::~Z3ArrayExprHash() {}
71
clear()72 void Z3ArrayExprHash::clear() {
73 _update_node_hash.clear();
74 _array_hash.clear();
75 }
76
Z3Builder(bool autoClearConstructCache,const char * z3LogInteractionFileArg)77 Z3Builder::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
~Z3Builder()100 Z3Builder::~Z3Builder() {
101 // Clear caches so exprs/sorts gets freed before the destroying context
102 // they aren associated with.
103 clearConstructCache();
104 _arr_hash.clear();
105 constant_array_assertions.clear();
106 Z3_del_context(ctx);
107 if (z3LogInteractionFile.length() > 0) {
108 Z3_close_log();
109 Z3InterationLogOpen = false;
110 }
111 }
112
getBvSort(unsigned width)113 Z3SortHandle Z3Builder::getBvSort(unsigned width) {
114 // FIXME: cache these
115 return Z3SortHandle(Z3_mk_bv_sort(ctx, width), ctx);
116 }
117
getArraySort(Z3SortHandle domainSort,Z3SortHandle rangeSort)118 Z3SortHandle Z3Builder::getArraySort(Z3SortHandle domainSort,
119 Z3SortHandle rangeSort) {
120 // FIXME: cache these
121 return Z3SortHandle(Z3_mk_array_sort(ctx, domainSort, rangeSort), ctx);
122 }
123
buildArray(const char * name,unsigned indexWidth,unsigned valueWidth)124 Z3ASTHandle 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
getTrue()133 Z3ASTHandle Z3Builder::getTrue() { return Z3ASTHandle(Z3_mk_true(ctx), ctx); }
134
getFalse()135 Z3ASTHandle Z3Builder::getFalse() { return Z3ASTHandle(Z3_mk_false(ctx), ctx); }
136
bvOne(unsigned width)137 Z3ASTHandle Z3Builder::bvOne(unsigned width) { return bvZExtConst(width, 1); }
138
bvZero(unsigned width)139 Z3ASTHandle Z3Builder::bvZero(unsigned width) { return bvZExtConst(width, 0); }
140
bvMinusOne(unsigned width)141 Z3ASTHandle Z3Builder::bvMinusOne(unsigned width) {
142 return bvSExtConst(width, (int64_t)-1);
143 }
144
bvConst32(unsigned width,uint32_t value)145 Z3ASTHandle 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
bvConst64(unsigned width,uint64_t value)150 Z3ASTHandle 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
bvZExtConst(unsigned width,uint64_t value)155 Z3ASTHandle 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
bvSExtConst(unsigned width,uint64_t value)166 Z3ASTHandle 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
bvBoolExtract(Z3ASTHandle expr,int bit)180 Z3ASTHandle Z3Builder::bvBoolExtract(Z3ASTHandle expr, int bit) {
181 return Z3ASTHandle(Z3_mk_eq(ctx, bvExtract(expr, bit, bit), bvOne(1)), ctx);
182 }
183
bvExtract(Z3ASTHandle expr,unsigned top,unsigned bottom)184 Z3ASTHandle Z3Builder::bvExtract(Z3ASTHandle expr, unsigned top,
185 unsigned bottom) {
186 return Z3ASTHandle(Z3_mk_extract(ctx, top, bottom, expr), ctx);
187 }
188
eqExpr(Z3ASTHandle a,Z3ASTHandle b)189 Z3ASTHandle Z3Builder::eqExpr(Z3ASTHandle a, Z3ASTHandle b) {
190 return Z3ASTHandle(Z3_mk_eq(ctx, a, b), ctx);
191 }
192
193 // logical right shift
bvRightShift(Z3ASTHandle expr,unsigned shift)194 Z3ASTHandle 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
bvLeftShift(Z3ASTHandle expr,unsigned shift)209 Z3ASTHandle 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
bvVarLeftShift(Z3ASTHandle expr,Z3ASTHandle shift)224 Z3ASTHandle Z3Builder::bvVarLeftShift(Z3ASTHandle expr, Z3ASTHandle shift) {
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
bvVarRightShift(Z3ASTHandle expr,Z3ASTHandle shift)243 Z3ASTHandle Z3Builder::bvVarRightShift(Z3ASTHandle expr, Z3ASTHandle shift) {
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
bvVarArithRightShift(Z3ASTHandle expr,Z3ASTHandle shift)262 Z3ASTHandle Z3Builder::bvVarArithRightShift(Z3ASTHandle expr,
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
notExpr(Z3ASTHandle expr)287 Z3ASTHandle Z3Builder::notExpr(Z3ASTHandle expr) {
288 return Z3ASTHandle(Z3_mk_not(ctx, expr), ctx);
289 }
290
bvNotExpr(Z3ASTHandle expr)291 Z3ASTHandle Z3Builder::bvNotExpr(Z3ASTHandle expr) {
292 return Z3ASTHandle(Z3_mk_bvnot(ctx, expr), ctx);
293 }
294
andExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)295 Z3ASTHandle Z3Builder::andExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
296 ::Z3_ast args[2] = {lhs, rhs};
297 return Z3ASTHandle(Z3_mk_and(ctx, 2, args), ctx);
298 }
299
bvAndExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)300 Z3ASTHandle Z3Builder::bvAndExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
301 return Z3ASTHandle(Z3_mk_bvand(ctx, lhs, rhs), ctx);
302 }
303
orExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)304 Z3ASTHandle Z3Builder::orExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
305 ::Z3_ast args[2] = {lhs, rhs};
306 return Z3ASTHandle(Z3_mk_or(ctx, 2, args), ctx);
307 }
308
bvOrExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)309 Z3ASTHandle Z3Builder::bvOrExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
310 return Z3ASTHandle(Z3_mk_bvor(ctx, lhs, rhs), ctx);
311 }
312
iffExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)313 Z3ASTHandle Z3Builder::iffExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
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
bvXorExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)322 Z3ASTHandle Z3Builder::bvXorExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
323 return Z3ASTHandle(Z3_mk_bvxor(ctx, lhs, rhs), ctx);
324 }
325
bvSignExtend(Z3ASTHandle src,unsigned width)326 Z3ASTHandle Z3Builder::bvSignExtend(Z3ASTHandle src, unsigned width) {
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
writeExpr(Z3ASTHandle array,Z3ASTHandle index,Z3ASTHandle value)334 Z3ASTHandle Z3Builder::writeExpr(Z3ASTHandle array, Z3ASTHandle index,
335 Z3ASTHandle value) {
336 return Z3ASTHandle(Z3_mk_store(ctx, array, index, value), ctx);
337 }
338
readExpr(Z3ASTHandle array,Z3ASTHandle index)339 Z3ASTHandle Z3Builder::readExpr(Z3ASTHandle array, Z3ASTHandle index) {
340 return Z3ASTHandle(Z3_mk_select(ctx, array, index), ctx);
341 }
342
iteExpr(Z3ASTHandle condition,Z3ASTHandle whenTrue,Z3ASTHandle whenFalse)343 Z3ASTHandle Z3Builder::iteExpr(Z3ASTHandle condition, Z3ASTHandle whenTrue,
344 Z3ASTHandle whenFalse) {
345 return Z3ASTHandle(Z3_mk_ite(ctx, condition, whenTrue, whenFalse), ctx);
346 }
347
getBVLength(Z3ASTHandle expr)348 unsigned Z3Builder::getBVLength(Z3ASTHandle expr) {
349 return Z3_get_bv_sort_size(ctx, Z3SortHandle(Z3_get_sort(ctx, expr), ctx));
350 }
351
bvLtExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)352 Z3ASTHandle Z3Builder::bvLtExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
353 return Z3ASTHandle(Z3_mk_bvult(ctx, lhs, rhs), ctx);
354 }
355
bvLeExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)356 Z3ASTHandle Z3Builder::bvLeExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
357 return Z3ASTHandle(Z3_mk_bvule(ctx, lhs, rhs), ctx);
358 }
359
sbvLtExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)360 Z3ASTHandle Z3Builder::sbvLtExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
361 return Z3ASTHandle(Z3_mk_bvslt(ctx, lhs, rhs), ctx);
362 }
363
sbvLeExpr(Z3ASTHandle lhs,Z3ASTHandle rhs)364 Z3ASTHandle Z3Builder::sbvLeExpr(Z3ASTHandle lhs, Z3ASTHandle rhs) {
365 return Z3ASTHandle(Z3_mk_bvsle(ctx, lhs, rhs), ctx);
366 }
367
constructAShrByConstant(Z3ASTHandle expr,unsigned shift,Z3ASTHandle isSigned)368 Z3ASTHandle Z3Builder::constructAShrByConstant(Z3ASTHandle expr, unsigned shift,
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
getInitialArray(const Array * root)386 Z3ASTHandle Z3Builder::getInitialArray(const Array *root) {
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
getInitialRead(const Array * root,unsigned index)424 Z3ASTHandle Z3Builder::getInitialRead(const Array *root, unsigned index) {
425 return readExpr(getInitialArray(root), bvConst32(32, index));
426 }
427
getArrayForUpdate(const Array * root,const UpdateNode * un)428 Z3ASTHandle Z3Builder::getArrayForUpdate(const Array *root,
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
448 /** if *width_out!=1 then result is a bitvector,
449 otherwise it is a bool */
construct(ref<Expr> e,int * width_out)450 Z3ASTHandle 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 {
456 ExprHashMap<std::pair<Z3ASTHandle, unsigned> >::iterator it =
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
473 /** if *width_out!=1 then result is a bitvector,
474 otherwise it is a bool */
constructActual(ref<Expr> e,int * width_out)475 Z3ASTHandle Z3Builder::constructActual(ref<Expr> e, int *width_out) {
476 int width;
477 if (!width_out)
478 width_out = &width;
479
480 ++stats::queryConstructs;
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
859