xref: /freebsd-src/contrib/llvm-project/llvm/lib/Support/Z3Solver.cpp (revision 6c4b055cfb6bf549e9145dde6454cc6b178c35e4)
10b57cec5SDimitry Andric //== Z3Solver.cpp -----------------------------------------------*- C++ -*--==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90fca6ea1SDimitry Andric #include "llvm/ADT/ScopeExit.h"
100b57cec5SDimitry Andric #include "llvm/Config/config.h"
110fca6ea1SDimitry Andric #include "llvm/Support/NativeFormatting.h"
120b57cec5SDimitry Andric #include "llvm/Support/SMTAPI.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #if LLVM_WITH_Z3
170b57cec5SDimitry Andric 
1881ad6265SDimitry Andric #include "llvm/ADT/SmallString.h"
1981ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
2081ad6265SDimitry Andric 
2181ad6265SDimitry Andric #include <set>
22*6c4b055cSDimitry Andric #include <unordered_map>
2381ad6265SDimitry Andric 
240b57cec5SDimitry Andric #include <z3.h>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace {
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric /// Configuration class for Z3
290b57cec5SDimitry Andric class Z3Config {
300b57cec5SDimitry Andric   friend class Z3Context;
310b57cec5SDimitry Andric 
320fca6ea1SDimitry Andric   Z3_config Config = Z3_mk_config();
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric public:
350fca6ea1SDimitry Andric   Z3Config() = default;
360fca6ea1SDimitry Andric   Z3Config(const Z3Config &) = delete;
370fca6ea1SDimitry Andric   Z3Config(Z3Config &&) = default;
380fca6ea1SDimitry Andric   Z3Config &operator=(Z3Config &) = delete;
390fca6ea1SDimitry Andric   Z3Config &operator=(Z3Config &&) = default;
400b57cec5SDimitry Andric   ~Z3Config() { Z3_del_config(Config); }
410b57cec5SDimitry Andric }; // end class Z3Config
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric // Function used to report errors
440b57cec5SDimitry Andric void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) {
450b57cec5SDimitry Andric   llvm::report_fatal_error("Z3 error: " +
460b57cec5SDimitry Andric                            llvm::Twine(Z3_get_error_msg(Context, Error)));
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric /// Wrapper for Z3 context
500b57cec5SDimitry Andric class Z3Context {
510b57cec5SDimitry Andric public:
520fca6ea1SDimitry Andric   Z3Config Config;
530b57cec5SDimitry Andric   Z3_context Context;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   Z3Context() {
560fca6ea1SDimitry Andric     Context = Z3_mk_context_rc(Config.Config);
570b57cec5SDimitry Andric     // The error function is set here because the context is the first object
580b57cec5SDimitry Andric     // created by the backend
590b57cec5SDimitry Andric     Z3_set_error_handler(Context, Z3ErrorHandler);
600b57cec5SDimitry Andric   }
610b57cec5SDimitry Andric 
620fca6ea1SDimitry Andric   Z3Context(const Z3Context &) = delete;
630fca6ea1SDimitry Andric   Z3Context(Z3Context &&) = default;
640fca6ea1SDimitry Andric   Z3Context &operator=(Z3Context &) = delete;
650fca6ea1SDimitry Andric   Z3Context &operator=(Z3Context &&) = default;
660fca6ea1SDimitry Andric 
670fca6ea1SDimitry Andric   ~Z3Context() {
680b57cec5SDimitry Andric     Z3_del_context(Context);
690b57cec5SDimitry Andric     Context = nullptr;
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric }; // end class Z3Context
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric /// Wrapper for Z3 Sort
740b57cec5SDimitry Andric class Z3Sort : public SMTSort {
750b57cec5SDimitry Andric   friend class Z3Solver;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   Z3Context &Context;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   Z3_sort Sort;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric public:
820b57cec5SDimitry Andric   /// Default constructor, mainly used by make_shared
830b57cec5SDimitry Andric   Z3Sort(Z3Context &C, Z3_sort ZS) : Context(C), Sort(ZS) {
840b57cec5SDimitry Andric     Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// Override implicit copy constructor for correct reference counting.
880b57cec5SDimitry Andric   Z3Sort(const Z3Sort &Other) : Context(Other.Context), Sort(Other.Sort) {
890b57cec5SDimitry Andric     Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   /// Override implicit copy assignment constructor for correct reference
930b57cec5SDimitry Andric   /// counting.
940b57cec5SDimitry Andric   Z3Sort &operator=(const Z3Sort &Other) {
950b57cec5SDimitry Andric     Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Other.Sort));
960b57cec5SDimitry Andric     Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
970b57cec5SDimitry Andric     Sort = Other.Sort;
980b57cec5SDimitry Andric     return *this;
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   Z3Sort(Z3Sort &&Other) = delete;
1020b57cec5SDimitry Andric   Z3Sort &operator=(Z3Sort &&Other) = delete;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   ~Z3Sort() {
1050b57cec5SDimitry Andric     if (Sort)
1060b57cec5SDimitry Andric       Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   void Profile(llvm::FoldingSetNodeID &ID) const override {
1100b57cec5SDimitry Andric     ID.AddInteger(
1110b57cec5SDimitry Andric         Z3_get_ast_id(Context.Context, reinterpret_cast<Z3_ast>(Sort)));
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   bool isBitvectorSortImpl() const override {
1150b57cec5SDimitry Andric     return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BV_SORT);
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   bool isFloatSortImpl() const override {
1190b57cec5SDimitry Andric     return (Z3_get_sort_kind(Context.Context, Sort) == Z3_FLOATING_POINT_SORT);
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   bool isBooleanSortImpl() const override {
1230b57cec5SDimitry Andric     return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BOOL_SORT);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   unsigned getBitvectorSortSizeImpl() const override {
1270b57cec5SDimitry Andric     return Z3_get_bv_sort_size(Context.Context, Sort);
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   unsigned getFloatSortSizeImpl() const override {
1310b57cec5SDimitry Andric     return Z3_fpa_get_ebits(Context.Context, Sort) +
1320b57cec5SDimitry Andric            Z3_fpa_get_sbits(Context.Context, Sort);
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   bool equal_to(SMTSort const &Other) const override {
1360b57cec5SDimitry Andric     return Z3_is_eq_sort(Context.Context, Sort,
1370b57cec5SDimitry Andric                          static_cast<const Z3Sort &>(Other).Sort);
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
1410b57cec5SDimitry Andric     OS << Z3_sort_to_string(Context.Context, Sort);
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric }; // end class Z3Sort
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric static const Z3Sort &toZ3Sort(const SMTSort &S) {
1460b57cec5SDimitry Andric   return static_cast<const Z3Sort &>(S);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric class Z3Expr : public SMTExpr {
1500b57cec5SDimitry Andric   friend class Z3Solver;
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   Z3Context &Context;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   Z3_ast AST;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric public:
1570b57cec5SDimitry Andric   Z3Expr(Z3Context &C, Z3_ast ZA) : SMTExpr(), Context(C), AST(ZA) {
1580b57cec5SDimitry Andric     Z3_inc_ref(Context.Context, AST);
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   /// Override implicit copy constructor for correct reference counting.
1620b57cec5SDimitry Andric   Z3Expr(const Z3Expr &Copy) : SMTExpr(), Context(Copy.Context), AST(Copy.AST) {
1630b57cec5SDimitry Andric     Z3_inc_ref(Context.Context, AST);
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   /// Override implicit copy assignment constructor for correct reference
1670b57cec5SDimitry Andric   /// counting.
1680b57cec5SDimitry Andric   Z3Expr &operator=(const Z3Expr &Other) {
1690b57cec5SDimitry Andric     Z3_inc_ref(Context.Context, Other.AST);
1700b57cec5SDimitry Andric     Z3_dec_ref(Context.Context, AST);
1710b57cec5SDimitry Andric     AST = Other.AST;
1720b57cec5SDimitry Andric     return *this;
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   Z3Expr(Z3Expr &&Other) = delete;
1760b57cec5SDimitry Andric   Z3Expr &operator=(Z3Expr &&Other) = delete;
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   ~Z3Expr() {
1790b57cec5SDimitry Andric     if (AST)
1800b57cec5SDimitry Andric       Z3_dec_ref(Context.Context, AST);
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   void Profile(llvm::FoldingSetNodeID &ID) const override {
1840b57cec5SDimitry Andric     ID.AddInteger(Z3_get_ast_id(Context.Context, AST));
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   /// Comparison of AST equality, not model equivalence.
1880b57cec5SDimitry Andric   bool equal_to(SMTExpr const &Other) const override {
1890b57cec5SDimitry Andric     assert(Z3_is_eq_sort(Context.Context, Z3_get_sort(Context.Context, AST),
1900b57cec5SDimitry Andric                          Z3_get_sort(Context.Context,
1910b57cec5SDimitry Andric                                      static_cast<const Z3Expr &>(Other).AST)) &&
1920b57cec5SDimitry Andric            "AST's must have the same sort");
1930b57cec5SDimitry Andric     return Z3_is_eq_ast(Context.Context, AST,
1940b57cec5SDimitry Andric                         static_cast<const Z3Expr &>(Other).AST);
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
1980b57cec5SDimitry Andric     OS << Z3_ast_to_string(Context.Context, AST);
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric }; // end class Z3Expr
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric static const Z3Expr &toZ3Expr(const SMTExpr &E) {
2030b57cec5SDimitry Andric   return static_cast<const Z3Expr &>(E);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric class Z3Model {
2070b57cec5SDimitry Andric   friend class Z3Solver;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   Z3Context &Context;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   Z3_model Model;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric public:
2140b57cec5SDimitry Andric   Z3Model(Z3Context &C, Z3_model ZM) : Context(C), Model(ZM) {
2150b57cec5SDimitry Andric     Z3_model_inc_ref(Context.Context, Model);
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   Z3Model(const Z3Model &Other) = delete;
2190b57cec5SDimitry Andric   Z3Model(Z3Model &&Other) = delete;
2200b57cec5SDimitry Andric   Z3Model &operator=(Z3Model &Other) = delete;
2210b57cec5SDimitry Andric   Z3Model &operator=(Z3Model &&Other) = delete;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   ~Z3Model() {
2240b57cec5SDimitry Andric     if (Model)
2250b57cec5SDimitry Andric       Z3_model_dec_ref(Context.Context, Model);
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   void print(raw_ostream &OS) const {
2290b57cec5SDimitry Andric     OS << Z3_model_to_string(Context.Context, Model);
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
2330b57cec5SDimitry Andric }; // end class Z3Model
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric /// Get the corresponding IEEE floating-point type for a given bitwidth.
2360b57cec5SDimitry Andric static const llvm::fltSemantics &getFloatSemantics(unsigned BitWidth) {
2370b57cec5SDimitry Andric   switch (BitWidth) {
2380b57cec5SDimitry Andric   default:
2390b57cec5SDimitry Andric     llvm_unreachable("Unsupported floating-point semantics!");
2400b57cec5SDimitry Andric     break;
2410b57cec5SDimitry Andric   case 16:
2420b57cec5SDimitry Andric     return llvm::APFloat::IEEEhalf();
2430b57cec5SDimitry Andric   case 32:
2440b57cec5SDimitry Andric     return llvm::APFloat::IEEEsingle();
2450b57cec5SDimitry Andric   case 64:
2460b57cec5SDimitry Andric     return llvm::APFloat::IEEEdouble();
2470b57cec5SDimitry Andric   case 128:
2480b57cec5SDimitry Andric     return llvm::APFloat::IEEEquad();
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric // Determine whether two float semantics are equivalent
2530b57cec5SDimitry Andric static bool areEquivalent(const llvm::fltSemantics &LHS,
2540b57cec5SDimitry Andric                           const llvm::fltSemantics &RHS) {
2550b57cec5SDimitry Andric   return (llvm::APFloat::semanticsPrecision(LHS) ==
2560b57cec5SDimitry Andric           llvm::APFloat::semanticsPrecision(RHS)) &&
2570b57cec5SDimitry Andric          (llvm::APFloat::semanticsMinExponent(LHS) ==
2580b57cec5SDimitry Andric           llvm::APFloat::semanticsMinExponent(RHS)) &&
2590b57cec5SDimitry Andric          (llvm::APFloat::semanticsMaxExponent(LHS) ==
2600b57cec5SDimitry Andric           llvm::APFloat::semanticsMaxExponent(RHS)) &&
2610b57cec5SDimitry Andric          (llvm::APFloat::semanticsSizeInBits(LHS) ==
2620b57cec5SDimitry Andric           llvm::APFloat::semanticsSizeInBits(RHS));
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric class Z3Solver : public SMTSolver {
2660b57cec5SDimitry Andric   friend class Z3ConstraintManager;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   Z3Context Context;
2690b57cec5SDimitry Andric 
2700fca6ea1SDimitry Andric   Z3_solver Solver = [this] {
2710fca6ea1SDimitry Andric     Z3_solver S = Z3_mk_simple_solver(Context.Context);
2720fca6ea1SDimitry Andric     Z3_solver_inc_ref(Context.Context, S);
2730fca6ea1SDimitry Andric     return S;
2740fca6ea1SDimitry Andric   }();
2750fca6ea1SDimitry Andric 
2760fca6ea1SDimitry Andric   Z3_params Params = [this] {
2770fca6ea1SDimitry Andric     Z3_params P = Z3_mk_params(Context.Context);
2780fca6ea1SDimitry Andric     Z3_params_inc_ref(Context.Context, P);
2790fca6ea1SDimitry Andric     return P;
2800fca6ea1SDimitry Andric   }();
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   // Cache Sorts
2830b57cec5SDimitry Andric   std::set<Z3Sort> CachedSorts;
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   // Cache Exprs
2860b57cec5SDimitry Andric   std::set<Z3Expr> CachedExprs;
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric public:
2890fca6ea1SDimitry Andric   Z3Solver() = default;
2900b57cec5SDimitry Andric   Z3Solver(const Z3Solver &Other) = delete;
2910b57cec5SDimitry Andric   Z3Solver(Z3Solver &&Other) = delete;
2920b57cec5SDimitry Andric   Z3Solver &operator=(Z3Solver &Other) = delete;
2930b57cec5SDimitry Andric   Z3Solver &operator=(Z3Solver &&Other) = delete;
2940b57cec5SDimitry Andric 
2950fca6ea1SDimitry Andric   ~Z3Solver() override {
2960fca6ea1SDimitry Andric     Z3_params_dec_ref(Context.Context, Params);
2970b57cec5SDimitry Andric     Z3_solver_dec_ref(Context.Context, Solver);
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   void addConstraint(const SMTExprRef &Exp) const override {
3010b57cec5SDimitry Andric     Z3_solver_assert(Context.Context, Solver, toZ3Expr(*Exp).AST);
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   // Given an SMTSort, adds/retrives it from the cache and returns
3050b57cec5SDimitry Andric   // an SMTSortRef to the SMTSort in the cache
3060b57cec5SDimitry Andric   SMTSortRef newSortRef(const SMTSort &Sort) {
3070b57cec5SDimitry Andric     auto It = CachedSorts.insert(toZ3Sort(Sort));
3080b57cec5SDimitry Andric     return &(*It.first);
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   // Given an SMTExpr, adds/retrives it from the cache and returns
3120b57cec5SDimitry Andric   // an SMTExprRef to the SMTExpr in the cache
3130b57cec5SDimitry Andric   SMTExprRef newExprRef(const SMTExpr &Exp) {
3140b57cec5SDimitry Andric     auto It = CachedExprs.insert(toZ3Expr(Exp));
3150b57cec5SDimitry Andric     return &(*It.first);
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   SMTSortRef getBoolSort() override {
3190b57cec5SDimitry Andric     return newSortRef(Z3Sort(Context, Z3_mk_bool_sort(Context.Context)));
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   SMTSortRef getBitvectorSort(unsigned BitWidth) override {
3230b57cec5SDimitry Andric     return newSortRef(
3240b57cec5SDimitry Andric         Z3Sort(Context, Z3_mk_bv_sort(Context.Context, BitWidth)));
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   SMTSortRef getSort(const SMTExprRef &Exp) override {
3280b57cec5SDimitry Andric     return newSortRef(
3290b57cec5SDimitry Andric         Z3Sort(Context, Z3_get_sort(Context.Context, toZ3Expr(*Exp).AST)));
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   SMTSortRef getFloat16Sort() override {
3330b57cec5SDimitry Andric     return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_16(Context.Context)));
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   SMTSortRef getFloat32Sort() override {
3370b57cec5SDimitry Andric     return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_32(Context.Context)));
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   SMTSortRef getFloat64Sort() override {
3410b57cec5SDimitry Andric     return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_64(Context.Context)));
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   SMTSortRef getFloat128Sort() override {
3450b57cec5SDimitry Andric     return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_128(Context.Context)));
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   SMTExprRef mkBVNeg(const SMTExprRef &Exp) override {
3490b57cec5SDimitry Andric     return newExprRef(
3500b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvneg(Context.Context, toZ3Expr(*Exp).AST)));
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   SMTExprRef mkBVNot(const SMTExprRef &Exp) override {
3540b57cec5SDimitry Andric     return newExprRef(
3550b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvnot(Context.Context, toZ3Expr(*Exp).AST)));
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   SMTExprRef mkNot(const SMTExprRef &Exp) override {
3590b57cec5SDimitry Andric     return newExprRef(
3600b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_not(Context.Context, toZ3Expr(*Exp).AST)));
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
3640b57cec5SDimitry Andric     return newExprRef(
3650b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvadd(Context.Context, toZ3Expr(*LHS).AST,
3660b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
3700b57cec5SDimitry Andric     return newExprRef(
3710b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvsub(Context.Context, toZ3Expr(*LHS).AST,
3720b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
3760b57cec5SDimitry Andric     return newExprRef(
3770b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvmul(Context.Context, toZ3Expr(*LHS).AST,
3780b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
3820b57cec5SDimitry Andric     return newExprRef(
3830b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvsrem(Context.Context, toZ3Expr(*LHS).AST,
3840b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
3880b57cec5SDimitry Andric     return newExprRef(
3890b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvurem(Context.Context, toZ3Expr(*LHS).AST,
3900b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
3940b57cec5SDimitry Andric     return newExprRef(
3950b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvsdiv(Context.Context, toZ3Expr(*LHS).AST,
3960b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
3970b57cec5SDimitry Andric   }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4000b57cec5SDimitry Andric     return newExprRef(
4010b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvudiv(Context.Context, toZ3Expr(*LHS).AST,
4020b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4060b57cec5SDimitry Andric     return newExprRef(
4070b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvshl(Context.Context, toZ3Expr(*LHS).AST,
4080b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4120b57cec5SDimitry Andric     return newExprRef(
4130b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvashr(Context.Context, toZ3Expr(*LHS).AST,
4140b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4180b57cec5SDimitry Andric     return newExprRef(
4190b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvlshr(Context.Context, toZ3Expr(*LHS).AST,
4200b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4240b57cec5SDimitry Andric     return newExprRef(
4250b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvxor(Context.Context, toZ3Expr(*LHS).AST,
4260b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4300b57cec5SDimitry Andric     return newExprRef(
4310b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvor(Context.Context, toZ3Expr(*LHS).AST,
4320b57cec5SDimitry Andric                                    toZ3Expr(*RHS).AST)));
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4360b57cec5SDimitry Andric     return newExprRef(
4370b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvand(Context.Context, toZ3Expr(*LHS).AST,
4380b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4420b57cec5SDimitry Andric     return newExprRef(
4430b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvult(Context.Context, toZ3Expr(*LHS).AST,
4440b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4450b57cec5SDimitry Andric   }
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4480b57cec5SDimitry Andric     return newExprRef(
4490b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvslt(Context.Context, toZ3Expr(*LHS).AST,
4500b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4540b57cec5SDimitry Andric     return newExprRef(
4550b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvugt(Context.Context, toZ3Expr(*LHS).AST,
4560b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4570b57cec5SDimitry Andric   }
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4600b57cec5SDimitry Andric     return newExprRef(
4610b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvsgt(Context.Context, toZ3Expr(*LHS).AST,
4620b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4660b57cec5SDimitry Andric     return newExprRef(
4670b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvule(Context.Context, toZ3Expr(*LHS).AST,
4680b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4690b57cec5SDimitry Andric   }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4720b57cec5SDimitry Andric     return newExprRef(
4730b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvsle(Context.Context, toZ3Expr(*LHS).AST,
4740b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4750b57cec5SDimitry Andric   }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4780b57cec5SDimitry Andric     return newExprRef(
4790b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvuge(Context.Context, toZ3Expr(*LHS).AST,
4800b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4840b57cec5SDimitry Andric     return newExprRef(
4850b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_bvsge(Context.Context, toZ3Expr(*LHS).AST,
4860b57cec5SDimitry Andric                                     toZ3Expr(*RHS).AST)));
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4900b57cec5SDimitry Andric     Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
4910b57cec5SDimitry Andric     return newExprRef(Z3Expr(Context, Z3_mk_and(Context.Context, 2, Args)));
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
4950b57cec5SDimitry Andric     Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
4960b57cec5SDimitry Andric     return newExprRef(Z3Expr(Context, Z3_mk_or(Context.Context, 2, Args)));
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5000b57cec5SDimitry Andric     return newExprRef(
5010b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_eq(Context.Context, toZ3Expr(*LHS).AST,
5020b57cec5SDimitry Andric                                  toZ3Expr(*RHS).AST)));
5030b57cec5SDimitry Andric   }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   SMTExprRef mkFPNeg(const SMTExprRef &Exp) override {
5060b57cec5SDimitry Andric     return newExprRef(
5070b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_neg(Context.Context, toZ3Expr(*Exp).AST)));
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) override {
5110b57cec5SDimitry Andric     return newExprRef(Z3Expr(
5120b57cec5SDimitry Andric         Context, Z3_mk_fpa_is_infinite(Context.Context, toZ3Expr(*Exp).AST)));
5130b57cec5SDimitry Andric   }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) override {
5160b57cec5SDimitry Andric     return newExprRef(
5170b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_is_nan(Context.Context, toZ3Expr(*Exp).AST)));
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) override {
5210b57cec5SDimitry Andric     return newExprRef(Z3Expr(
5220b57cec5SDimitry Andric         Context, Z3_mk_fpa_is_normal(Context.Context, toZ3Expr(*Exp).AST)));
5230b57cec5SDimitry Andric   }
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   SMTExprRef mkFPIsZero(const SMTExprRef &Exp) override {
5260b57cec5SDimitry Andric     return newExprRef(Z3Expr(
5270b57cec5SDimitry Andric         Context, Z3_mk_fpa_is_zero(Context.Context, toZ3Expr(*Exp).AST)));
5280b57cec5SDimitry Andric   }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5310b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
5320b57cec5SDimitry Andric     return newExprRef(
5330b57cec5SDimitry Andric         Z3Expr(Context,
5345ffd83dbSDimitry Andric                Z3_mk_fpa_mul(Context.Context, toZ3Expr(*RoundingMode).AST,
5355ffd83dbSDimitry Andric                              toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
5360b57cec5SDimitry Andric   }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5390b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
5400b57cec5SDimitry Andric     return newExprRef(
5410b57cec5SDimitry Andric         Z3Expr(Context,
5425ffd83dbSDimitry Andric                Z3_mk_fpa_div(Context.Context, toZ3Expr(*RoundingMode).AST,
5435ffd83dbSDimitry Andric                              toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5470b57cec5SDimitry Andric     return newExprRef(
5480b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_rem(Context.Context, toZ3Expr(*LHS).AST,
5490b57cec5SDimitry Andric                                       toZ3Expr(*RHS).AST)));
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5530b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
5540b57cec5SDimitry Andric     return newExprRef(
5550b57cec5SDimitry Andric         Z3Expr(Context,
5565ffd83dbSDimitry Andric                Z3_mk_fpa_add(Context.Context, toZ3Expr(*RoundingMode).AST,
5575ffd83dbSDimitry Andric                              toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
5580b57cec5SDimitry Andric   }
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5610b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
5620b57cec5SDimitry Andric     return newExprRef(
5630b57cec5SDimitry Andric         Z3Expr(Context,
5645ffd83dbSDimitry Andric                Z3_mk_fpa_sub(Context.Context, toZ3Expr(*RoundingMode).AST,
5655ffd83dbSDimitry Andric                              toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5690b57cec5SDimitry Andric     return newExprRef(
5700b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_lt(Context.Context, toZ3Expr(*LHS).AST,
5710b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5750b57cec5SDimitry Andric     return newExprRef(
5760b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_gt(Context.Context, toZ3Expr(*LHS).AST,
5770b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5810b57cec5SDimitry Andric     return newExprRef(
5820b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_leq(Context.Context, toZ3Expr(*LHS).AST,
5830b57cec5SDimitry Andric                                       toZ3Expr(*RHS).AST)));
5840b57cec5SDimitry Andric   }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5870b57cec5SDimitry Andric     return newExprRef(
5880b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_geq(Context.Context, toZ3Expr(*LHS).AST,
5890b57cec5SDimitry Andric                                       toZ3Expr(*RHS).AST)));
5900b57cec5SDimitry Andric   }
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   SMTExprRef mkFPEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
5930b57cec5SDimitry Andric     return newExprRef(
5940b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_fpa_eq(Context.Context, toZ3Expr(*LHS).AST,
5950b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
5990b57cec5SDimitry Andric                    const SMTExprRef &F) override {
6000b57cec5SDimitry Andric     return newExprRef(
6010b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_ite(Context.Context, toZ3Expr(*Cond).AST,
6020b57cec5SDimitry Andric                                   toZ3Expr(*T).AST, toZ3Expr(*F).AST)));
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) override {
6060b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6070b57cec5SDimitry Andric         Context, Z3_mk_sign_ext(Context.Context, i, toZ3Expr(*Exp).AST)));
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) override {
6110b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6120b57cec5SDimitry Andric         Context, Z3_mk_zero_ext(Context.Context, i, toZ3Expr(*Exp).AST)));
6130b57cec5SDimitry Andric   }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   SMTExprRef mkBVExtract(unsigned High, unsigned Low,
6160b57cec5SDimitry Andric                          const SMTExprRef &Exp) override {
6170b57cec5SDimitry Andric     return newExprRef(Z3Expr(Context, Z3_mk_extract(Context.Context, High, Low,
6180b57cec5SDimitry Andric                                                     toZ3Expr(*Exp).AST)));
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   /// Creates a predicate that checks for overflow in a bitvector addition
6220b57cec5SDimitry Andric   /// operation
6230b57cec5SDimitry Andric   SMTExprRef mkBVAddNoOverflow(const SMTExprRef &LHS, const SMTExprRef &RHS,
6240b57cec5SDimitry Andric                                bool isSigned) override {
6250b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6260b57cec5SDimitry Andric         Context, Z3_mk_bvadd_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
6270b57cec5SDimitry Andric                                          toZ3Expr(*RHS).AST, isSigned)));
6280b57cec5SDimitry Andric   }
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   /// Creates a predicate that checks for underflow in a signed bitvector
6310b57cec5SDimitry Andric   /// addition operation
6320b57cec5SDimitry Andric   SMTExprRef mkBVAddNoUnderflow(const SMTExprRef &LHS,
6330b57cec5SDimitry Andric                                 const SMTExprRef &RHS) override {
6340b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6350b57cec5SDimitry Andric         Context, Z3_mk_bvadd_no_underflow(Context.Context, toZ3Expr(*LHS).AST,
6360b57cec5SDimitry Andric                                           toZ3Expr(*RHS).AST)));
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   /// Creates a predicate that checks for overflow in a signed bitvector
6400b57cec5SDimitry Andric   /// subtraction operation
6410b57cec5SDimitry Andric   SMTExprRef mkBVSubNoOverflow(const SMTExprRef &LHS,
6420b57cec5SDimitry Andric                                const SMTExprRef &RHS) override {
6430b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6440b57cec5SDimitry Andric         Context, Z3_mk_bvsub_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
6450b57cec5SDimitry Andric                                          toZ3Expr(*RHS).AST)));
6460b57cec5SDimitry Andric   }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   /// Creates a predicate that checks for underflow in a bitvector subtraction
6490b57cec5SDimitry Andric   /// operation
6500b57cec5SDimitry Andric   SMTExprRef mkBVSubNoUnderflow(const SMTExprRef &LHS, const SMTExprRef &RHS,
6510b57cec5SDimitry Andric                                 bool isSigned) override {
6520b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6530b57cec5SDimitry Andric         Context, Z3_mk_bvsub_no_underflow(Context.Context, toZ3Expr(*LHS).AST,
6540b57cec5SDimitry Andric                                           toZ3Expr(*RHS).AST, isSigned)));
6550b57cec5SDimitry Andric   }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   /// Creates a predicate that checks for overflow in a signed bitvector
6580b57cec5SDimitry Andric   /// division/modulus operation
6590b57cec5SDimitry Andric   SMTExprRef mkBVSDivNoOverflow(const SMTExprRef &LHS,
6600b57cec5SDimitry Andric                                 const SMTExprRef &RHS) override {
6610b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6620b57cec5SDimitry Andric         Context, Z3_mk_bvsdiv_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
6630b57cec5SDimitry Andric                                           toZ3Expr(*RHS).AST)));
6640b57cec5SDimitry Andric   }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   /// Creates a predicate that checks for overflow in a bitvector negation
6670b57cec5SDimitry Andric   /// operation
6680b57cec5SDimitry Andric   SMTExprRef mkBVNegNoOverflow(const SMTExprRef &Exp) override {
6690b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6700b57cec5SDimitry Andric         Context, Z3_mk_bvneg_no_overflow(Context.Context, toZ3Expr(*Exp).AST)));
6710b57cec5SDimitry Andric   }
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   /// Creates a predicate that checks for overflow in a bitvector multiplication
6740b57cec5SDimitry Andric   /// operation
6750b57cec5SDimitry Andric   SMTExprRef mkBVMulNoOverflow(const SMTExprRef &LHS, const SMTExprRef &RHS,
6760b57cec5SDimitry Andric                                bool isSigned) override {
6770b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6780b57cec5SDimitry Andric         Context, Z3_mk_bvmul_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
6790b57cec5SDimitry Andric                                          toZ3Expr(*RHS).AST, isSigned)));
6800b57cec5SDimitry Andric   }
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   /// Creates a predicate that checks for underflow in a signed bitvector
6830b57cec5SDimitry Andric   /// multiplication operation
6840b57cec5SDimitry Andric   SMTExprRef mkBVMulNoUnderflow(const SMTExprRef &LHS,
6850b57cec5SDimitry Andric                                 const SMTExprRef &RHS) override {
6860b57cec5SDimitry Andric     return newExprRef(Z3Expr(
6870b57cec5SDimitry Andric         Context, Z3_mk_bvmul_no_underflow(Context.Context, toZ3Expr(*LHS).AST,
6880b57cec5SDimitry Andric                                           toZ3Expr(*RHS).AST)));
6890b57cec5SDimitry Andric   }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   SMTExprRef mkBVConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
6920b57cec5SDimitry Andric     return newExprRef(
6930b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_concat(Context.Context, toZ3Expr(*LHS).AST,
6940b57cec5SDimitry Andric                                      toZ3Expr(*RHS).AST)));
6950b57cec5SDimitry Andric   }
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric   SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
6980b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
6990b57cec5SDimitry Andric     return newExprRef(Z3Expr(
7000b57cec5SDimitry Andric         Context,
7010b57cec5SDimitry Andric         Z3_mk_fpa_to_fp_float(Context.Context, toZ3Expr(*RoundingMode).AST,
7020b57cec5SDimitry Andric                               toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   SMTExprRef mkSBVtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
7060b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
7070b57cec5SDimitry Andric     return newExprRef(Z3Expr(
7080b57cec5SDimitry Andric         Context,
7090b57cec5SDimitry Andric         Z3_mk_fpa_to_fp_signed(Context.Context, toZ3Expr(*RoundingMode).AST,
7100b57cec5SDimitry Andric                                toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
7110b57cec5SDimitry Andric   }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric   SMTExprRef mkUBVtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
7140b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
7150b57cec5SDimitry Andric     return newExprRef(Z3Expr(
7160b57cec5SDimitry Andric         Context,
7170b57cec5SDimitry Andric         Z3_mk_fpa_to_fp_unsigned(Context.Context, toZ3Expr(*RoundingMode).AST,
7180b57cec5SDimitry Andric                                  toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
7190b57cec5SDimitry Andric   }
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric   SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) override {
7220b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
7230b57cec5SDimitry Andric     return newExprRef(Z3Expr(
7240b57cec5SDimitry Andric         Context, Z3_mk_fpa_to_sbv(Context.Context, toZ3Expr(*RoundingMode).AST,
7250b57cec5SDimitry Andric                                   toZ3Expr(*From).AST, ToWidth)));
7260b57cec5SDimitry Andric   }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) override {
7290b57cec5SDimitry Andric     SMTExprRef RoundingMode = getFloatRoundingMode();
7300b57cec5SDimitry Andric     return newExprRef(Z3Expr(
7310b57cec5SDimitry Andric         Context, Z3_mk_fpa_to_ubv(Context.Context, toZ3Expr(*RoundingMode).AST,
7320b57cec5SDimitry Andric                                   toZ3Expr(*From).AST, ToWidth)));
7330b57cec5SDimitry Andric   }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   SMTExprRef mkBoolean(const bool b) override {
7360b57cec5SDimitry Andric     return newExprRef(Z3Expr(Context, b ? Z3_mk_true(Context.Context)
7370b57cec5SDimitry Andric                                         : Z3_mk_false(Context.Context)));
7380b57cec5SDimitry Andric   }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) override {
7415ffd83dbSDimitry Andric     const Z3_sort Z3Sort = toZ3Sort(*getBitvectorSort(BitWidth)).Sort;
7425ffd83dbSDimitry Andric 
7435ffd83dbSDimitry Andric     // Slow path, when 64 bits are not enough.
7441ac55f4cSDimitry Andric     if (LLVM_UNLIKELY(!Int.isRepresentableByInt64())) {
7455ffd83dbSDimitry Andric       SmallString<40> Buffer;
7465ffd83dbSDimitry Andric       Int.toString(Buffer, 10);
7475ffd83dbSDimitry Andric       return newExprRef(Z3Expr(
7485ffd83dbSDimitry Andric           Context, Z3_mk_numeral(Context.Context, Buffer.c_str(), Z3Sort)));
7495ffd83dbSDimitry Andric     }
7505ffd83dbSDimitry Andric 
7515ffd83dbSDimitry Andric     const int64_t BitReprAsSigned = Int.getExtValue();
7525ffd83dbSDimitry Andric     const uint64_t BitReprAsUnsigned =
7535ffd83dbSDimitry Andric         reinterpret_cast<const uint64_t &>(BitReprAsSigned);
7545ffd83dbSDimitry Andric 
7555ffd83dbSDimitry Andric     Z3_ast Literal =
7565ffd83dbSDimitry Andric         Int.isSigned()
7575ffd83dbSDimitry Andric             ? Z3_mk_int64(Context.Context, BitReprAsSigned, Z3Sort)
7585ffd83dbSDimitry Andric             : Z3_mk_unsigned_int64(Context.Context, BitReprAsUnsigned, Z3Sort);
7595ffd83dbSDimitry Andric     return newExprRef(Z3Expr(Context, Literal));
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   SMTExprRef mkFloat(const llvm::APFloat Float) override {
7630b57cec5SDimitry Andric     SMTSortRef Sort =
7640b57cec5SDimitry Andric         getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics()));
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric     llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false);
7670b57cec5SDimitry Andric     SMTExprRef Z3Int = mkBitvector(Int, Int.getBitWidth());
7680b57cec5SDimitry Andric     return newExprRef(Z3Expr(
7690b57cec5SDimitry Andric         Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST,
7700b57cec5SDimitry Andric                                     toZ3Sort(*Sort).Sort)));
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) override {
7740b57cec5SDimitry Andric     return newExprRef(
7750b57cec5SDimitry Andric         Z3Expr(Context, Z3_mk_const(Context.Context,
7760b57cec5SDimitry Andric                                     Z3_mk_string_symbol(Context.Context, Name),
7770b57cec5SDimitry Andric                                     toZ3Sort(*Sort).Sort)));
7780b57cec5SDimitry Andric   }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
7810b57cec5SDimitry Andric                             bool isUnsigned) override {
7820b57cec5SDimitry Andric     return llvm::APSInt(
7830b57cec5SDimitry Andric         llvm::APInt(BitWidth,
7840b57cec5SDimitry Andric                     Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST),
7850b57cec5SDimitry Andric                     10),
7860b57cec5SDimitry Andric         isUnsigned);
7870b57cec5SDimitry Andric   }
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric   bool getBoolean(const SMTExprRef &Exp) override {
7900b57cec5SDimitry Andric     return Z3_get_bool_value(Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE;
7910b57cec5SDimitry Andric   }
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric   SMTExprRef getFloatRoundingMode() override {
7940b57cec5SDimitry Andric     // TODO: Don't assume nearest ties to even rounding mode
7950b57cec5SDimitry Andric     return newExprRef(Z3Expr(Context, Z3_mk_fpa_rne(Context.Context)));
7960b57cec5SDimitry Andric   }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric   bool toAPFloat(const SMTSortRef &Sort, const SMTExprRef &AST,
7990b57cec5SDimitry Andric                  llvm::APFloat &Float, bool useSemantics) {
8000b57cec5SDimitry Andric     assert(Sort->isFloatSort() && "Unsupported sort to floating-point!");
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric     llvm::APSInt Int(Sort->getFloatSortSize(), true);
8030b57cec5SDimitry Andric     const llvm::fltSemantics &Semantics =
8040b57cec5SDimitry Andric         getFloatSemantics(Sort->getFloatSortSize());
8050b57cec5SDimitry Andric     SMTSortRef BVSort = getBitvectorSort(Sort->getFloatSortSize());
8060b57cec5SDimitry Andric     if (!toAPSInt(BVSort, AST, Int, true)) {
8070b57cec5SDimitry Andric       return false;
8080b57cec5SDimitry Andric     }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric     if (useSemantics && !areEquivalent(Float.getSemantics(), Semantics)) {
8110b57cec5SDimitry Andric       assert(false && "Floating-point types don't match!");
8120b57cec5SDimitry Andric       return false;
8130b57cec5SDimitry Andric     }
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric     Float = llvm::APFloat(Semantics, Int);
8160b57cec5SDimitry Andric     return true;
8170b57cec5SDimitry Andric   }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   bool toAPSInt(const SMTSortRef &Sort, const SMTExprRef &AST,
8200b57cec5SDimitry Andric                 llvm::APSInt &Int, bool useSemantics) {
8210b57cec5SDimitry Andric     if (Sort->isBitvectorSort()) {
8220b57cec5SDimitry Andric       if (useSemantics && Int.getBitWidth() != Sort->getBitvectorSortSize()) {
8230b57cec5SDimitry Andric         assert(false && "Bitvector types don't match!");
8240b57cec5SDimitry Andric         return false;
8250b57cec5SDimitry Andric       }
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric       // FIXME: This function is also used to retrieve floating-point values,
8280b57cec5SDimitry Andric       // which can be 16, 32, 64 or 128 bits long. Bitvectors can be anything
8290b57cec5SDimitry Andric       // between 1 and 64 bits long, which is the reason we have this weird
8300b57cec5SDimitry Andric       // guard. In the future, we need proper calls in the backend to retrieve
8310b57cec5SDimitry Andric       // floating-points and its special values (NaN, +/-infinity, +/-zero),
8320b57cec5SDimitry Andric       // then we can drop this weird condition.
8330b57cec5SDimitry Andric       if (Sort->getBitvectorSortSize() <= 64 ||
8340b57cec5SDimitry Andric           Sort->getBitvectorSortSize() == 128) {
8350b57cec5SDimitry Andric         Int = getBitvector(AST, Int.getBitWidth(), Int.isUnsigned());
8360b57cec5SDimitry Andric         return true;
8370b57cec5SDimitry Andric       }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric       assert(false && "Bitwidth not supported!");
8400b57cec5SDimitry Andric       return false;
8410b57cec5SDimitry Andric     }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric     if (Sort->isBooleanSort()) {
8440b57cec5SDimitry Andric       if (useSemantics && Int.getBitWidth() < 1) {
8450b57cec5SDimitry Andric         assert(false && "Boolean type doesn't match!");
8460b57cec5SDimitry Andric         return false;
8470b57cec5SDimitry Andric       }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric       Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), getBoolean(AST)),
8500b57cec5SDimitry Andric                          Int.isUnsigned());
8510b57cec5SDimitry Andric       return true;
8520b57cec5SDimitry Andric     }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric     llvm_unreachable("Unsupported sort to integer!");
8550b57cec5SDimitry Andric   }
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric   bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) override {
8580b57cec5SDimitry Andric     Z3Model Model(Context, Z3_solver_get_model(Context.Context, Solver));
8590b57cec5SDimitry Andric     Z3_func_decl Func = Z3_get_app_decl(
8600b57cec5SDimitry Andric         Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
8610b57cec5SDimitry Andric     if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
8620b57cec5SDimitry Andric       return false;
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric     SMTExprRef Assign = newExprRef(
8650b57cec5SDimitry Andric         Z3Expr(Context,
8660b57cec5SDimitry Andric                Z3_model_get_const_interp(Context.Context, Model.Model, Func)));
8670b57cec5SDimitry Andric     SMTSortRef Sort = getSort(Assign);
8680b57cec5SDimitry Andric     return toAPSInt(Sort, Assign, Int, true);
8690b57cec5SDimitry Andric   }
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric   bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) override {
8720b57cec5SDimitry Andric     Z3Model Model(Context, Z3_solver_get_model(Context.Context, Solver));
8730b57cec5SDimitry Andric     Z3_func_decl Func = Z3_get_app_decl(
8740b57cec5SDimitry Andric         Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
8750b57cec5SDimitry Andric     if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
8760b57cec5SDimitry Andric       return false;
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric     SMTExprRef Assign = newExprRef(
8790b57cec5SDimitry Andric         Z3Expr(Context,
8800b57cec5SDimitry Andric                Z3_model_get_const_interp(Context.Context, Model.Model, Func)));
8810b57cec5SDimitry Andric     SMTSortRef Sort = getSort(Assign);
8820b57cec5SDimitry Andric     return toAPFloat(Sort, Assign, Float, true);
8830b57cec5SDimitry Andric   }
8840b57cec5SDimitry Andric 
885bdd1243dSDimitry Andric   std::optional<bool> check() const override {
8860fca6ea1SDimitry Andric     Z3_solver_set_params(Context.Context, Solver, Params);
8870b57cec5SDimitry Andric     Z3_lbool res = Z3_solver_check(Context.Context, Solver);
8880b57cec5SDimitry Andric     if (res == Z3_L_TRUE)
8890b57cec5SDimitry Andric       return true;
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric     if (res == Z3_L_FALSE)
8920b57cec5SDimitry Andric       return false;
8930b57cec5SDimitry Andric 
894bdd1243dSDimitry Andric     return std::nullopt;
8950b57cec5SDimitry Andric   }
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   void push() override { return Z3_solver_push(Context.Context, Solver); }
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric   void pop(unsigned NumStates = 1) override {
9000b57cec5SDimitry Andric     assert(Z3_solver_get_num_scopes(Context.Context, Solver) >= NumStates);
9010b57cec5SDimitry Andric     return Z3_solver_pop(Context.Context, Solver, NumStates);
9020b57cec5SDimitry Andric   }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   bool isFPSupported() override { return true; }
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   /// Reset the solver and remove all constraints.
9070b57cec5SDimitry Andric   void reset() override { Z3_solver_reset(Context.Context, Solver); }
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
9100b57cec5SDimitry Andric     OS << Z3_solver_to_string(Context.Context, Solver);
9110b57cec5SDimitry Andric   }
9120fca6ea1SDimitry Andric 
9130fca6ea1SDimitry Andric   void setUnsignedParam(StringRef Key, unsigned Value) override {
9140fca6ea1SDimitry Andric     Z3_symbol Sym = Z3_mk_string_symbol(Context.Context, Key.str().c_str());
9150fca6ea1SDimitry Andric     Z3_params_set_uint(Context.Context, Params, Sym, Value);
9160fca6ea1SDimitry Andric   }
9170fca6ea1SDimitry Andric 
9180fca6ea1SDimitry Andric   void setBoolParam(StringRef Key, bool Value) override {
9190fca6ea1SDimitry Andric     Z3_symbol Sym = Z3_mk_string_symbol(Context.Context, Key.str().c_str());
9200fca6ea1SDimitry Andric     Z3_params_set_bool(Context.Context, Params, Sym, Value);
9210fca6ea1SDimitry Andric   }
9220fca6ea1SDimitry Andric 
9230fca6ea1SDimitry Andric   std::unique_ptr<SMTSolverStatistics> getStatistics() const override;
9240b57cec5SDimitry Andric }; // end class Z3Solver
9250b57cec5SDimitry Andric 
9260fca6ea1SDimitry Andric class Z3Statistics final : public SMTSolverStatistics {
9270fca6ea1SDimitry Andric public:
9280fca6ea1SDimitry Andric   double getDouble(StringRef Key) const override {
9290fca6ea1SDimitry Andric     auto It = DoubleValues.find(Key.str());
9300fca6ea1SDimitry Andric     assert(It != DoubleValues.end());
9310fca6ea1SDimitry Andric     return It->second;
9320fca6ea1SDimitry Andric   };
9330fca6ea1SDimitry Andric   unsigned getUnsigned(StringRef Key) const override {
9340fca6ea1SDimitry Andric     auto It = UnsignedValues.find(Key.str());
9350fca6ea1SDimitry Andric     assert(It != UnsignedValues.end());
9360fca6ea1SDimitry Andric     return It->second;
9370fca6ea1SDimitry Andric   };
9380fca6ea1SDimitry Andric 
9390fca6ea1SDimitry Andric   void print(raw_ostream &OS) const override {
9400fca6ea1SDimitry Andric     for (auto const &[K, V] : UnsignedValues) {
9410fca6ea1SDimitry Andric       OS << K << ": " << V << '\n';
9420fca6ea1SDimitry Andric     }
9430fca6ea1SDimitry Andric     for (auto const &[K, V] : DoubleValues) {
9440fca6ea1SDimitry Andric       write_double(OS << K << ": ", V, FloatStyle::Fixed);
9450fca6ea1SDimitry Andric       OS << '\n';
9460fca6ea1SDimitry Andric     }
9470fca6ea1SDimitry Andric   }
9480fca6ea1SDimitry Andric 
9490fca6ea1SDimitry Andric private:
9500fca6ea1SDimitry Andric   friend class Z3Solver;
9510fca6ea1SDimitry Andric   std::unordered_map<std::string, unsigned> UnsignedValues;
9520fca6ea1SDimitry Andric   std::unordered_map<std::string, double> DoubleValues;
9530fca6ea1SDimitry Andric };
9540fca6ea1SDimitry Andric 
9550fca6ea1SDimitry Andric std::unique_ptr<SMTSolverStatistics> Z3Solver::getStatistics() const {
9560fca6ea1SDimitry Andric   auto const &C = Context.Context;
9570fca6ea1SDimitry Andric   Z3_stats S = Z3_solver_get_statistics(C, Solver);
9580fca6ea1SDimitry Andric   Z3_stats_inc_ref(C, S);
9590fca6ea1SDimitry Andric   auto StatsGuard = llvm::make_scope_exit([&C, &S] { Z3_stats_dec_ref(C, S); });
9600fca6ea1SDimitry Andric   Z3Statistics Result;
9610fca6ea1SDimitry Andric 
9620fca6ea1SDimitry Andric   unsigned NumKeys = Z3_stats_size(C, S);
9630fca6ea1SDimitry Andric   for (unsigned Idx = 0; Idx < NumKeys; ++Idx) {
9640fca6ea1SDimitry Andric     const char *Key = Z3_stats_get_key(C, S, Idx);
9650fca6ea1SDimitry Andric     if (Z3_stats_is_uint(C, S, Idx)) {
9660fca6ea1SDimitry Andric       auto Value = Z3_stats_get_uint_value(C, S, Idx);
9670fca6ea1SDimitry Andric       Result.UnsignedValues.try_emplace(Key, Value);
9680fca6ea1SDimitry Andric     } else {
9690fca6ea1SDimitry Andric       assert(Z3_stats_is_double(C, S, Idx));
9700fca6ea1SDimitry Andric       auto Value = Z3_stats_get_double_value(C, S, Idx);
9710fca6ea1SDimitry Andric       Result.DoubleValues.try_emplace(Key, Value);
9720fca6ea1SDimitry Andric     }
9730fca6ea1SDimitry Andric   }
9740fca6ea1SDimitry Andric   return std::make_unique<Z3Statistics>(std::move(Result));
9750fca6ea1SDimitry Andric }
9760fca6ea1SDimitry Andric 
9770b57cec5SDimitry Andric } // end anonymous namespace
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric #endif
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric llvm::SMTSolverRef llvm::CreateZ3Solver() {
9820b57cec5SDimitry Andric #if LLVM_WITH_Z3
9838bcb0991SDimitry Andric   return std::make_unique<Z3Solver>();
9840b57cec5SDimitry Andric #else
9850b57cec5SDimitry Andric   llvm::report_fatal_error("LLVM was not compiled with Z3 support, rebuild "
9860b57cec5SDimitry Andric                            "with -DLLVM_ENABLE_Z3_SOLVER=ON",
9870b57cec5SDimitry Andric                            false);
9880b57cec5SDimitry Andric   return nullptr;
9890b57cec5SDimitry Andric #endif
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric LLVM_DUMP_METHOD void SMTSort::dump() const { print(llvm::errs()); }
9930b57cec5SDimitry Andric LLVM_DUMP_METHOD void SMTExpr::dump() const { print(llvm::errs()); }
9940b57cec5SDimitry Andric LLVM_DUMP_METHOD void SMTSolver::dump() const { print(llvm::errs()); }
9950fca6ea1SDimitry Andric LLVM_DUMP_METHOD void SMTSolverStatistics::dump() const { print(llvm::errs()); }
996