10#include "llvm/Config/config.h"
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);
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));
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);
268 Z3_solver Solver = [
this] {
269 Z3_solver S = Z3_mk_simple_solver(
Context.Context);
270 Z3_solver_inc_ref(
Context.Context, S);
274 Z3_params Params = [
this] {
275 Z3_params
P = Z3_mk_params(
Context.Context);
276 Z3_params_inc_ref(
Context.Context,
P);
281 std::set<Z3Sort> CachedSorts;
284 std::set<Z3Expr> CachedExprs;
287 Z3Solver() =
default;
288 Z3Solver(
const Z3Solver &
Other) =
delete;
289 Z3Solver(Z3Solver &&
Other) =
delete;
290 Z3Solver &operator=(Z3Solver &
Other) =
delete;
291 Z3Solver &operator=(Z3Solver &&
Other) =
delete;
293 ~Z3Solver()
override {
294 Z3_params_dec_ref(
Context.Context, Params);
295 Z3_solver_dec_ref(
Context.Context, Solver);
298 void addConstraint(
const SMTExprRef &Exp)
const override {
299 Z3_solver_assert(
Context.Context, Solver, toZ3Expr(*Exp).AST);
305 auto It = CachedSorts.insert(toZ3Sort(Sort));
312 auto It = CachedExprs.insert(toZ3Expr(Exp));
317 return newSortRef(Z3Sort(
Context, Z3_mk_bool_sort(
Context.Context)));
327 Z3Sort(
Context, Z3_get_sort(
Context.Context, toZ3Expr(*Exp).AST)));
331 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_16(
Context.Context)));
335 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_32(
Context.Context)));
339 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_64(
Context.Context)));
343 return newSortRef(Z3Sort(
Context, Z3_mk_fpa_sort_128(
Context.Context)));
348 Z3Expr(
Context, Z3_mk_bvneg(
Context.Context, toZ3Expr(*Exp).AST)));
353 Z3Expr(
Context, Z3_mk_bvnot(
Context.Context, toZ3Expr(*Exp).AST)));
364 toZ3Expr(*RHS).AST)));
370 toZ3Expr(*RHS).AST)));
376 toZ3Expr(*RHS).AST)));
382 toZ3Expr(*RHS).AST)));
388 toZ3Expr(*RHS).AST)));
394 toZ3Expr(*RHS).AST)));
400 toZ3Expr(*RHS).AST)));
406 toZ3Expr(*RHS).AST)));
412 toZ3Expr(*RHS).AST)));
418 toZ3Expr(*RHS).AST)));
424 toZ3Expr(*RHS).AST)));
430 toZ3Expr(*RHS).AST)));
436 toZ3Expr(*RHS).AST)));
442 toZ3Expr(*RHS).AST)));
448 toZ3Expr(*RHS).AST)));
454 toZ3Expr(*RHS).AST)));
460 toZ3Expr(*RHS).AST)));
466 toZ3Expr(*RHS).AST)));
472 toZ3Expr(*RHS).AST)));
478 toZ3Expr(*RHS).AST)));
484 toZ3Expr(*RHS).AST)));
488 Z3_ast
Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
489 return newExprRef(Z3Expr(
Context, Z3_mk_and(
Context.Context, 2, Args)));
493 Z3_ast
Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
494 return newExprRef(Z3Expr(
Context, Z3_mk_or(
Context.Context, 2, Args)));
500 toZ3Expr(*RHS).AST)));
505 Z3Expr(
Context, Z3_mk_fpa_neg(
Context.Context, toZ3Expr(*Exp).AST)));
509 return newExprRef(Z3Expr(
510 Context, Z3_mk_fpa_is_infinite(
Context.Context, toZ3Expr(*Exp).AST)));
515 Z3Expr(
Context, Z3_mk_fpa_is_nan(
Context.Context, toZ3Expr(*Exp).AST)));
519 return newExprRef(Z3Expr(
520 Context, Z3_mk_fpa_is_normal(
Context.Context, toZ3Expr(*Exp).AST)));
524 return newExprRef(Z3Expr(
525 Context, Z3_mk_fpa_is_zero(
Context.Context, toZ3Expr(*Exp).AST)));
532 Z3_mk_fpa_mul(
Context.Context, toZ3Expr(*RoundingMode).AST,
533 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
540 Z3_mk_fpa_div(
Context.Context, toZ3Expr(*RoundingMode).AST,
541 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
546 Z3Expr(
Context, Z3_mk_fpa_rem(
Context.Context, toZ3Expr(*LHS).AST,
547 toZ3Expr(*RHS).AST)));
554 Z3_mk_fpa_add(
Context.Context, toZ3Expr(*RoundingMode).AST,
555 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
562 Z3_mk_fpa_sub(
Context.Context, toZ3Expr(*RoundingMode).AST,
563 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
569 toZ3Expr(*RHS).AST)));
575 toZ3Expr(*RHS).AST)));
580 Z3Expr(
Context, Z3_mk_fpa_leq(
Context.Context, toZ3Expr(*LHS).AST,
581 toZ3Expr(*RHS).AST)));
586 Z3Expr(
Context, Z3_mk_fpa_geq(
Context.Context, toZ3Expr(*LHS).AST,
587 toZ3Expr(*RHS).AST)));
593 toZ3Expr(*RHS).AST)));
600 toZ3Expr(*T).AST, toZ3Expr(*F).AST)));
604 return newExprRef(Z3Expr(
605 Context, Z3_mk_sign_ext(
Context.Context, i, toZ3Expr(*Exp).AST)));
609 return newExprRef(Z3Expr(
610 Context, Z3_mk_zero_ext(
Context.Context, i, toZ3Expr(*Exp).AST)));
616 toZ3Expr(*Exp).AST)));
623 return newExprRef(Z3Expr(
624 Context, Z3_mk_bvadd_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
632 return newExprRef(Z3Expr(
633 Context, Z3_mk_bvadd_no_underflow(
Context.Context, toZ3Expr(*LHS).AST,
634 toZ3Expr(*RHS).AST)));
641 return newExprRef(Z3Expr(
642 Context, Z3_mk_bvsub_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
643 toZ3Expr(*RHS).AST)));
650 return newExprRef(Z3Expr(
651 Context, Z3_mk_bvsub_no_underflow(
Context.Context, toZ3Expr(*LHS).AST,
659 return newExprRef(Z3Expr(
660 Context, Z3_mk_bvsdiv_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
661 toZ3Expr(*RHS).AST)));
667 return newExprRef(Z3Expr(
668 Context, Z3_mk_bvneg_no_overflow(
Context.Context, toZ3Expr(*Exp).AST)));
675 return newExprRef(Z3Expr(
676 Context, Z3_mk_bvmul_no_overflow(
Context.Context, toZ3Expr(*LHS).AST,
684 return newExprRef(Z3Expr(
685 Context, Z3_mk_bvmul_no_underflow(
Context.Context, toZ3Expr(*LHS).AST,
686 toZ3Expr(*RHS).AST)));
692 toZ3Expr(*RHS).AST)));
697 return newExprRef(Z3Expr(
699 Z3_mk_fpa_to_fp_float(
Context.Context, toZ3Expr(*RoundingMode).AST,
700 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
705 return newExprRef(Z3Expr(
707 Z3_mk_fpa_to_fp_signed(
Context.Context, toZ3Expr(*RoundingMode).AST,
708 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
713 return newExprRef(Z3Expr(
715 Z3_mk_fpa_to_fp_unsigned(
Context.Context, toZ3Expr(*RoundingMode).AST,
716 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
721 return newExprRef(Z3Expr(
722 Context, Z3_mk_fpa_to_sbv(
Context.Context, toZ3Expr(*RoundingMode).AST,
723 toZ3Expr(*From).AST, ToWidth)));
728 return newExprRef(Z3Expr(
729 Context, Z3_mk_fpa_to_ubv(
Context.Context, toZ3Expr(*RoundingMode).AST,
730 toZ3Expr(*From).AST, ToWidth)));
735 : Z3_mk_false(
Context.Context)));
739 const Z3_sort Z3Sort = toZ3Sort(*getBitvectorSort(
BitWidth)).Sort;
743 SmallString<40> Buffer;
744 Int.toString(Buffer, 10);
745 return newExprRef(Z3Expr(
749 const int64_t BitReprAsSigned =
Int.getExtValue();
751 reinterpret_cast<const uint64_t &
>(BitReprAsSigned);
755 ? Z3_mk_int64(
Context.Context, BitReprAsSigned, Z3Sort)
756 : Z3_mk_unsigned_int64(
Context.
Context, BitReprAsUnsigned, Z3Sort);
760 SMTExprRef mkFloat(
const llvm::APFloat Float)
override {
764 llvm::APSInt
Int = llvm::APSInt(
Float.bitcastToAPInt(),
false);
766 return newExprRef(Z3Expr(
767 Context, Z3_mk_fpa_to_fp_bv(
Context.Context, toZ3Expr(*Z3Int).AST,
768 toZ3Sort(*Sort).Sort)));
774 Z3_mk_string_symbol(
Context.Context, Name),
775 toZ3Sort(*Sort).Sort)));
779 bool isUnsigned)
override {
782 Z3_get_numeral_string(
Context.Context, toZ3Expr(*Exp).AST),
787 bool getBoolean(
const SMTExprRef &Exp)
override {
788 return Z3_get_bool_value(
Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE;
793 return newExprRef(Z3Expr(
Context, Z3_mk_fpa_rne(
Context.Context)));
797 llvm::APFloat &Float,
bool useSemantics) {
801 const llvm::fltSemantics &Semantics =
804 if (!toAPSInt(BVSort, AST,
Int,
true)) {
808 if (useSemantics && !areEquivalent(
Float.getSemantics(), Semantics)) {
809 assert(
false &&
"Floating-point types don't match!");
813 Float = llvm::APFloat(Semantics,
Int);
818 llvm::APSInt &
Int,
bool useSemantics) {
821 assert(
false &&
"Bitvector types don't match!");
829 Int = getBitvector(AST,
Int.getBitWidth(),
Int.isUnsigned());
834 if (useSemantics &&
Int.getBitWidth() < 1) {
835 assert(
false &&
"Boolean type doesn't match!");
839 Int = llvm::APSInt(llvm::APInt(
Int.getBitWidth(), getBoolean(AST)),
847 bool getInterpretation(
const SMTExprRef &Exp, llvm::APSInt &
Int)
override {
849 Z3_func_decl
Func = Z3_get_app_decl(
851 if (Z3_model_has_interp(
Context.Context,
Model.Model, Func) != Z3_L_TRUE)
856 Z3_model_get_const_interp(
Context.Context,
Model.Model, Func)));
858 return toAPSInt(Sort, Assign,
Int,
true);
861 bool getInterpretation(
const SMTExprRef &Exp, llvm::APFloat &Float)
override {
863 Z3_func_decl
Func = Z3_get_app_decl(
865 if (Z3_model_has_interp(
Context.Context,
Model.Model, Func) != Z3_L_TRUE)
870 Z3_model_get_const_interp(
Context.Context,
Model.Model, Func)));
872 return toAPFloat(Sort, Assign, Float,
true);
875 std::optional<bool> check()
const override {
876 Z3_solver_set_params(
Context.Context, Solver, Params);
877 Z3_lbool res = Z3_solver_check(
Context.Context, Solver);
878 if (res == Z3_L_TRUE)
881 if (res == Z3_L_FALSE)
887 void push()
override {
return Z3_solver_push(
Context.Context, Solver); }
889 void pop(
unsigned NumStates = 1)
override {
890 assert(Z3_solver_get_num_scopes(
Context.Context, Solver) >= NumStates);
891 return Z3_solver_pop(
Context.Context, Solver, NumStates);
894 bool isFPSupported()
override {
return true; }
897 void reset()
override { Z3_solver_reset(
Context.Context, Solver); }
899 void print(raw_ostream &OS)
const override {
900 OS << Z3_solver_to_string(
Context.Context, Solver);
903 void setUnsignedParam(StringRef
Key,
unsigned Value)
override {
904 Z3_symbol Sym = Z3_mk_string_symbol(
Context.Context,
Key.str().c_str());
905 Z3_params_set_uint(
Context.Context, Params, Sym,
Value);
908 void setBoolParam(StringRef
Key,
bool Value)
override {
909 Z3_symbol Sym = Z3_mk_string_symbol(
Context.Context,
Key.str().c_str());
910 Z3_params_set_bool(
Context.Context, Params, Sym,
Value);
913 std::unique_ptr<SMTSolverStatistics> getStatistics()
const override;
919 auto It = DoubleValues.find(
Key.str());
920 assert(It != DoubleValues.end());
924 auto It = UnsignedValues.find(
Key.str());
925 if (It == UnsignedValues.end())
930 void print(raw_ostream &OS)
const override {
931 for (
const auto &
E : UnsignedValues)
932 OS <<
E.first() <<
": " <<
E.second <<
'\n';
933 for (
const auto &
E : DoubleValues) {
934 write_double(OS <<
E.first() <<
": ",
E.second, FloatStyle::Fixed);
940 friend class Z3Solver;
941 StringMap<unsigned> UnsignedValues;
942 StringMap<double> DoubleValues;
945std::unique_ptr<SMTSolverStatistics> Z3Solver::getStatistics()
const {
946 auto const &
C = Context.Context;
947 Z3_stats S = Z3_solver_get_statistics(
C, Solver);
948 Z3_stats_inc_ref(
C, S);
952 unsigned NumKeys = Z3_stats_size(
C, S);
953 for (
unsigned Idx = 0;
Idx < NumKeys; ++
Idx) {
954 const char *
Key = Z3_stats_get_key(
C, S, Idx);
955 if (Z3_stats_is_uint(
C, S, Idx)) {
956 auto Value = Z3_stats_get_uint_value(
C, S, Idx);
959 assert(Z3_stats_is_double(
C, S, Idx));
960 auto Value = Z3_stats_get_double_value(
C, S, Idx);
964 return std::make_unique<Z3Statistics>(std::move(Result));
973 return std::make_unique<Z3Solver>();
976 "with -DLLVM_ENABLE_Z3_SOLVER=ON",
982#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 Opcode)
SmallVector< MachineOperand, 4 > Cond
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
This file defines the SmallString class.
static const fltSemantics & IEEEsingle()
static LLVM_ABI ExponentType semanticsMinExponent(const fltSemantics &)
static const fltSemantics & IEEEquad()
static LLVM_ABI unsigned int semanticsSizeInBits(const fltSemantics &)
static const fltSemantics & IEEEdouble()
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
static const fltSemantics & IEEEhalf()
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_ABI 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.
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.
const SMTExpr * SMTExprRef
Shared pointer for SMTExprs, used by SMTSolver API.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.