10#include "llvm/Config/config.h"
22#include <unordered_map>
30 friend class Z3Context;
32 Z3_config Config = Z3_mk_config();
36 Z3Config(
const Z3Config &) =
delete;
37 Z3Config(Z3Config &&) =
default;
38 Z3Config &operator=(Z3Config &) =
delete;
39 Z3Config &operator=(Z3Config &&) =
default;
40 ~Z3Config() { Z3_del_config(Config); }
44void Z3ErrorHandler(Z3_context Context, Z3_error_code
Error) {
56 Context = Z3_mk_context_rc(Config.Config);
59 Z3_set_error_handler(
Context, Z3ErrorHandler);
62 Z3Context(
const Z3Context &) =
delete;
63 Z3Context(Z3Context &&) =
default;
64 Z3Context &operator=(Z3Context &) =
delete;
65 Z3Context &operator=(Z3Context &&) =
default;
75 friend class Z3Solver;
83 Z3Sort(Z3Context &
C, Z3_sort ZS) :
Context(
C), Sort(ZS) {
84 Z3_inc_ref(
Context.Context,
reinterpret_cast<Z3_ast
>(Sort));
89 Z3_inc_ref(
Context.Context,
reinterpret_cast<Z3_ast
>(Sort));
94 Z3Sort &operator=(
const Z3Sort &
Other) {
95 Z3_inc_ref(
Context.Context,
reinterpret_cast<Z3_ast
>(
Other.Sort));
96 Z3_dec_ref(
Context.Context,
reinterpret_cast<Z3_ast
>(Sort));
101 Z3Sort(Z3Sort &&
Other) =
delete;
102 Z3Sort &operator=(Z3Sort &&
Other) =
delete;
106 Z3_dec_ref(
Context.Context,
reinterpret_cast<Z3_ast
>(Sort));
109 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
111 Z3_get_ast_id(
Context.Context,
reinterpret_cast<Z3_ast
>(Sort)));
114 bool isBitvectorSortImpl()
const override {
115 return (Z3_get_sort_kind(
Context.Context, Sort) == Z3_BV_SORT);
118 bool isFloatSortImpl()
const override {
119 return (Z3_get_sort_kind(
Context.Context, Sort) == Z3_FLOATING_POINT_SORT);
122 bool isBooleanSortImpl()
const override {
123 return (Z3_get_sort_kind(
Context.Context, Sort) == Z3_BOOL_SORT);
126 unsigned getBitvectorSortSizeImpl()
const override {
127 return Z3_get_bv_sort_size(
Context.Context, Sort);
130 unsigned getFloatSortSizeImpl()
const override {
131 return Z3_fpa_get_ebits(
Context.Context, Sort) +
132 Z3_fpa_get_sbits(
Context.Context, Sort);
135 bool equal_to(SMTSort
const &
Other)
const override {
136 return Z3_is_eq_sort(
Context.Context, Sort,
137 static_cast<const Z3Sort &
>(
Other).Sort);
140 void print(raw_ostream &OS)
const override {
141 OS << Z3_sort_to_string(
Context.Context, Sort);
145static const Z3Sort &toZ3Sort(
const SMTSort &S) {
146 return static_cast<const Z3Sort &
>(S);
150 friend class Z3Solver;
157 Z3Expr(Z3Context &
C, Z3_ast ZA) : SMTExpr(),
Context(
C), AST(ZA) {
158 Z3_inc_ref(
Context.Context, AST);
163 Z3_inc_ref(
Context.Context, AST);
168 Z3Expr &operator=(
const Z3Expr &
Other) {
170 Z3_dec_ref(
Context.Context, AST);
175 Z3Expr(Z3Expr &&
Other) =
delete;
176 Z3Expr &operator=(Z3Expr &&
Other) =
delete;
180 Z3_dec_ref(
Context.Context, AST);
183 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
184 ID.AddInteger(Z3_get_ast_id(
Context.Context, AST));
188 bool equal_to(SMTExpr
const &
Other)
const override {
191 static_cast<const Z3Expr &
>(
Other).AST)) &&
192 "AST's must have the same sort");
193 return Z3_is_eq_ast(
Context.Context, AST,
194 static_cast<const Z3Expr &
>(
Other).AST);
197 void print(raw_ostream &OS)
const override {
198 OS << Z3_ast_to_string(
Context.Context, AST);
202static const Z3Expr &toZ3Expr(
const SMTExpr &
E) {
203 return static_cast<const Z3Expr &
>(
E);
207 friend class Z3Solver;
215 Z3_model_inc_ref(
Context.Context, Model);
218 Z3Model(
const Z3Model &
Other) =
delete;
219 Z3Model(Z3Model &&
Other) =
delete;
220 Z3Model &operator=(Z3Model &
Other) =
delete;
221 Z3Model &operator=(Z3Model &&
Other) =
delete;
225 Z3_model_dec_ref(
Context.Context, Model);
228 void print(raw_ostream &OS)
const {
229 OS << Z3_model_to_string(
Context.Context, Model);
266 friend class Z3ConstraintManager;
270 Z3_solver Solver = [
this] {
271 Z3_solver S = Z3_mk_simple_solver(
Context.Context);
272 Z3_solver_inc_ref(
Context.Context, S);
276 Z3_params Params = [
this] {
277 Z3_params
P = Z3_mk_params(
Context.Context);
278 Z3_params_inc_ref(
Context.Context,
P);
283 std::set<Z3Sort> CachedSorts;
286 std::set<Z3Expr> CachedExprs;
289 Z3Solver() =
default;
290 Z3Solver(
const Z3Solver &
Other) =
delete;
291 Z3Solver(Z3Solver &&
Other) =
delete;
292 Z3Solver &operator=(Z3Solver &
Other) =
delete;
293 Z3Solver &operator=(Z3Solver &&
Other) =
delete;
295 ~Z3Solver()
override {
296 Z3_params_dec_ref(
Context.Context, Params);
297 Z3_solver_dec_ref(
Context.Context, Solver);
300 void addConstraint(
const SMTExprRef &Exp)
const override {
301 Z3_solver_assert(
Context.Context, Solver, toZ3Expr(*Exp).AST);
307 auto It = CachedSorts.insert(toZ3Sort(Sort));
314 auto It = CachedExprs.insert(toZ3Expr(Exp));
319 return newSortRef(Z3Sort(
Context, Z3_mk_bool_sort(
Context.Context)));
329 Z3Sort(
Context, Z3_get_sort(
Context.Context, toZ3Expr(*Exp).AST)));
333 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_16(
Context.Context)));
337 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_32(
Context.Context)));
341 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_64(
Context.Context)));
345 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_128(
Context.Context)));
350 Z3Expr(
Context, Z3_mk_bvneg(
Context.Context, toZ3Expr(*Exp).AST)));
355 Z3Expr(
Context, Z3_mk_bvnot(
Context.Context, toZ3Expr(*Exp).AST)));
366 toZ3Expr(*RHS).AST)));
372 toZ3Expr(*RHS).AST)));
378 toZ3Expr(*RHS).AST)));
384 toZ3Expr(*RHS).AST)));
390 toZ3Expr(*RHS).AST)));
396 toZ3Expr(*RHS).AST)));
402 toZ3Expr(*RHS).AST)));
408 toZ3Expr(*RHS).AST)));
414 toZ3Expr(*RHS).AST)));
420 toZ3Expr(*RHS).AST)));
426 toZ3Expr(*RHS).AST)));
432 toZ3Expr(*RHS).AST)));
438 toZ3Expr(*RHS).AST)));
444 toZ3Expr(*RHS).AST)));
450 toZ3Expr(*RHS).AST)));
456 toZ3Expr(*RHS).AST)));
462 toZ3Expr(*RHS).AST)));
468 toZ3Expr(*RHS).AST)));
474 toZ3Expr(*RHS).AST)));
480 toZ3Expr(*RHS).AST)));
486 toZ3Expr(*RHS).AST)));
490 Z3_ast
Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
491 return newExprRef(Z3Expr(
Context, Z3_mk_and(
Context.Context, 2, Args)));
495 Z3_ast
Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
496 return newExprRef(Z3Expr(
Context, Z3_mk_or(
Context.Context, 2, Args)));
502 toZ3Expr(*RHS).AST)));
507 Z3Expr(
Context, Z3_mk_fpa_neg(
Context.Context, toZ3Expr(*Exp).AST)));
511 return newExprRef(Z3Expr(
512 Context, Z3_mk_fpa_is_infinite(
Context.Context, toZ3Expr(*Exp).AST)));
517 Z3Expr(
Context, Z3_mk_fpa_is_nan(
Context.Context, toZ3Expr(*Exp).AST)));
521 return newExprRef(Z3Expr(
522 Context, Z3_mk_fpa_is_normal(
Context.Context, toZ3Expr(*Exp).AST)));
526 return newExprRef(Z3Expr(
527 Context, Z3_mk_fpa_is_zero(
Context.Context, toZ3Expr(*Exp).AST)));
534 Z3_mk_fpa_mul(
Context.Context, toZ3Expr(*RoundingMode).AST,
535 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
542 Z3_mk_fpa_div(
Context.Context, toZ3Expr(*RoundingMode).AST,
543 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
548 Z3Expr(
Context, Z3_mk_fpa_rem(
Context.Context, toZ3Expr(*LHS).AST,
549 toZ3Expr(*RHS).AST)));
556 Z3_mk_fpa_add(
Context.Context, toZ3Expr(*RoundingMode).AST,
557 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
564 Z3_mk_fpa_sub(
Context.Context, toZ3Expr(*RoundingMode).AST,
565 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
571 toZ3Expr(*RHS).AST)));
577 toZ3Expr(*RHS).AST)));
582 Z3Expr(
Context, Z3_mk_fpa_leq(
Context.Context, toZ3Expr(*LHS).AST,
583 toZ3Expr(*RHS).AST)));
588 Z3Expr(
Context, Z3_mk_fpa_geq(
Context.Context, toZ3Expr(*LHS).AST,
589 toZ3Expr(*RHS).AST)));
595 toZ3Expr(*RHS).AST)));
602 toZ3Expr(*T).AST, toZ3Expr(*F).AST)));
606 return newExprRef(Z3Expr(
607 Context, Z3_mk_sign_ext(
Context.Context, i, toZ3Expr(*Exp).AST)));
611 return newExprRef(Z3Expr(
612 Context, Z3_mk_zero_ext(
Context.Context, i, toZ3Expr(*Exp).AST)));
618 toZ3Expr(*Exp).AST)));
625 return newExprRef(Z3Expr(
626 Context, Z3_mk_bvadd_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
634 return newExprRef(Z3Expr(
635 Context, Z3_mk_bvadd_no_underflow(
Context.Context, toZ3Expr(*LHS).AST,
636 toZ3Expr(*RHS).AST)));
643 return newExprRef(Z3Expr(
644 Context, Z3_mk_bvsub_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
645 toZ3Expr(*RHS).AST)));
652 return newExprRef(Z3Expr(
653 Context, Z3_mk_bvsub_no_underflow(
Context.Context, toZ3Expr(*LHS).AST,
661 return newExprRef(Z3Expr(
662 Context, Z3_mk_bvsdiv_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
663 toZ3Expr(*RHS).AST)));
669 return newExprRef(Z3Expr(
670 Context, Z3_mk_bvneg_no_overflow(
Context.Context, toZ3Expr(*Exp).AST)));
677 return newExprRef(Z3Expr(
678 Context, Z3_mk_bvmul_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
686 return newExprRef(Z3Expr(
687 Context, Z3_mk_bvmul_no_underflow(
Context.Context, toZ3Expr(*LHS).AST,
688 toZ3Expr(*RHS).AST)));
694 toZ3Expr(*RHS).AST)));
699 return newExprRef(Z3Expr(
701 Z3_mk_fpa_to_fp_float(
Context.Context, toZ3Expr(*RoundingMode).AST,
702 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
707 return newExprRef(Z3Expr(
709 Z3_mk_fpa_to_fp_signed(
Context.Context, toZ3Expr(*RoundingMode).AST,
710 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
715 return newExprRef(Z3Expr(
717 Z3_mk_fpa_to_fp_unsigned(
Context.Context, toZ3Expr(*RoundingMode).AST,
718 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
723 return newExprRef(Z3Expr(
724 Context, Z3_mk_fpa_to_sbv(
Context.Context, toZ3Expr(*RoundingMode).AST,
725 toZ3Expr(*From).AST, ToWidth)));
730 return newExprRef(Z3Expr(
731 Context, Z3_mk_fpa_to_ubv(
Context.Context, toZ3Expr(*RoundingMode).AST,
732 toZ3Expr(*From).AST, ToWidth)));
737 : Z3_mk_false(
Context.Context)));
741 const Z3_sort Z3Sort = toZ3Sort(*getBitvectorSort(
BitWidth)).Sort;
745 SmallString<40> Buffer;
746 Int.toString(Buffer, 10);
747 return newExprRef(Z3Expr(
751 const int64_t BitReprAsSigned =
Int.getExtValue();
752 const uint64_t BitReprAsUnsigned =
753 reinterpret_cast<const uint64_t &
>(BitReprAsSigned);
757 ? Z3_mk_int64(
Context.Context, BitReprAsSigned, Z3Sort)
758 : Z3_mk_unsigned_int64(
Context.
Context, BitReprAsUnsigned, Z3Sort);
766 llvm::APSInt
Int = llvm::APSInt(
Float.bitcastToAPInt(),
false);
768 return newExprRef(Z3Expr(
769 Context, Z3_mk_fpa_to_fp_bv(
Context.Context, toZ3Expr(*Z3Int).AST,
770 toZ3Sort(*Sort).Sort)));
776 Z3_mk_string_symbol(
Context.Context, Name),
777 toZ3Sort(*Sort).Sort)));
781 bool isUnsigned)
override {
784 Z3_get_numeral_string(
Context.Context, toZ3Expr(*Exp).AST),
789 bool getBoolean(
const SMTExprRef &Exp)
override {
790 return Z3_get_bool_value(
Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE;
795 return newExprRef(Z3Expr(
Context, Z3_mk_fpa_rne(
Context.Context)));
799 llvm::APFloat &
Float,
bool useSemantics) {
803 const llvm::fltSemantics &Semantics =
806 if (!toAPSInt(BVSort, AST,
Int,
true)) {
810 if (useSemantics && !areEquivalent(
Float.getSemantics(), Semantics)) {
811 assert(
false &&
"Floating-point types don't match!");
815 Float = llvm::APFloat(Semantics,
Int);
820 llvm::APSInt &
Int,
bool useSemantics) {
823 assert(
false &&
"Bitvector types don't match!");
835 Int = getBitvector(AST,
Int.getBitWidth(),
Int.isUnsigned());
839 assert(
false &&
"Bitwidth not supported!");
844 if (useSemantics &&
Int.getBitWidth() < 1) {
845 assert(
false &&
"Boolean type doesn't match!");
849 Int = llvm::APSInt(llvm::APInt(
Int.getBitWidth(), getBoolean(AST)),
857 bool getInterpretation(
const SMTExprRef &Exp, llvm::APSInt &
Int)
override {
859 Z3_func_decl
Func = Z3_get_app_decl(
861 if (Z3_model_has_interp(
Context.Context,
Model.Model, Func) != Z3_L_TRUE)
866 Z3_model_get_const_interp(
Context.Context,
Model.Model, Func)));
868 return toAPSInt(Sort, Assign,
Int,
true);
871 bool getInterpretation(
const SMTExprRef &Exp, llvm::APFloat &
Float)
override {
873 Z3_func_decl
Func = Z3_get_app_decl(
875 if (Z3_model_has_interp(
Context.Context,
Model.Model, Func) != Z3_L_TRUE)
880 Z3_model_get_const_interp(
Context.Context,
Model.Model, Func)));
882 return toAPFloat(Sort, Assign,
Float,
true);
885 std::optional<bool> check()
const override {
886 Z3_solver_set_params(
Context.Context, Solver, Params);
887 Z3_lbool res = Z3_solver_check(
Context.Context, Solver);
888 if (res == Z3_L_TRUE)
891 if (res == Z3_L_FALSE)
897 void push()
override {
return Z3_solver_push(
Context.Context, Solver); }
899 void pop(
unsigned NumStates = 1)
override {
900 assert(Z3_solver_get_num_scopes(
Context.Context, Solver) >= NumStates);
901 return Z3_solver_pop(
Context.Context, Solver, NumStates);
904 bool isFPSupported()
override {
return true; }
907 void reset()
override { Z3_solver_reset(
Context.Context, Solver); }
909 void print(raw_ostream &OS)
const override {
910 OS << Z3_solver_to_string(
Context.Context, Solver);
913 void setUnsignedParam(StringRef
Key,
unsigned Value)
override {
914 Z3_symbol Sym = Z3_mk_string_symbol(
Context.Context,
Key.str().c_str());
915 Z3_params_set_uint(
Context.Context, Params, Sym,
Value);
918 void setBoolParam(StringRef
Key,
bool Value)
override {
919 Z3_symbol Sym = Z3_mk_string_symbol(
Context.Context,
Key.str().c_str());
920 Z3_params_set_bool(
Context.Context, Params, Sym,
Value);
923 std::unique_ptr<SMTSolverStatistics> getStatistics()
const override;
929 auto It = DoubleValues.find(
Key.str());
930 assert(It != DoubleValues.end());
934 auto It = UnsignedValues.find(
Key.str());
935 if (It == UnsignedValues.end())
940 void print(raw_ostream &OS)
const override {
941 for (
auto const &[K, V] : UnsignedValues) {
942 OS <<
K <<
": " <<
V <<
'\n';
944 for (
auto const &[K, V] : DoubleValues) {
951 friend class Z3Solver;
952 std::unordered_map<std::string, unsigned> UnsignedValues;
953 std::unordered_map<std::string, double> DoubleValues;
956std::unique_ptr<SMTSolverStatistics> Z3Solver::getStatistics()
const {
957 auto const &
C = Context.Context;
958 Z3_stats S = Z3_solver_get_statistics(
C, Solver);
959 Z3_stats_inc_ref(
C, S);
963 unsigned NumKeys = Z3_stats_size(
C, S);
964 for (
unsigned Idx = 0; Idx < NumKeys; ++Idx) {
965 const char *
Key = Z3_stats_get_key(
C, S, Idx);
966 if (Z3_stats_is_uint(
C, S, Idx)) {
967 auto Value = Z3_stats_get_uint_value(
C, S, Idx);
970 assert(Z3_stats_is_double(
C, S, Idx));
971 auto Value = Z3_stats_get_double_value(
C, S, Idx);
975 return std::make_unique<Z3Statistics>(std::move(Result));
984 return std::make_unique<Z3Solver>();
987 "with -DLLVM_ENABLE_Z3_SOLVER=ON",
993#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static bool isSigned(unsigned int Opcode)
const SmallVectorImpl< MachineOperand > & Cond
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallString class.
Lightweight error class with error context and mandatory checking.
Generic base class for SMT exprs.
LLVM_DUMP_METHOD void dump() const
virtual void print(raw_ostream &OS) const =0
virtual unsigned getUnsigned(llvm::StringRef) const =0
LLVM_DUMP_METHOD void dump() const
virtual double getDouble(llvm::StringRef) const =0
virtual void print(raw_ostream &OS) const =0
Generic base class for SMT Solvers.
virtual void print(raw_ostream &OS) const =0
LLVM_DUMP_METHOD void dump() const
Generic base class for SMT sorts.
virtual void print(raw_ostream &OS) const =0
virtual bool isBitvectorSort() const
Returns true if the sort is a bitvector, calls isBitvectorSortImpl().
virtual bool isFloatSort() const
Returns true if the sort is a floating-point, calls isFloatSortImpl().
virtual unsigned getFloatSortSize() const
Returns the floating-point size, fails if the sort is not a floating-point Calls getFloatSortSizeImpl...
virtual unsigned getBitvectorSortSize() const
Returns the bitvector size, fails if the sort is not a bitvector Calls getBitvectorSortSizeImpl().
virtual bool isBooleanSort() const
Returns true if the sort is a boolean, calls isBooleanSortImpl().
LLVM_DUMP_METHOD void dump() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
const SMTExpr * SMTExprRef
Shared pointer for SMTExprs, used by SMTSolver API.
std::shared_ptr< SMTSolver > SMTSolverRef
Shared pointer for SMTSolvers.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RoundingMode
Rounding mode.
LLVM_ABI void write_double(raw_ostream &S, double D, FloatStyle Style, std::optional< size_t > Precision=std::nullopt)
constexpr unsigned BitWidth
const SMTSort * SMTSortRef
Shared pointer for SMTSorts, used by SMTSolver API.
LLVM_ABI SMTSolverRef CreateZ3Solver()
Convenience method to create and Z3Solver object.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static LLVM_ABI ExponentType semanticsMinExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsSizeInBits(const fltSemantics &)
static LLVM_ABI const fltSemantics & IEEEquad() LLVM_READNONE
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
static LLVM_ABI const fltSemantics & IEEEhalf() LLVM_READNONE