LLVM 24.0.0git
Z3Solver.cpp
Go to the documentation of this file.
1//== Z3Solver.cpp -----------------------------------------------*- C++ -*--==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/Config/config.h"
12#include "llvm/Support/SMTAPI.h"
13
14using namespace llvm;
15
16#if LLVM_WITH_Z3
17
19#include "llvm/ADT/StringMap.h"
20#include "llvm/ADT/Twine.h"
21
22#include <set>
23
24#include <z3.h>
25
26namespace {
27
28/// Configuration class for Z3
29class Z3Config {
30 friend class Z3Context;
31
32 Z3_config Config = Z3_mk_config();
33
34public:
35 Z3Config() = default;
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); }
41}; // end class Z3Config
42
43// Function used to report errors
44void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) {
45 llvm::report_fatal_error("Z3 error: " +
46 llvm::Twine(Z3_get_error_msg(Context, Error)));
47}
48
49/// Wrapper for Z3 context
50class Z3Context {
51public:
52 Z3Config Config;
53 Z3_context Context;
54
55 Z3Context() {
56 Context = Z3_mk_context_rc(Config.Config);
57 // The error function is set here because the context is the first object
58 // created by the backend
59 Z3_set_error_handler(Context, Z3ErrorHandler);
60 }
61
62 Z3Context(const Z3Context &) = delete;
63 Z3Context(Z3Context &&) = default;
64 Z3Context &operator=(Z3Context &) = delete;
65 Z3Context &operator=(Z3Context &&) = default;
66
67 ~Z3Context() {
68 Z3_del_context(Context);
69 Context = nullptr;
70 }
71}; // end class Z3Context
72
73/// Wrapper for Z3 Sort
74class Z3Sort : public SMTSort {
75 friend class Z3Solver;
76
77 Z3Context &Context;
78
79 Z3_sort Sort;
80
81public:
82 /// Default constructor, mainly used by make_shared
83 Z3Sort(Z3Context &C, Z3_sort ZS) : Context(C), Sort(ZS) {
84 Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
85 }
86
87 /// Override implicit copy constructor for correct reference counting.
88 Z3Sort(const Z3Sort &Other) : Context(Other.Context), Sort(Other.Sort) {
89 Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
90 }
91
92 /// Override implicit copy assignment constructor for correct reference
93 /// counting.
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));
97 Sort = Other.Sort;
98 return *this;
99 }
100
101 Z3Sort(Z3Sort &&Other) = delete;
102 Z3Sort &operator=(Z3Sort &&Other) = delete;
103
104 ~Z3Sort() {
105 if (Sort)
106 Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
107 }
108
109 void Profile(llvm::FoldingSetNodeID &ID) const override {
110 ID.AddInteger(
111 Z3_get_ast_id(Context.Context, reinterpret_cast<Z3_ast>(Sort)));
112 }
113
114 bool isBitvectorSortImpl() const override {
115 return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BV_SORT);
116 }
117
118 bool isFloatSortImpl() const override {
119 return (Z3_get_sort_kind(Context.Context, Sort) == Z3_FLOATING_POINT_SORT);
120 }
121
122 bool isBooleanSortImpl() const override {
123 return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BOOL_SORT);
124 }
125
126 unsigned getBitvectorSortSizeImpl() const override {
127 return Z3_get_bv_sort_size(Context.Context, Sort);
128 }
129
130 unsigned getFloatSortSizeImpl() const override {
131 return Z3_fpa_get_ebits(Context.Context, Sort) +
132 Z3_fpa_get_sbits(Context.Context, Sort);
133 }
134
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);
138 }
139
140 void print(raw_ostream &OS) const override {
141 OS << Z3_sort_to_string(Context.Context, Sort);
142 }
143}; // end class Z3Sort
144
145static const Z3Sort &toZ3Sort(const SMTSort &S) {
146 return static_cast<const Z3Sort &>(S);
147}
148
149class Z3Expr : public SMTExpr {
150 friend class Z3Solver;
151
152 Z3Context &Context;
153
154 Z3_ast AST;
155
156public:
157 Z3Expr(Z3Context &C, Z3_ast ZA) : SMTExpr(), Context(C), AST(ZA) {
158 Z3_inc_ref(Context.Context, AST);
159 }
160
161 /// Override implicit copy constructor for correct reference counting.
162 Z3Expr(const Z3Expr &Copy) : SMTExpr(), Context(Copy.Context), AST(Copy.AST) {
163 Z3_inc_ref(Context.Context, AST);
164 }
165
166 /// Override implicit copy assignment constructor for correct reference
167 /// counting.
168 Z3Expr &operator=(const Z3Expr &Other) {
169 Z3_inc_ref(Context.Context, Other.AST);
170 Z3_dec_ref(Context.Context, AST);
171 AST = Other.AST;
172 return *this;
173 }
174
175 Z3Expr(Z3Expr &&Other) = delete;
176 Z3Expr &operator=(Z3Expr &&Other) = delete;
177
178 ~Z3Expr() {
179 if (AST)
180 Z3_dec_ref(Context.Context, AST);
181 }
182
183 void Profile(llvm::FoldingSetNodeID &ID) const override {
184 ID.AddInteger(Z3_get_ast_id(Context.Context, AST));
185 }
186
187 /// Comparison of AST equality, not model equivalence.
188 bool equal_to(SMTExpr const &Other) const override {
189 assert(Z3_is_eq_sort(Context.Context, Z3_get_sort(Context.Context, AST),
190 Z3_get_sort(Context.Context,
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);
195 }
196
197 void print(raw_ostream &OS) const override {
198 OS << Z3_ast_to_string(Context.Context, AST);
199 }
200}; // end class Z3Expr
201
202static const Z3Expr &toZ3Expr(const SMTExpr &E) {
203 return static_cast<const Z3Expr &>(E);
204}
205
206class Z3Model {
207 friend class Z3Solver;
208
209 Z3Context &Context;
210
211 Z3_model Model;
212
213public:
214 Z3Model(Z3Context &C, Z3_model ZM) : Context(C), Model(ZM) {
215 Z3_model_inc_ref(Context.Context, Model);
216 }
217
218 Z3Model(const Z3Model &Other) = delete;
219 Z3Model(Z3Model &&Other) = delete;
220 Z3Model &operator=(Z3Model &Other) = delete;
221 Z3Model &operator=(Z3Model &&Other) = delete;
222
223 ~Z3Model() {
224 if (Model)
225 Z3_model_dec_ref(Context.Context, Model);
226 }
227
228 void print(raw_ostream &OS) const {
229 OS << Z3_model_to_string(Context.Context, Model);
230 }
231
232 LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); }
233}; // end class Z3Model
234
235/// Get the corresponding IEEE floating-point type for a given bitwidth.
236static const llvm::fltSemantics &getFloatSemantics(unsigned BitWidth) {
237 switch (BitWidth) {
238 default:
239 llvm_unreachable("Unsupported floating-point semantics!");
240 break;
241 case 16:
243 case 32:
245 case 64:
247 case 128:
249 }
250}
251
252// Determine whether two float semantics are equivalent
253static bool areEquivalent(const llvm::fltSemantics &LHS,
254 const llvm::fltSemantics &RHS) {
263}
264
265class Z3Solver : public SMTSolver {
266 Z3Context Context;
267
268 Z3_solver Solver = [this] {
269 Z3_solver S = Z3_mk_simple_solver(Context.Context);
270 Z3_solver_inc_ref(Context.Context, S);
271 return S;
272 }();
273
274 Z3_params Params = [this] {
275 Z3_params P = Z3_mk_params(Context.Context);
276 Z3_params_inc_ref(Context.Context, P);
277 return P;
278 }();
279
280 // Cache Sorts
281 std::set<Z3Sort> CachedSorts;
282
283 // Cache Exprs
284 std::set<Z3Expr> CachedExprs;
285
286public:
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;
292
293 ~Z3Solver() override {
294 Z3_params_dec_ref(Context.Context, Params);
295 Z3_solver_dec_ref(Context.Context, Solver);
296 }
297
298 void addConstraint(const SMTExprRef &Exp) const override {
299 Z3_solver_assert(Context.Context, Solver, toZ3Expr(*Exp).AST);
300 }
301
302 // Given an SMTSort, adds/retrives it from the cache and returns
303 // an SMTSortRef to the SMTSort in the cache
304 SMTSortRef newSortRef(const SMTSort &Sort) {
305 auto It = CachedSorts.insert(toZ3Sort(Sort));
306 return &(*It.first);
307 }
308
309 // Given an SMTExpr, adds/retrives it from the cache and returns
310 // an SMTExprRef to the SMTExpr in the cache
311 SMTExprRef newExprRef(const SMTExpr &Exp) {
312 auto It = CachedExprs.insert(toZ3Expr(Exp));
313 return &(*It.first);
314 }
315
316 SMTSortRef getBoolSort() override {
317 return newSortRef(Z3Sort(Context, Z3_mk_bool_sort(Context.Context)));
318 }
319
320 SMTSortRef getBitvectorSort(unsigned BitWidth) override {
321 return newSortRef(
322 Z3Sort(Context, Z3_mk_bv_sort(Context.Context, BitWidth)));
323 }
324
325 SMTSortRef getSort(const SMTExprRef &Exp) override {
326 return newSortRef(
327 Z3Sort(Context, Z3_get_sort(Context.Context, toZ3Expr(*Exp).AST)));
328 }
329
330 SMTSortRef getFloat16Sort() override {
331 return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_16(Context.Context)));
332 }
333
334 SMTSortRef getFloat32Sort() override {
335 return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_32(Context.Context)));
336 }
337
338 SMTSortRef getFloat64Sort() override {
339 return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_64(Context.Context)));
340 }
341
342 SMTSortRef getFloat128Sort() override {
343 return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_128(Context.Context)));
344 }
345
346 SMTExprRef mkBVNeg(const SMTExprRef &Exp) override {
347 return newExprRef(
348 Z3Expr(Context, Z3_mk_bvneg(Context.Context, toZ3Expr(*Exp).AST)));
349 }
350
351 SMTExprRef mkBVNot(const SMTExprRef &Exp) override {
352 return newExprRef(
353 Z3Expr(Context, Z3_mk_bvnot(Context.Context, toZ3Expr(*Exp).AST)));
354 }
355
356 SMTExprRef mkNot(const SMTExprRef &Exp) override {
357 return newExprRef(
358 Z3Expr(Context, Z3_mk_not(Context.Context, toZ3Expr(*Exp).AST)));
359 }
360
361 SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
362 return newExprRef(
363 Z3Expr(Context, Z3_mk_bvadd(Context.Context, toZ3Expr(*LHS).AST,
364 toZ3Expr(*RHS).AST)));
365 }
366
367 SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
368 return newExprRef(
369 Z3Expr(Context, Z3_mk_bvsub(Context.Context, toZ3Expr(*LHS).AST,
370 toZ3Expr(*RHS).AST)));
371 }
372
373 SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
374 return newExprRef(
375 Z3Expr(Context, Z3_mk_bvmul(Context.Context, toZ3Expr(*LHS).AST,
376 toZ3Expr(*RHS).AST)));
377 }
378
379 SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
380 return newExprRef(
381 Z3Expr(Context, Z3_mk_bvsrem(Context.Context, toZ3Expr(*LHS).AST,
382 toZ3Expr(*RHS).AST)));
383 }
384
385 SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
386 return newExprRef(
387 Z3Expr(Context, Z3_mk_bvurem(Context.Context, toZ3Expr(*LHS).AST,
388 toZ3Expr(*RHS).AST)));
389 }
390
391 SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
392 return newExprRef(
393 Z3Expr(Context, Z3_mk_bvsdiv(Context.Context, toZ3Expr(*LHS).AST,
394 toZ3Expr(*RHS).AST)));
395 }
396
397 SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
398 return newExprRef(
399 Z3Expr(Context, Z3_mk_bvudiv(Context.Context, toZ3Expr(*LHS).AST,
400 toZ3Expr(*RHS).AST)));
401 }
402
403 SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
404 return newExprRef(
405 Z3Expr(Context, Z3_mk_bvshl(Context.Context, toZ3Expr(*LHS).AST,
406 toZ3Expr(*RHS).AST)));
407 }
408
409 SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
410 return newExprRef(
411 Z3Expr(Context, Z3_mk_bvashr(Context.Context, toZ3Expr(*LHS).AST,
412 toZ3Expr(*RHS).AST)));
413 }
414
415 SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
416 return newExprRef(
417 Z3Expr(Context, Z3_mk_bvlshr(Context.Context, toZ3Expr(*LHS).AST,
418 toZ3Expr(*RHS).AST)));
419 }
420
421 SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
422 return newExprRef(
423 Z3Expr(Context, Z3_mk_bvxor(Context.Context, toZ3Expr(*LHS).AST,
424 toZ3Expr(*RHS).AST)));
425 }
426
427 SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
428 return newExprRef(
429 Z3Expr(Context, Z3_mk_bvor(Context.Context, toZ3Expr(*LHS).AST,
430 toZ3Expr(*RHS).AST)));
431 }
432
433 SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
434 return newExprRef(
435 Z3Expr(Context, Z3_mk_bvand(Context.Context, toZ3Expr(*LHS).AST,
436 toZ3Expr(*RHS).AST)));
437 }
438
439 SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
440 return newExprRef(
441 Z3Expr(Context, Z3_mk_bvult(Context.Context, toZ3Expr(*LHS).AST,
442 toZ3Expr(*RHS).AST)));
443 }
444
445 SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
446 return newExprRef(
447 Z3Expr(Context, Z3_mk_bvslt(Context.Context, toZ3Expr(*LHS).AST,
448 toZ3Expr(*RHS).AST)));
449 }
450
451 SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
452 return newExprRef(
453 Z3Expr(Context, Z3_mk_bvugt(Context.Context, toZ3Expr(*LHS).AST,
454 toZ3Expr(*RHS).AST)));
455 }
456
457 SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
458 return newExprRef(
459 Z3Expr(Context, Z3_mk_bvsgt(Context.Context, toZ3Expr(*LHS).AST,
460 toZ3Expr(*RHS).AST)));
461 }
462
463 SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
464 return newExprRef(
465 Z3Expr(Context, Z3_mk_bvule(Context.Context, toZ3Expr(*LHS).AST,
466 toZ3Expr(*RHS).AST)));
467 }
468
469 SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
470 return newExprRef(
471 Z3Expr(Context, Z3_mk_bvsle(Context.Context, toZ3Expr(*LHS).AST,
472 toZ3Expr(*RHS).AST)));
473 }
474
475 SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
476 return newExprRef(
477 Z3Expr(Context, Z3_mk_bvuge(Context.Context, toZ3Expr(*LHS).AST,
478 toZ3Expr(*RHS).AST)));
479 }
480
481 SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
482 return newExprRef(
483 Z3Expr(Context, Z3_mk_bvsge(Context.Context, toZ3Expr(*LHS).AST,
484 toZ3Expr(*RHS).AST)));
485 }
486
487 SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
488 Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
489 return newExprRef(Z3Expr(Context, Z3_mk_and(Context.Context, 2, Args)));
490 }
491
492 SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
493 Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST};
494 return newExprRef(Z3Expr(Context, Z3_mk_or(Context.Context, 2, Args)));
495 }
496
497 SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
498 return newExprRef(
499 Z3Expr(Context, Z3_mk_eq(Context.Context, toZ3Expr(*LHS).AST,
500 toZ3Expr(*RHS).AST)));
501 }
502
503 SMTExprRef mkFPNeg(const SMTExprRef &Exp) override {
504 return newExprRef(
505 Z3Expr(Context, Z3_mk_fpa_neg(Context.Context, toZ3Expr(*Exp).AST)));
506 }
507
508 SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) override {
509 return newExprRef(Z3Expr(
510 Context, Z3_mk_fpa_is_infinite(Context.Context, toZ3Expr(*Exp).AST)));
511 }
512
513 SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) override {
514 return newExprRef(
515 Z3Expr(Context, Z3_mk_fpa_is_nan(Context.Context, toZ3Expr(*Exp).AST)));
516 }
517
518 SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) override {
519 return newExprRef(Z3Expr(
520 Context, Z3_mk_fpa_is_normal(Context.Context, toZ3Expr(*Exp).AST)));
521 }
522
523 SMTExprRef mkFPIsZero(const SMTExprRef &Exp) override {
524 return newExprRef(Z3Expr(
525 Context, Z3_mk_fpa_is_zero(Context.Context, toZ3Expr(*Exp).AST)));
526 }
527
528 SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
529 SMTExprRef RoundingMode = getFloatRoundingMode();
530 return newExprRef(
531 Z3Expr(Context,
532 Z3_mk_fpa_mul(Context.Context, toZ3Expr(*RoundingMode).AST,
533 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
534 }
535
536 SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
537 SMTExprRef RoundingMode = getFloatRoundingMode();
538 return newExprRef(
539 Z3Expr(Context,
540 Z3_mk_fpa_div(Context.Context, toZ3Expr(*RoundingMode).AST,
541 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
542 }
543
544 SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
545 return newExprRef(
546 Z3Expr(Context, Z3_mk_fpa_rem(Context.Context, toZ3Expr(*LHS).AST,
547 toZ3Expr(*RHS).AST)));
548 }
549
550 SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
551 SMTExprRef RoundingMode = getFloatRoundingMode();
552 return newExprRef(
553 Z3Expr(Context,
554 Z3_mk_fpa_add(Context.Context, toZ3Expr(*RoundingMode).AST,
555 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
556 }
557
558 SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
559 SMTExprRef RoundingMode = getFloatRoundingMode();
560 return newExprRef(
561 Z3Expr(Context,
562 Z3_mk_fpa_sub(Context.Context, toZ3Expr(*RoundingMode).AST,
563 toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST)));
564 }
565
566 SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
567 return newExprRef(
568 Z3Expr(Context, Z3_mk_fpa_lt(Context.Context, toZ3Expr(*LHS).AST,
569 toZ3Expr(*RHS).AST)));
570 }
571
572 SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
573 return newExprRef(
574 Z3Expr(Context, Z3_mk_fpa_gt(Context.Context, toZ3Expr(*LHS).AST,
575 toZ3Expr(*RHS).AST)));
576 }
577
578 SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
579 return newExprRef(
580 Z3Expr(Context, Z3_mk_fpa_leq(Context.Context, toZ3Expr(*LHS).AST,
581 toZ3Expr(*RHS).AST)));
582 }
583
584 SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
585 return newExprRef(
586 Z3Expr(Context, Z3_mk_fpa_geq(Context.Context, toZ3Expr(*LHS).AST,
587 toZ3Expr(*RHS).AST)));
588 }
589
590 SMTExprRef mkFPEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
591 return newExprRef(
592 Z3Expr(Context, Z3_mk_fpa_eq(Context.Context, toZ3Expr(*LHS).AST,
593 toZ3Expr(*RHS).AST)));
594 }
595
596 SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
597 const SMTExprRef &F) override {
598 return newExprRef(
599 Z3Expr(Context, Z3_mk_ite(Context.Context, toZ3Expr(*Cond).AST,
600 toZ3Expr(*T).AST, toZ3Expr(*F).AST)));
601 }
602
603 SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) override {
604 return newExprRef(Z3Expr(
605 Context, Z3_mk_sign_ext(Context.Context, i, toZ3Expr(*Exp).AST)));
606 }
607
608 SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) override {
609 return newExprRef(Z3Expr(
610 Context, Z3_mk_zero_ext(Context.Context, i, toZ3Expr(*Exp).AST)));
611 }
612
613 SMTExprRef mkBVExtract(unsigned High, unsigned Low,
614 const SMTExprRef &Exp) override {
615 return newExprRef(Z3Expr(Context, Z3_mk_extract(Context.Context, High, Low,
616 toZ3Expr(*Exp).AST)));
617 }
618
619 /// Creates a predicate that checks for overflow in a bitvector addition
620 /// operation
621 SMTExprRef mkBVAddNoOverflow(const SMTExprRef &LHS, const SMTExprRef &RHS,
622 bool isSigned) override {
623 return newExprRef(Z3Expr(
624 Context, Z3_mk_bvadd_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
625 toZ3Expr(*RHS).AST, isSigned)));
626 }
627
628 /// Creates a predicate that checks for underflow in a signed bitvector
629 /// addition operation
630 SMTExprRef mkBVAddNoUnderflow(const SMTExprRef &LHS,
631 const SMTExprRef &RHS) override {
632 return newExprRef(Z3Expr(
633 Context, Z3_mk_bvadd_no_underflow(Context.Context, toZ3Expr(*LHS).AST,
634 toZ3Expr(*RHS).AST)));
635 }
636
637 /// Creates a predicate that checks for overflow in a signed bitvector
638 /// subtraction operation
639 SMTExprRef mkBVSubNoOverflow(const SMTExprRef &LHS,
640 const SMTExprRef &RHS) override {
641 return newExprRef(Z3Expr(
642 Context, Z3_mk_bvsub_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
643 toZ3Expr(*RHS).AST)));
644 }
645
646 /// Creates a predicate that checks for underflow in a bitvector subtraction
647 /// operation
648 SMTExprRef mkBVSubNoUnderflow(const SMTExprRef &LHS, const SMTExprRef &RHS,
649 bool isSigned) override {
650 return newExprRef(Z3Expr(
651 Context, Z3_mk_bvsub_no_underflow(Context.Context, toZ3Expr(*LHS).AST,
652 toZ3Expr(*RHS).AST, isSigned)));
653 }
654
655 /// Creates a predicate that checks for overflow in a signed bitvector
656 /// division/modulus operation
657 SMTExprRef mkBVSDivNoOverflow(const SMTExprRef &LHS,
658 const SMTExprRef &RHS) override {
659 return newExprRef(Z3Expr(
660 Context, Z3_mk_bvsdiv_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
661 toZ3Expr(*RHS).AST)));
662 }
663
664 /// Creates a predicate that checks for overflow in a bitvector negation
665 /// operation
666 SMTExprRef mkBVNegNoOverflow(const SMTExprRef &Exp) override {
667 return newExprRef(Z3Expr(
668 Context, Z3_mk_bvneg_no_overflow(Context.Context, toZ3Expr(*Exp).AST)));
669 }
670
671 /// Creates a predicate that checks for overflow in a bitvector multiplication
672 /// operation
673 SMTExprRef mkBVMulNoOverflow(const SMTExprRef &LHS, const SMTExprRef &RHS,
674 bool isSigned) override {
675 return newExprRef(Z3Expr(
676 Context, Z3_mk_bvmul_no_overflow(Context.Context, toZ3Expr(*LHS).AST,
677 toZ3Expr(*RHS).AST, isSigned)));
678 }
679
680 /// Creates a predicate that checks for underflow in a signed bitvector
681 /// multiplication operation
682 SMTExprRef mkBVMulNoUnderflow(const SMTExprRef &LHS,
683 const SMTExprRef &RHS) override {
684 return newExprRef(Z3Expr(
685 Context, Z3_mk_bvmul_no_underflow(Context.Context, toZ3Expr(*LHS).AST,
686 toZ3Expr(*RHS).AST)));
687 }
688
689 SMTExprRef mkBVConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) override {
690 return newExprRef(
691 Z3Expr(Context, Z3_mk_concat(Context.Context, toZ3Expr(*LHS).AST,
692 toZ3Expr(*RHS).AST)));
693 }
694
695 SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
696 SMTExprRef RoundingMode = getFloatRoundingMode();
697 return newExprRef(Z3Expr(
698 Context,
699 Z3_mk_fpa_to_fp_float(Context.Context, toZ3Expr(*RoundingMode).AST,
700 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
701 }
702
703 SMTExprRef mkSBVtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
704 SMTExprRef RoundingMode = getFloatRoundingMode();
705 return newExprRef(Z3Expr(
706 Context,
707 Z3_mk_fpa_to_fp_signed(Context.Context, toZ3Expr(*RoundingMode).AST,
708 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
709 }
710
711 SMTExprRef mkUBVtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
712 SMTExprRef RoundingMode = getFloatRoundingMode();
713 return newExprRef(Z3Expr(
714 Context,
715 Z3_mk_fpa_to_fp_unsigned(Context.Context, toZ3Expr(*RoundingMode).AST,
716 toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
717 }
718
719 SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) override {
720 SMTExprRef RoundingMode = getFloatRoundingMode();
721 return newExprRef(Z3Expr(
722 Context, Z3_mk_fpa_to_sbv(Context.Context, toZ3Expr(*RoundingMode).AST,
723 toZ3Expr(*From).AST, ToWidth)));
724 }
725
726 SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) override {
727 SMTExprRef RoundingMode = getFloatRoundingMode();
728 return newExprRef(Z3Expr(
729 Context, Z3_mk_fpa_to_ubv(Context.Context, toZ3Expr(*RoundingMode).AST,
730 toZ3Expr(*From).AST, ToWidth)));
731 }
732
733 SMTExprRef mkBoolean(const bool b) override {
734 return newExprRef(Z3Expr(Context, b ? Z3_mk_true(Context.Context)
735 : Z3_mk_false(Context.Context)));
736 }
737
738 SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) override {
739 const Z3_sort Z3Sort = toZ3Sort(*getBitvectorSort(BitWidth)).Sort;
740
741 // Slow path, when 64 bits are not enough.
742 if (LLVM_UNLIKELY(!Int.isRepresentableByInt64())) {
743 SmallString<40> Buffer;
744 Int.toString(Buffer, 10);
745 return newExprRef(Z3Expr(
746 Context, Z3_mk_numeral(Context.Context, Buffer.c_str(), Z3Sort)));
747 }
748
749 const int64_t BitReprAsSigned = Int.getExtValue();
750 const uint64_t BitReprAsUnsigned =
751 reinterpret_cast<const uint64_t &>(BitReprAsSigned);
752
753 Z3_ast Literal =
754 Int.isSigned()
755 ? Z3_mk_int64(Context.Context, BitReprAsSigned, Z3Sort)
756 : Z3_mk_unsigned_int64(Context.Context, BitReprAsUnsigned, Z3Sort);
757 return newExprRef(Z3Expr(Context, Literal));
758 }
759
760 SMTExprRef mkFloat(const llvm::APFloat Float) override {
761 SMTSortRef Sort =
762 getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics()));
763
764 llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false);
765 SMTExprRef Z3Int = mkBitvector(Int, Int.getBitWidth());
766 return newExprRef(Z3Expr(
767 Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST,
768 toZ3Sort(*Sort).Sort)));
769 }
770
771 SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) override {
772 return newExprRef(
773 Z3Expr(Context, Z3_mk_const(Context.Context,
774 Z3_mk_string_symbol(Context.Context, Name),
775 toZ3Sort(*Sort).Sort)));
776 }
777
778 llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
779 bool isUnsigned) override {
780 return llvm::APSInt(
781 llvm::APInt(BitWidth,
782 Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST),
783 10),
784 isUnsigned);
785 }
786
787 bool getBoolean(const SMTExprRef &Exp) override {
788 return Z3_get_bool_value(Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE;
789 }
790
791 SMTExprRef getFloatRoundingMode() override {
792 // TODO: Don't assume nearest ties to even rounding mode
793 return newExprRef(Z3Expr(Context, Z3_mk_fpa_rne(Context.Context)));
794 }
795
796 bool toAPFloat(const SMTSortRef &Sort, const SMTExprRef &AST,
797 llvm::APFloat &Float, bool useSemantics) {
798 assert(Sort->isFloatSort() && "Unsupported sort to floating-point!");
799
800 llvm::APSInt Int(Sort->getFloatSortSize(), true);
801 const llvm::fltSemantics &Semantics =
802 getFloatSemantics(Sort->getFloatSortSize());
803 SMTSortRef BVSort = getBitvectorSort(Sort->getFloatSortSize());
804 if (!toAPSInt(BVSort, AST, Int, true)) {
805 return false;
806 }
807
808 if (useSemantics && !areEquivalent(Float.getSemantics(), Semantics)) {
809 assert(false && "Floating-point types don't match!");
810 return false;
811 }
812
813 Float = llvm::APFloat(Semantics, Int);
814 return true;
815 }
816
817 bool toAPSInt(const SMTSortRef &Sort, const SMTExprRef &AST,
818 llvm::APSInt &Int, bool useSemantics) {
819 if (Sort->isBitvectorSort()) {
820 if (useSemantics && Int.getBitWidth() != Sort->getBitvectorSortSize()) {
821 assert(false && "Bitvector types don't match!");
822 return false;
823 }
824
825 // FIXME: This function is also used to retrieve floating-point values,
826 // which can be 16, 32, 64 or 128 bits long. In the future, we need proper
827 // calls in the backend to retrieve floating-points and its special values
828 // (NaN, +/-infinity, +/-zero).
829 Int = getBitvector(AST, Int.getBitWidth(), Int.isUnsigned());
830 return true;
831 }
832
833 if (Sort->isBooleanSort()) {
834 if (useSemantics && Int.getBitWidth() < 1) {
835 assert(false && "Boolean type doesn't match!");
836 return false;
837 }
838
839 Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), getBoolean(AST)),
840 Int.isUnsigned());
841 return true;
842 }
843
844 llvm_unreachable("Unsupported sort to integer!");
845 }
846
847 bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) override {
848 Z3Model Model(Context, Z3_solver_get_model(Context.Context, Solver));
849 Z3_func_decl Func = Z3_get_app_decl(
850 Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
851 if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
852 return false;
853
854 SMTExprRef Assign = newExprRef(
855 Z3Expr(Context,
856 Z3_model_get_const_interp(Context.Context, Model.Model, Func)));
857 SMTSortRef Sort = getSort(Assign);
858 return toAPSInt(Sort, Assign, Int, true);
859 }
860
861 bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) override {
862 Z3Model Model(Context, Z3_solver_get_model(Context.Context, Solver));
863 Z3_func_decl Func = Z3_get_app_decl(
864 Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
865 if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
866 return false;
867
868 SMTExprRef Assign = newExprRef(
869 Z3Expr(Context,
870 Z3_model_get_const_interp(Context.Context, Model.Model, Func)));
871 SMTSortRef Sort = getSort(Assign);
872 return toAPFloat(Sort, Assign, Float, true);
873 }
874
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)
879 return true;
880
881 if (res == Z3_L_FALSE)
882 return false;
883
884 return std::nullopt;
885 }
886
887 void push() override { return Z3_solver_push(Context.Context, Solver); }
888
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);
892 }
893
894 bool isFPSupported() override { return true; }
895
896 /// Reset the solver and remove all constraints.
897 void reset() override { Z3_solver_reset(Context.Context, Solver); }
898
899 void print(raw_ostream &OS) const override {
900 OS << Z3_solver_to_string(Context.Context, Solver);
901 }
902
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);
906 }
907
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);
911 }
912
913 std::unique_ptr<SMTSolverStatistics> getStatistics() const override;
914}; // end class Z3Solver
915
916class Z3Statistics final : public SMTSolverStatistics {
917public:
918 double getDouble(StringRef Key) const override {
919 auto It = DoubleValues.find(Key.str());
920 assert(It != DoubleValues.end());
921 return It->second;
922 };
923 unsigned getUnsigned(StringRef Key) const override {
924 auto It = UnsignedValues.find(Key.str());
925 if (It == UnsignedValues.end())
926 return 0;
927 return It->second;
928 };
929
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);
935 OS << '\n';
936 }
937 }
938
939private:
940 friend class Z3Solver;
941 StringMap<unsigned> UnsignedValues;
942 StringMap<double> DoubleValues;
943};
944
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);
949 llvm::scope_exit StatsGuard([&C, &S] { Z3_stats_dec_ref(C, S); });
950 Z3Statistics Result;
951
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);
957 Result.UnsignedValues.try_emplace(Key, Value);
958 } else {
959 assert(Z3_stats_is_double(C, S, Idx));
960 auto Value = Z3_stats_get_double_value(C, S, Idx);
961 Result.DoubleValues.try_emplace(Key, Value);
962 }
963 }
964 return std::make_unique<Z3Statistics>(std::move(Result));
965}
966
967} // end anonymous namespace
968
969#endif
970
972#if LLVM_WITH_Z3
973 return std::make_unique<Z3Solver>();
974#else
975 llvm::report_fatal_error("LLVM was not compiled with Z3 support, rebuild "
976 "with -DLLVM_ENABLE_Z3_SOLVER=ON",
977 false);
978 return nullptr;
979#endif
980}
981
982#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
987#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
uint64_t uint64_t
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)
Definition Compiler.h:348
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:690
static bool isSigned(unsigned Opcode)
#define F(x, y, z)
Definition MD5.cpp:54
Load MIR Sample Profile
#define T
uint64_t High
#define P(N)
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.
Value * RHS
Value * LHS
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static LLVM_ABI ExponentType semanticsMinExponent(const fltSemantics &)
Definition APFloat.cpp:342
static const fltSemantics & IEEEquad()
Definition APFloat.h:306
static LLVM_ABI unsigned int semanticsSizeInBits(const fltSemantics &)
Definition APFloat.cpp:345
static const fltSemantics & IEEEdouble()
Definition APFloat.h:305
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
Definition APFloat.cpp:338
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
Definition APFloat.cpp:334
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Generic base class for SMT exprs.
Definition SMTAPI.h:103
LLVM_DUMP_METHOD void dump() const
Definition Z3Solver.cpp:984
virtual void print(raw_ostream &OS) const =0
virtual unsigned getUnsigned(llvm::StringRef) const =0
LLVM_DUMP_METHOD void dump() const
Definition Z3Solver.cpp:986
virtual double getDouble(llvm::StringRef) const =0
virtual void print(raw_ostream &OS) const =0
Generic base class for SMT Solvers.
Definition SMTAPI.h:156
virtual void print(raw_ostream &OS) const =0
LLVM_ABI LLVM_DUMP_METHOD void dump() const
Definition Z3Solver.cpp:985
Generic base class for SMT sorts.
Definition SMTAPI.h:27
virtual void print(raw_ostream &OS) const =0
virtual bool isBitvectorSort() const
Returns true if the sort is a bitvector, calls isBitvectorSortImpl().
Definition SMTAPI.h:33
virtual bool isFloatSort() const
Returns true if the sort is a floating-point, calls isFloatSortImpl().
Definition SMTAPI.h:36
virtual unsigned getFloatSortSize() const
Returns the floating-point size, fails if the sort is not a floating-point Calls getFloatSortSizeImpl...
Definition SMTAPI.h:52
virtual unsigned getBitvectorSortSize() const
Returns the bitvector size, fails if the sort is not a bitvector Calls getBitvectorSortSizeImpl().
Definition SMTAPI.h:43
virtual bool isBooleanSort() const
Returns true if the sort is a boolean, calls isBooleanSortImpl().
Definition SMTAPI.h:39
LLVM_DUMP_METHOD void dump() const
Definition Z3Solver.cpp:983
const char * c_str()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
#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
Definition RDFGraph.h:393
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.
Definition Threading.h:280
const SMTExpr * SMTExprRef
Shared pointer for SMTExprs, used by SMTSolver API.
Definition SMTAPI.h:149
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2189
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
std::shared_ptr< SMTSolver > SMTSolverRef
Shared pointer for SMTSolvers.
Definition SMTAPI.h:468
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
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.
@ Other
Any other memory.
Definition ModRef.h:68
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.
Definition SMTAPI.h:100
LLVM_ABI SMTSolverRef CreateZ3Solver()
Convenience method to create and Z3Solver object.
Definition Z3Solver.cpp:971