1 /*
2 * This file is part of the Yices SMT Solver.
3 * Copyright (C) 2017 SRI International.
4 *
5 * Yices is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Yices is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Yices. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * UTILITIES TO ACCESS CONTEXT STRUCTURES
21 */
22
23 #ifndef __CONTEXT_UTILS_H
24 #define __CONTEXT_UTILS_H
25
26 #include "context/context_types.h"
27
28
29 /*
30 * SUBST AND MARK VECTOR
31 */
32
33 /*
34 * If variable elimination is enabled, then ctx->subst is used to
35 * store candidate substitutions before we check for substitution
36 * cycles. The mark vector is used to mark terms during cycle detection.
37 */
38
39 /*
40 * Return ctx->subst. Allocate and initialize it if necessary.
41 */
42 extern pseudo_subst_t *context_get_subst(context_t *ctx);
43
44 /*
45 * Free ctx->subst (if it's not NULL)
46 */
47 extern void context_free_subst(context_t *ctx);
48
49
50 /*
51 * Return ctx->marks. Allocate and initialize it if necessary.
52 */
53 extern mark_vector_t *context_get_marks(context_t *ctx);
54
55
56 /*
57 * Free the mark vector if non-NULL
58 */
59 extern void context_free_marks(context_t *ctx);
60
61
62 /*
63 * INTERNAL CACHES AND AUXILIARY STRUCTURES
64 */
65
66 /*
67 * There are two internal caches for visiting terms.
68 * - the 'cache' uses a bitvector implementation and should be
69 * better for operations that visit many terms.
70 * - the 'small_cache' uses a hash table and should be better
71 * for operations that visit a small number of terms.
72 *
73 * There are three buffers for internal construction of polynomials
74 * - arith_buffer is more expensive (requires more memory) but
75 * it supports more operations (e.g., term constructors in yices_api.c
76 * take arith_buffers as arguments).
77 * - poly_buffer is a cheaper data structure, but it does not support
78 * all the operations
79 * - aux_poly is even cheaper, but it's for direct construction only
80 *
81 * There's one buffer for bitvector polynomials. It's suitable for all
82 * bit widths.
83 */
84
85 /*
86 * Allocate/reset/free the small cache
87 * - the cache is allocated and initialized on the first call to get_small_cache
88 * - reset and free do nothing if the cache is not allocated
89 */
90 extern int_hset_t *context_get_small_cache(context_t *ctx);
91 extern void context_reset_small_cache(context_t *ctx);
92 extern void context_free_small_cache(context_t *ctx);
93
94
95 /*
96 * Allocate/free the cache
97 * - same conventions as for the small_cache
98 */
99 extern int_bvset_t *context_get_cache(context_t *ctx);
100 extern void context_free_cache(context_t *ctx);
101
102
103 /*
104 * Buffers for polynomials
105 */
106 extern rba_buffer_t *context_get_arith_buffer(context_t *ctx);
107 extern void context_free_arith_buffer(context_t *ctx);
108
109 extern poly_buffer_t *context_get_poly_buffer(context_t *ctx);
110 extern void context_free_poly_buffer(context_t *ctx);
111 extern void context_reset_poly_buffer(context_t *ctx);
112
113
114 /*
115 * Allocate the auxiliary polynomial buffer and make it large enough
116 * for n monomials.
117 */
118 extern polynomial_t *context_get_aux_poly(context_t *ctx, uint32_t n);
119
120 /*
121 * Free the auxiliary polynomial
122 */
123 extern void context_free_aux_poly(context_t *ctx);
124
125
126 /*
127 * Buffers for bitvector polynomials
128 */
129 extern bvpoly_buffer_t *context_get_bvpoly_buffer(context_t *ctx);
130 extern void context_free_bvpoly_buffer(context_t *ctx);
131
132
133
134 /*
135 * EQUALITY CACHE
136 */
137
138 /*
139 * If lift-if is enabled then arithmetic equalities
140 * (eq (ite c t1 t2) u) are rewritten to (ite c (eq t1 u) (eq t2 u))
141 * We don't create new terms (eq t1 u) or (eq t2 u). Instead, we store
142 * the internalization of equalities (eq t1 u) in the eq_cache:
143 * This cache maps pairs of terms <t, u> to a literal l (such that
144 * l is the internalization of (t == u)).
145 *
146 * The following functions operate on this cache: reset/free/push/pop
147 * do nothing if the cache does not exist.
148 */
149 extern pmap2_t *context_get_eq_cache(context_t *ctx);
150 extern void context_free_eq_cache(context_t *ctx);
151 extern void context_eq_cache_push(context_t *ctx);
152 extern void context_eq_cache_pop(context_t *ctx);
153
context_reset_eq_cache(context_t * ctx)154 static inline void context_reset_eq_cache(context_t *ctx) {
155 context_free_eq_cache(ctx);
156 }
157
158
159 /*
160 * Check what's mapped to (t1, t2) in the internal eq_cache.
161 * - return null_literal if nothing is mapped to (t1, t2) (or if the cache does not exit)
162 */
163 extern literal_t find_in_eq_cache(context_t *ctx, term_t t1, term_t t2);
164
165
166 /*
167 * Add the mapping (t1, t2) --> l to the equality cache.
168 * - allocate and initialize the cache if needed.
169 * - the pair (t1, t2) must not be in the cache already.
170 * - l must be different from null_literal
171 */
172 extern void add_to_eq_cache(context_t *ctx, term_t t1, term_t t2, literal_t l);
173
174
175
176 /*
177 * DIV/MOD TABLE
178 */
179
180 /*
181 * Initialization/reset/deletion and push/pop
182 * - get_divmod_table allocates and initializes the table if needed.
183 * - free/reset/push/pop do nothing if the table does not exist.
184 */
185 extern divmod_tbl_t *context_get_divmod_table(context_t *ctx);
186 extern void context_free_divmod_table(context_t *ctx);
187 extern void context_reset_divmod_table(context_t *ctx);
188 extern void context_divmod_table_push(context_t *ctx);
189 extern void context_divmod_table_pop(context_t *ctx);
190
191
192 /*
193 * Check whether the record for (floor x) is in the table.
194 * If so return the theory variable mapped to (floor x).
195 * If not return null_thvar
196 * Also returns null_thvar if the table does not exist.
197 */
198 extern thvar_t context_find_var_for_floor(context_t *ctx, thvar_t x);
199
200
201 /*
202 * Check whether the record for (ceil x) is in the table.
203 * If so return the theory variable mapped to (ceil x).
204 * If not return null_thvar
205 * Also returns null_thvar if the table does not exist.
206 */
207 extern thvar_t context_find_var_for_ceil(context_t *ctx, thvar_t x);
208
209 /*
210 * Check whether the record for (div x k) is in the table.
211 * If so return the theory variable mapped to (div x k).
212 * If not return null_thvar.
213 * Also returns null_thvar if the table does not exist.
214 */
215 extern thvar_t context_find_var_for_div(context_t *ctx, thvar_t x, const rational_t *k);
216
217
218 /*
219 * Add record for (floor x):
220 * - y = theory variable for (floor x)
221 * - this creates the table if needed.
222 */
223 extern void context_record_floor(context_t *ctx, thvar_t x, thvar_t y);
224
225
226 /*
227 * Same thing for (ceil x)
228 * - y = theory variable for (ceil x)
229 */
230 extern void context_record_ceil(context_t *ctx, thvar_t x, thvar_t y);
231
232
233 /*
234 * Same thing for (div x k)
235 * - y = theory variable for (div x k)
236 */
237 extern void context_record_div(context_t *ctx, thvar_t x, const rational_t *k, thvar_t y);
238
239
240
241
242 /*
243 * FACTORING OF DISJUNCTS
244 */
245
246 /*
247 * Return the explorer data structure
248 * - allocate and initialize it if needed
249 */
250 extern bfs_explorer_t *context_get_explorer(context_t *ctx);
251
252 /*
253 * Free the explorer if it's not NULL
254 */
255 extern void context_free_explorer(context_t *ctx);
256
257 /*
258 * Reset it if it's not NULL
259 */
260 extern void context_reset_explorer(context_t *ctx);
261
262 /*
263 * Get the common factors of term t
264 * - this checks whether t is of the form (or (and ..) (and ..) ...))
265 * and stores all terms that occur in each conjuncts into vector v
266 * - example: if t is (or (and A B) (and A C D)) then A is stored in v
267 * - if t is not (OR ...) then t is added to v
268 *
269 * This allocates and initializes ctx->explorer if needed
270 */
271 extern void context_factor_disjunction(context_t *ctx, term_t t, ivector_t *v);
272
273
274 /*
275 * AUXILIARY ATOMS
276 */
277
278 /*
279 * Simplification procedures can add equalities to the aux_eq vector
280 * or atoms to the aux_atom vector. These vectors can then be processed
281 * later by the internalization/flatteining procedures.
282 */
283
284 /*
285 * Auxiliary equalities:
286 * - add a new equality (x == y) in the aux_eq vector.
287 * - this is useful for simplification procedures that are executed after
288 * assertion flattening (e.g., symmetry breaking).
289 * - the auxiliary equalities can then be processed by process_aux_eqs
290 */
291 extern void add_aux_eq(context_t *ctx, term_t x, term_t y);
292
293 /*
294 * Variant: add term e as an auxiliary equality
295 * - e can be either ARITH_BINEQ_ATOM or ARITH_EQ_ATOM
296 */
297 extern void add_arith_aux_eq(context_t *ctx, term_t eq);
298
299
300 /*
301 * Auxiliary atoms:
302 * - add atom a to the aux_atoms vector
303 * - the auxiliary atom can be processed later by process_aux_atoms
304 */
305 extern void add_aux_atom(context_t *ctx, term_t atom);
306
307
308
309 /*
310 * DIFFERENCE-LOGIC DATA
311 */
312
313 /*
314 * Map to compute a bound on the length path:
315 * - allocate and initialize the table if needed
316 */
317 extern int_rat_hmap_t *context_get_edge_map(context_t *ctx);
318
319 /*
320 * Delete the map
321 */
322 extern void context_free_edge_map(context_t *ctx);
323
324 /*
325 * Difference-logic profile:
326 * - allocate and initialize the structure if it does not exist
327 */
328 extern dl_data_t *context_get_dl_profile(context_t *ctx);
329
330 /*
331 * Free the profile record if it's not NULL
332 */
333 extern void context_free_dl_profile(context_t *ctx);
334
335
336 /*
337 * TESTS
338 */
339
340 /*
341 * Check whether t is true or false (i.e., mapped to 'true_occ' or 'false_occ'
342 * in the internalization table.
343 * - t must be a root in the internalization table
344 */
345 extern bool term_is_true(context_t *ctx, term_t t);
346 extern bool term_is_false(context_t *ctx, term_t t);
347
348 /*
349 * Check whether (or a[0] ... a[n-1]) is true by checking whether
350 * one of the a[i] is internalized to a true term
351 */
352 extern bool disjunct_is_true(context_t *ctx, term_t *a, uint32_t n);
353
354 /*
355 * Check whether t is not internalized and of the form (ite c a b)
356 * - takes the substitution into account
357 */
358 extern bool term_is_ite(context_t *ctx, term_t t);
359
360 /*
361 * Given a descriptor (ite c t e), checks whether it
362 * contains nested if-then-elses (i.e., whether t or e
363 * are themselves if-then-else terms).
364 *
365 * This takes the substitution/internalization table into account:
366 * - if t or e is already internalized, it's not considered an if-then-else
367 * - otherwise t and e are replaced by their root in the internalization
368 * table
369 */
370 extern bool ite_is_deep(context_t *ctx, composite_term_t *ite);
371
372
373
374 /*
375 * OPTIONS/SUPPORTED FEATURES
376 */
377
378 /*
379 * Set or clear preprocessing options
380 */
enable_variable_elimination(context_t * ctx)381 static inline void enable_variable_elimination(context_t *ctx) {
382 ctx->options |= VARELIM_OPTION_MASK;
383 }
384
disable_variable_elimination(context_t * ctx)385 static inline void disable_variable_elimination(context_t *ctx) {
386 ctx->options &= ~VARELIM_OPTION_MASK;
387 }
388
enable_or_flattening(context_t * ctx)389 static inline void enable_or_flattening(context_t *ctx) {
390 ctx->options |= FLATTENOR_OPTION_MASK;
391 }
392
disable_or_flattening(context_t * ctx)393 static inline void disable_or_flattening(context_t *ctx) {
394 ctx->options &= ~FLATTENOR_OPTION_MASK;
395 }
396
enable_diseq_and_or_flattening(context_t * ctx)397 static inline void enable_diseq_and_or_flattening(context_t *ctx) {
398 ctx->options |= FLATTENOR_OPTION_MASK|FLATTENDISEQ_OPTION_MASK;
399 }
400
disable_diseq_and_or_flattening(context_t * ctx)401 static inline void disable_diseq_and_or_flattening(context_t *ctx) {
402 ctx->options &= ~(FLATTENOR_OPTION_MASK|FLATTENDISEQ_OPTION_MASK);
403 }
404
enable_eq_abstraction(context_t * ctx)405 static inline void enable_eq_abstraction(context_t *ctx) {
406 ctx->options |= EQABSTRACT_OPTION_MASK;
407 }
408
disable_eq_abstraction(context_t * ctx)409 static inline void disable_eq_abstraction(context_t *ctx) {
410 ctx->options &= ~EQABSTRACT_OPTION_MASK;
411 }
412
enable_arith_elimination(context_t * ctx)413 static inline void enable_arith_elimination(context_t *ctx) {
414 ctx->options |= ARITHELIM_OPTION_MASK;
415 }
416
disable_arith_elimination(context_t * ctx)417 static inline void disable_arith_elimination(context_t *ctx) {
418 ctx->options &= ~ARITHELIM_OPTION_MASK;
419 }
420
enable_keep_ite(context_t * ctx)421 static inline void enable_keep_ite(context_t *ctx) {
422 ctx->options |= KEEP_ITE_OPTION_MASK;
423 }
424
disable_keep_ite(context_t * ctx)425 static inline void disable_keep_ite(context_t *ctx) {
426 ctx->options &= ~KEEP_ITE_OPTION_MASK;
427 }
428
enable_bvarith_elimination(context_t * ctx)429 static inline void enable_bvarith_elimination(context_t *ctx) {
430 ctx->options |= BVARITHELIM_OPTION_MASK;
431 }
432
disable_bvarith_elimination(context_t * ctx)433 static inline void disable_bvarith_elimination(context_t *ctx) {
434 ctx->options &= ~BVARITHELIM_OPTION_MASK;
435 }
436
enable_symmetry_breaking(context_t * ctx)437 static inline void enable_symmetry_breaking(context_t *ctx) {
438 ctx->options |= BREAKSYM_OPTION_MASK;
439 }
440
disable_symmetry_breaking(context_t * ctx)441 static inline void disable_symmetry_breaking(context_t *ctx) {
442 ctx->options &= ~BREAKSYM_OPTION_MASK;
443 }
444
enable_pseudo_inverse_simplification(context_t * ctx)445 static inline void enable_pseudo_inverse_simplification(context_t *ctx) {
446 ctx->options |= PSEUDO_INVERSE_OPTION_MASK;
447 }
448
disable_pseudo_inverse_simplification(context_t * ctx)449 static inline void disable_pseudo_inverse_simplification(context_t *ctx) {
450 ctx->options &= ~PSEUDO_INVERSE_OPTION_MASK;
451 }
452
enable_assert_ite_bounds(context_t * ctx)453 static inline void enable_assert_ite_bounds(context_t *ctx) {
454 ctx->options |= ITE_BOUNDS_OPTION_MASK;
455 }
456
disable_assert_ite_bounds(context_t * ctx)457 static inline void disable_assert_ite_bounds(context_t *ctx) {
458 ctx->options &= ~ITE_BOUNDS_OPTION_MASK;
459 }
460
enable_cond_def_preprocessing(context_t * ctx)461 static inline void enable_cond_def_preprocessing(context_t *ctx) {
462 ctx->options |= CONDITIONAL_DEF_OPTION_MASK;
463 }
464
disable_cond_def_preprocessing(context_t * ctx)465 static inline void disable_cond_def_preprocessing(context_t *ctx) {
466 ctx->options &= ~CONDITIONAL_DEF_OPTION_MASK;
467 }
468
enable_ite_flattening(context_t * ctx)469 static inline void enable_ite_flattening(context_t *ctx) {
470 ctx->options |= FLATTEN_ITE_OPTION_MASK;
471 }
472
disable_ite_flattening(context_t * ctx)473 static inline void disable_ite_flattening(context_t *ctx) {
474 ctx->options &= ~FLATTEN_ITE_OPTION_MASK;
475 }
476
enable_or_factoring(context_t * ctx)477 static inline void enable_or_factoring(context_t *ctx) {
478 ctx->options |= FACTOR_OR_OPTION_MASK;
479 }
480
disable_or_factoring(context_t * ctx)481 static inline void disable_or_factoring(context_t *ctx) {
482 ctx->options &= ~FACTOR_OR_OPTION_MASK;
483 }
484
485
486
487 /*
488 * Check which options are enabled
489 */
context_var_elim_enabled(context_t * ctx)490 static inline bool context_var_elim_enabled(context_t *ctx) {
491 return (ctx->options & VARELIM_OPTION_MASK) != 0;
492 }
493
context_flatten_or_enabled(context_t * ctx)494 static inline bool context_flatten_or_enabled(context_t *ctx) {
495 return (ctx->options & FLATTENOR_OPTION_MASK) != 0;
496 }
497
context_flatten_diseq_enabled(context_t * ctx)498 static inline bool context_flatten_diseq_enabled(context_t *ctx) {
499 return (ctx->options & FLATTENDISEQ_OPTION_MASK) != 0;
500 }
501
context_eq_abstraction_enabled(context_t * ctx)502 static inline bool context_eq_abstraction_enabled(context_t *ctx) {
503 return (ctx->options & EQABSTRACT_OPTION_MASK) != 0;
504 }
505
context_arith_elim_enabled(context_t * ctx)506 static inline bool context_arith_elim_enabled(context_t *ctx) {
507 return (ctx->options & ARITHELIM_OPTION_MASK) != 0;
508 }
509
context_keep_ite_enabled(context_t * ctx)510 static inline bool context_keep_ite_enabled(context_t *ctx) {
511 return (ctx->options & KEEP_ITE_OPTION_MASK) != 0;
512 }
513
context_bvarith_elim_enabled(context_t * ctx)514 static inline bool context_bvarith_elim_enabled(context_t *ctx) {
515 return (ctx->options & BVARITHELIM_OPTION_MASK) != 0;
516 }
517
context_breaksym_enabled(context_t * ctx)518 static inline bool context_breaksym_enabled(context_t *ctx) {
519 return (ctx->options & BREAKSYM_OPTION_MASK) != 0;
520 }
521
context_pseudo_inverse_enabled(context_t * ctx)522 static inline bool context_pseudo_inverse_enabled(context_t *ctx) {
523 return (ctx->options & PSEUDO_INVERSE_OPTION_MASK) != 0;
524 }
525
context_ite_bounds_enabled(context_t * ctx)526 static inline bool context_ite_bounds_enabled(context_t *ctx) {
527 return (ctx->options & ITE_BOUNDS_OPTION_MASK) != 0;
528 }
529
context_cond_def_preprocessing_enabled(context_t * ctx)530 static inline bool context_cond_def_preprocessing_enabled(context_t *ctx) {
531 return (ctx->options & CONDITIONAL_DEF_OPTION_MASK) != 0;
532 }
533
context_ite_flattening_enabled(context_t * ctx)534 static inline bool context_ite_flattening_enabled(context_t *ctx) {
535 return (ctx->options & FLATTEN_ITE_OPTION_MASK) != 0;
536 }
537
context_or_factoring_enabled(context_t * ctx)538 static inline bool context_or_factoring_enabled(context_t *ctx) {
539 return (ctx->options & FACTOR_OR_OPTION_MASK) != 0;
540 }
541
context_has_preprocess_options(context_t * ctx)542 static inline bool context_has_preprocess_options(context_t *ctx) {
543 return (ctx->options & PREPROCESSING_OPTIONS_MASK) != 0;
544 }
545
context_dump_enabled(context_t * ctx)546 static inline bool context_dump_enabled(context_t *ctx) {
547 return (ctx->options & DUMP_OPTION_MASK) != 0;
548 }
549
splx_eager_lemmas_enabled(context_t * ctx)550 static inline bool splx_eager_lemmas_enabled(context_t *ctx) {
551 return (ctx->options & SPLX_EGRLMAS_OPTION_MASK) != 0;
552 }
553
splx_periodic_icheck_enabled(context_t * ctx)554 static inline bool splx_periodic_icheck_enabled(context_t *ctx) {
555 return (ctx->options & SPLX_ICHECK_OPTION_MASK) != 0;
556 }
557
splx_eqprop_enabled(context_t * ctx)558 static inline bool splx_eqprop_enabled(context_t *ctx) {
559 return (ctx->options & SPLX_EQPROP_OPTION_MASK) != 0;
560 }
561
562
563 /*
564 * Provisional: set/clear/test dump mode
565 */
enable_dump(context_t * ctx)566 static inline void enable_dump(context_t *ctx) {
567 ctx->options |= DUMP_OPTION_MASK;
568 }
569
disable_dump(context_t * ctx)570 static inline void disable_dump(context_t *ctx) {
571 ctx->options &= ~DUMP_OPTION_MASK;
572 }
573
574 // Lax mode
enable_lax_mode(context_t * ctx)575 static inline void enable_lax_mode(context_t *ctx) {
576 ctx->options |= LAX_OPTION_MASK;
577 }
578
disable_lax_mode(context_t * ctx)579 static inline void disable_lax_mode(context_t *ctx) {
580 ctx->options &= ~LAX_OPTION_MASK;
581 }
582
context_in_strict_mode(context_t * ctx)583 static inline bool context_in_strict_mode(context_t *ctx) {
584 return (ctx->options & LAX_OPTION_MASK) == 0;
585 }
586
587
588 /*
589 * Supported theories
590 */
context_allows_uf(context_t * ctx)591 static inline bool context_allows_uf(context_t *ctx) {
592 return (ctx->theories & UF_MASK) != 0;
593 }
594
context_allows_bv(context_t * ctx)595 static inline bool context_allows_bv(context_t *ctx) {
596 return (ctx->theories & BV_MASK) != 0;
597 }
598
context_allows_idl(context_t * ctx)599 static inline bool context_allows_idl(context_t *ctx) {
600 return (ctx->theories & IDL_MASK) != 0;
601 }
602
context_allows_rdl(context_t * ctx)603 static inline bool context_allows_rdl(context_t *ctx) {
604 return (ctx->theories & RDL_MASK) != 0;
605 }
606
context_allows_lia(context_t * ctx)607 static inline bool context_allows_lia(context_t *ctx) {
608 return (ctx->theories & LIA_MASK) != 0;
609 }
610
context_allows_lra(context_t * ctx)611 static inline bool context_allows_lra(context_t *ctx) {
612 return (ctx->theories & LRA_MASK) != 0;
613 }
614
context_allows_lira(context_t * ctx)615 static inline bool context_allows_lira(context_t *ctx) {
616 return (ctx->theories & LIRA_MASK) != 0;
617 }
618
context_allows_nlarith(context_t * ctx)619 static inline bool context_allows_nlarith(context_t *ctx) {
620 return (ctx->theories & NLIRA_MASK) != 0;
621 }
622
context_allows_fun_updates(context_t * ctx)623 static inline bool context_allows_fun_updates(context_t *ctx) {
624 return (ctx->theories & FUN_UPDT_MASK) != 0;
625 }
626
context_allows_extensionality(context_t * ctx)627 static inline bool context_allows_extensionality(context_t *ctx) {
628 return (ctx->theories & FUN_EXT_MASK) != 0;
629 }
630
context_allows_quantifiers(context_t * ctx)631 static inline bool context_allows_quantifiers(context_t *ctx) {
632 return (ctx->theories & QUANT_MASK) != 0;
633 }
634
635
636 /*
637 * Check which solvers are present
638 */
context_has_egraph(context_t * ctx)639 static inline bool context_has_egraph(context_t *ctx) {
640 return ctx->egraph != NULL;
641 }
642
context_has_arith_solver(context_t * ctx)643 static inline bool context_has_arith_solver(context_t *ctx) {
644 return ctx->arith_solver != NULL;
645 }
646
context_has_bv_solver(context_t * ctx)647 static inline bool context_has_bv_solver(context_t *ctx) {
648 return ctx->bv_solver != NULL;
649 }
650
context_has_fun_solver(context_t * ctx)651 static inline bool context_has_fun_solver(context_t *ctx) {
652 return ctx->fun_solver != NULL;
653 }
654
context_has_mcsat(context_t * ctx)655 static inline bool context_has_mcsat(context_t *ctx) {
656 return ctx->mcsat != NULL;
657 }
658
659
660 /*
661 * Get the difference-logic profile record (only useful for contexts
662 * with architecture CTX_ARCH_AUTO_IDL or CTX_ARCH_AUTO_RDL).
663 */
get_diff_logic_profile(context_t * ctx)664 static inline dl_data_t *get_diff_logic_profile(context_t *ctx) {
665 return ctx->dl_profile;
666 }
667
668
669 /*
670 * Optional features
671 */
context_supports_multichecks(context_t * ctx)672 static inline bool context_supports_multichecks(context_t *ctx) {
673 return (ctx->options & MULTICHECKS_OPTION_MASK) != 0;
674 }
675
context_supports_pushpop(context_t * ctx)676 static inline bool context_supports_pushpop(context_t *ctx) {
677 return (ctx->options & PUSHPOP_OPTION_MASK) != 0;
678 }
679
context_supports_cleaninterrupt(context_t * ctx)680 static inline bool context_supports_cleaninterrupt(context_t *ctx) {
681 return (ctx->options & CLEANINT_OPTION_MASK) != 0;
682 }
683
684
685 /*
686 * Read the mode flag
687 */
context_get_mode(context_t * ctx)688 static inline context_mode_t context_get_mode(context_t *ctx) {
689 return ctx->mode;
690 }
691
692
693 #endif /* __CONTEXT_UTILS_H */
694
695