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