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 * TABLE OF VARIABLES FOR THE BITVECTOR SOLVER
21 */
22
23 /*
24 * For each variable x, we store
25 * - bit_size[x] = number of bits in x
26 * - kind[x] = tag so that we know how to interpret def[x]
27 * - def[x] = definition of x
28 * - eterm[x] = attached egraph term (optional)
29 * - map[x] = array of literals (bit blasting)
30 *
31 * Several variables may share the same map. To delete the maps
32 * correctly in push/pop, we use reference counting. The literal
33 * arrays assigned to map[x] must be allocated with the
34 * refcount_int_array functions.
35 *
36 * We use two bits in kind[x] to mark variables and to record which variables
37 * have been bit-blasted:
38 */
39
40 #ifndef __BV_VARTABLE_H
41 #define __BV_VARTABLE_H
42
43 #include <stdint.h>
44 #include <stdbool.h>
45 #include <assert.h>
46
47 #include "solvers/cdcl/smt_core_base_types.h"
48 #include "solvers/egraph/egraph_base_types.h"
49 #include "terms/bvpoly_buffers.h"
50 #include "terms/power_products.h"
51 #include "utils/int_hash_tables.h"
52 #include "utils/refcount_int_arrays.h"
53
54
55
56 /*
57 * Tags for kind[x]
58 * - variables (no definition)
59 * - constants (small/large bitvector constants)
60 * - bit expressions
61 * - array of bit expressions
62 * - binary and unary operators (arithmetic + shift)
63 *
64 * For polynomials, we use two representations:
65 * - when created, polynomials have a bvpoly or bvpoly64 descriptor
66 * - in the first step of bit-blasting, we compile the polynomial
67 * expressions into the simpler operations that the bitblaster supports
68 * (i.e., binary ADD, SUB, MUL + NEG)
69 */
70 typedef enum bvvar_tag {
71 BVTAG_VAR, // uninterpreted bitvector
72 BVTAG_CONST64, // constant represented as a 64bit unsigned integer
73 BVTAG_CONST, // constant represented as an array of 32bit words
74 BVTAG_POLY64, // polynomial with small coefficients
75 BVTAG_POLY, // polynomial with large coefficients
76 BVTAG_PPROD, // power product
77 BVTAG_BIT_ARRAY, // array of literals
78 BVTAG_ITE, // if-then-else (mux)
79 BVTAG_UDIV, // quotient in unsigned division
80 BVTAG_UREM, // remainder in unsigned division
81 BVTAG_SDIV, // quotient in signed division (rounding towards 0)
82 BVTAG_SREM, // remainder in signed division (rounding towards 0)
83 BVTAG_SMOD, // remainder in floor division (rounding towards -infinity)
84 BVTAG_SHL, // shift left
85 BVTAG_LSHR, // logical shift right
86 BVTAG_ASHR, // arithmetic shift right
87
88 // auxiliary arithmetic operators for compilation of polynomials
89 BVTAG_ADD, // binary ADD
90 BVTAG_SUB, // binary SUB
91 BVTAG_MUL, // binary MUL
92 BVTAG_NEG, // opposite (one argument)
93 } bvvar_tag_t;
94
95 #define NUM_BVTAGS (BVTAG_NEG + 1)
96
97
98 /*
99 * Descriptor for (if c then x else y)
100 */
101 typedef struct bv_ite_s {
102 literal_t cond;
103 thvar_t left;
104 thvar_t right;
105 } bv_ite_t;
106
107
108 /*
109 * Descriptor (definition)
110 */
111 typedef union bvvar_desc_u {
112 uint64_t val; // for const64
113 thvar_t op[2]; // two variable operands
114 void *ptr; // pointer to polynomial/pprod/ite
115 } bvvar_desc_t;
116
117
118
119 /*
120 * Variable table
121 * - nvars = number of variables
122 * - size = size of arrays bit_size, kind, def, map
123 * = size of eterm if eterm isn't NULL
124 * - kind[x] is used both to store the tag for x and to mark x
125 * marking is done by setting the high-order bit of kind[x] to 1
126 * - the mark indicates whether or not bit-blasting has been done on x
127 */
128 typedef struct bv_vartable_s {
129 uint32_t nvars;
130 uint32_t size;
131
132 // definition, size, etc.
133 uint32_t *bit_size;
134 uint8_t *kind;
135 bvvar_desc_t *def;
136 eterm_t *eterm;
137
138 // mapping to literals
139 literal_t **map;
140
141 // hash consing
142 int_htbl_t htbl;
143 } bv_vartable_t;
144
145
146 #define DEF_BVVARTABLE_SIZE 100
147 #define MAX_BVVARTABLE_SIZE (UINT32_MAX/sizeof(bvvar_desc_t))
148
149
150
151 /*
152 * Bit masks for the kind:
153 * - bit 7: mark
154 * - bit 6: bit-blasted bit
155 * - bit 5 to 0: the tag
156 */
157
158 #define BVVAR_MARK_MASK ((uint8_t) 0x80)
159 #define BVVAR_BLST_MASK ((uint8_t) 0x40)
160 #define BVVAR_TAG_MASK ((uint8_t) 0x3F)
161
162
163
164 /*
165 * OPERATIONS
166 */
167
168 /*
169 * Initialize table
170 * - use the default size
171 * - the eterm array is not allocated here, but on the first
172 * call to attach_eterm
173 * - variable 0 is reserved to prevent confusion with const_idx
174 */
175 extern void init_bv_vartable(bv_vartable_t *table);
176
177
178 /*
179 * Delete the table
180 */
181 extern void delete_bv_vartable(bv_vartable_t *table);
182
183
184 /*
185 * Reset: empty the table
186 * - the variable 0 marker is kept
187 */
188 extern void reset_bv_vartable(bv_vartable_t *table);
189
190
191 /*
192 * Attach egraph term t to variable x
193 * - x must be not have an eterm attached already
194 */
195 extern void attach_eterm_to_bvvar(bv_vartable_t *table, thvar_t x, eterm_t t);
196
197
198 /*
199 * Check whether x has an eterm attached
200 */
bvvar_has_eterm(bv_vartable_t * table,thvar_t x)201 static inline bool bvvar_has_eterm(bv_vartable_t *table, thvar_t x) {
202 assert(1 <= x && x < table->nvars);
203 return table->eterm != NULL && table->eterm[x] != null_eterm;
204 }
205
206
207 /*
208 * Get the eterm attached to x or null_eterm
209 */
bvvar_get_eterm(bv_vartable_t * table,thvar_t x)210 static inline eterm_t bvvar_get_eterm(bv_vartable_t *table, thvar_t x) {
211 eterm_t t;
212
213 assert(1 <= x && x < table->nvars);
214 t = null_eterm;
215 if (table->eterm != NULL) {
216 t = table->eterm[x];
217 }
218 return t;
219 }
220
221
222 /*
223 * Remove all eterms of id >= nterms
224 */
225 extern void bv_vartable_remove_eterms(bv_vartable_t *table, uint32_t nterms);
226
227
228
229 /*
230 * Remove all variables of index >= nv
231 */
232 extern void bv_vartable_remove_vars(bv_vartable_t *table, uint32_t nv);
233
234
235
236 /*
237 * VARIABLE CONSTRUCTORS
238 */
239
240 /*
241 * All constructors check whether a variable matching the given definition
242 * is present in table. If so they return it. Otherwise, they create
243 * a new variable with the right descriptor and return it.
244 */
245
246 /*
247 * New variable: n = number of bits
248 */
249 extern thvar_t make_bvvar(bv_vartable_t *table, uint32_t n);
250
251
252 /*
253 * Constants: n = number of bits, val = constant value
254 * - val must be normalized modulo 2^n
255 */
256 extern thvar_t get_bvconst64(bv_vartable_t *table, uint32_t n, uint64_t val);
257 extern thvar_t get_bvconst(bv_vartable_t *table, uint32_t n, uint32_t *val);
258
259
260 /*
261 * Polynomials and power products
262 */
263 extern thvar_t get_bvpoly64(bv_vartable_t *table, bvpoly_buffer_t *buffer);
264 extern thvar_t get_bvpoly(bv_vartable_t *table, bvpoly_buffer_t *buffer);
265 extern thvar_t get_bvpprod(bv_vartable_t *table, uint32_t n, pp_buffer_t *buffer);
266
267
268 /*
269 * For all these constructors: n = number of bits
270 */
271 extern thvar_t get_bvarray(bv_vartable_t *table, uint32_t n, literal_t *a);
272 extern thvar_t get_bvite(bv_vartable_t *table, uint32_t n, literal_t l, thvar_t x, thvar_t y);
273 extern thvar_t get_bvdiv(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
274 extern thvar_t get_bvrem(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
275 extern thvar_t get_bvsdiv(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
276 extern thvar_t get_bvsrem(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
277 extern thvar_t get_bvsmod(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
278 extern thvar_t get_bvshl(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
279 extern thvar_t get_bvlshr(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
280 extern thvar_t get_bvashr(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y);
281
282
283 /*
284 * Search for (div x y), (rem x y), etc.
285 * - return -1 if the term is not in the table
286 */
287 extern thvar_t find_div(bv_vartable_t *table, thvar_t x, thvar_t y);
288 extern thvar_t find_rem(bv_vartable_t *table, thvar_t x, thvar_t y);
289 extern thvar_t find_sdiv(bv_vartable_t *table, thvar_t x, thvar_t y);
290 extern thvar_t find_srem(bv_vartable_t *table, thvar_t x, thvar_t y);
291
292
293
294 /*
295 * Auxiliary arithmetic nodes:
296 * - n = number of bits
297 * - x (and y is present) = operands
298 * - set new_var to true if a new variable is created
299 * set new_var to false if the variable was already present in table
300 */
301 extern thvar_t get_bvadd(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y, bool *new_var);
302 extern thvar_t get_bvsub(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y, bool *new_var);
303 extern thvar_t get_bvmul(bv_vartable_t *table, uint32_t n, thvar_t x, thvar_t y, bool *new_var);
304 extern thvar_t get_bvneg(bv_vartable_t *table, uint32_t n, thvar_t x, bool *new_var);
305
306 extern thvar_t find_bvadd(bv_vartable_t *table, thvar_t x, thvar_t y);
307 extern thvar_t find_bvsub(bv_vartable_t *table, thvar_t x, thvar_t y);
308 extern thvar_t find_bvmul(bv_vartable_t *table, thvar_t x, thvar_t y);
309 extern thvar_t find_bvneg(bv_vartable_t *table, thvar_t x);
310
311
312
313 /*
314 * Extract the tag out of kind[x]
315 * - kind[x] stores
316 * bit 7: mark bit
317 * bit 6: bitblasted bit
318 * bit 5--0: tag
319 */
tag_of_kind(uint8_t k)320 static inline bvvar_tag_t tag_of_kind(uint8_t k) {
321 return (bvvar_tag_t) (k & BVVAR_TAG_MASK);
322 }
323
mark_of_kind(uint8_t k)324 static inline bool mark_of_kind(uint8_t k) {
325 return (k & BVVAR_MARK_MASK) != 0;
326 }
327
blasted_of_kind(uint8_t k)328 static inline bool blasted_of_kind(uint8_t k) {
329 return (k & BVVAR_BLST_MASK) != 0;
330 }
331
332
333
334 /*
335 * ACCESS TO VARIABLE ATTRIBUTES
336 */
valid_bvvar(bv_vartable_t * table,thvar_t x)337 static inline bool valid_bvvar(bv_vartable_t *table, thvar_t x) {
338 return 0 <= x && x < table->nvars;
339 }
340
bvvar_tag(bv_vartable_t * table,thvar_t x)341 static inline bvvar_tag_t bvvar_tag(bv_vartable_t *table, thvar_t x) {
342 assert(valid_bvvar(table, x));
343 return tag_of_kind(table->kind[x]);
344 }
345
bvvar_is_marked(bv_vartable_t * table,thvar_t x)346 static inline bool bvvar_is_marked(bv_vartable_t *table, thvar_t x) {
347 assert(valid_bvvar(table, x));
348 return mark_of_kind(table->kind[x]);
349 }
350
bvvar_is_bitblasted(bv_vartable_t * table,thvar_t x)351 static inline bool bvvar_is_bitblasted(bv_vartable_t *table, thvar_t x) {
352 assert(valid_bvvar(table, x));
353 return blasted_of_kind(table->kind[x]);
354 }
355
bvvar_bitsize(bv_vartable_t * table,thvar_t x)356 static inline uint32_t bvvar_bitsize(bv_vartable_t *table, thvar_t x) {
357 assert(valid_bvvar(table, x));
358 return table->bit_size[x];
359 }
360
bvvar_is_uninterpreted(bv_vartable_t * table,thvar_t x)361 static inline bool bvvar_is_uninterpreted(bv_vartable_t *table, thvar_t x) {
362 return bvvar_tag(table, x) == BVTAG_VAR;
363 }
364
bvvar_is_const64(bv_vartable_t * table,thvar_t x)365 static inline bool bvvar_is_const64(bv_vartable_t *table, thvar_t x) {
366 return bvvar_tag(table, x) == BVTAG_CONST64;
367 }
368
bvvar_is_const(bv_vartable_t * table,thvar_t x)369 static inline bool bvvar_is_const(bv_vartable_t *table, thvar_t x) {
370 return bvvar_tag(table, x) == BVTAG_CONST;
371 }
372
bvvar_is_poly64(bv_vartable_t * table,thvar_t x)373 static inline bool bvvar_is_poly64(bv_vartable_t *table, thvar_t x) {
374 return bvvar_tag(table, x) == BVTAG_POLY64;
375 }
376
bvvar_is_poly(bv_vartable_t * table,thvar_t x)377 static inline bool bvvar_is_poly(bv_vartable_t *table, thvar_t x) {
378 return bvvar_tag(table, x) == BVTAG_POLY;
379 }
380
bvvar_is_pprod(bv_vartable_t * table,thvar_t x)381 static inline bool bvvar_is_pprod(bv_vartable_t *table, thvar_t x) {
382 return bvvar_tag(table, x) == BVTAG_PPROD;
383 }
384
bvvar_is_bvarray(bv_vartable_t * table,thvar_t x)385 static inline bool bvvar_is_bvarray(bv_vartable_t *table, thvar_t x) {
386 return bvvar_tag(table, x) == BVTAG_BIT_ARRAY;
387 }
388
bvvar_is_ite(bv_vartable_t * table,thvar_t x)389 static inline bool bvvar_is_ite(bv_vartable_t *table, thvar_t x) {
390 return bvvar_tag(table, x) == BVTAG_ITE;
391 }
392
393
394 /*
395 * Value of a constant
396 */
bvvar_val64(bv_vartable_t * table,thvar_t x)397 static inline uint64_t bvvar_val64(bv_vartable_t *table, thvar_t x) {
398 assert(bvvar_is_const64(table, x));
399 return table->def[x].val;
400 }
401
bvvar_val(bv_vartable_t * table,thvar_t x)402 static inline uint32_t *bvvar_val(bv_vartable_t *table, thvar_t x) {
403 assert(bvvar_is_const(table, x));
404 return table->def[x].ptr;
405 }
406
407
408 /*
409 * Definition of a variable x
410 */
bvvar_poly_def(bv_vartable_t * table,thvar_t x)411 static inline bvpoly_t *bvvar_poly_def(bv_vartable_t *table, thvar_t x) {
412 assert(bvvar_is_poly(table, x));
413 return table->def[x].ptr;
414 }
415
bvvar_poly64_def(bv_vartable_t * table,thvar_t x)416 static inline bvpoly64_t *bvvar_poly64_def(bv_vartable_t *table, thvar_t x) {
417 assert(bvvar_is_poly64(table, x));
418 return table->def[x].ptr;
419 }
420
bvvar_pprod_def(bv_vartable_t * table,thvar_t x)421 static inline pprod_t *bvvar_pprod_def(bv_vartable_t *table, thvar_t x) {
422 assert(bvvar_is_pprod(table, x));
423 return table->def[x].ptr;
424 }
425
bvvar_bvarray_def(bv_vartable_t * table,thvar_t x)426 static inline literal_t *bvvar_bvarray_def(bv_vartable_t *table, thvar_t x) {
427 assert(bvvar_is_bvarray(table, x));
428 return table->def[x].ptr;
429 }
430
bvvar_ite_def(bv_vartable_t * table,thvar_t x)431 static inline bv_ite_t *bvvar_ite_def(bv_vartable_t *table, thvar_t x) {
432 assert(bvvar_is_ite(table, x));
433 return table->def[x].ptr;
434 }
435
436 // pair of operands
bvvar_binop(bv_vartable_t * table,thvar_t x)437 static inline thvar_t *bvvar_binop(bv_vartable_t *table, thvar_t x) {
438 assert(bvvar_tag(table, x) >= BVTAG_UDIV);
439 return table->def[x].op;
440 }
441
442
443 /*
444 * Check whether variable x is mapped to something
445 */
bvvar_is_mapped(bv_vartable_t * table,thvar_t x)446 static inline bool bvvar_is_mapped(bv_vartable_t *table, thvar_t x) {
447 assert(valid_bvvar(table, x));
448 return table->map[x] != NULL;
449 }
450
451
452 /*
453 * Return the literal array mapped to x (NULL if nothing is mapped)
454 */
bvvar_get_map(bv_vartable_t * table,thvar_t x)455 static inline literal_t *bvvar_get_map(bv_vartable_t *table, thvar_t x) {
456 assert(valid_bvvar(table, x));
457 return table->map[x];
458 }
459
460
461 /*
462 * Map literal array a to variable x
463 * - a must be non-null and allocated using int_array_alloc
464 */
bvvar_set_map(bv_vartable_t * table,thvar_t x,literal_t * a)465 static inline void bvvar_set_map(bv_vartable_t *table, thvar_t x, literal_t *a) {
466 assert(! bvvar_is_mapped(table, x) && a != NULL);
467 int_array_incref(a);
468 table->map[x] = a;
469 }
470
471
472 /*
473 * Reset the map of x to NULL
474 * - x must have a non-null map
475 */
bvvar_reset_map(bv_vartable_t * table,thvar_t x)476 static inline void bvvar_reset_map(bv_vartable_t *table, thvar_t x) {
477 assert(bvvar_is_mapped(table, x));
478 int_array_decref(table->map[x]);
479 table->map[x] = NULL;
480 }
481
482
483 /*
484 * Set/clear the mark on x
485 */
bvvar_set_mark(bv_vartable_t * table,thvar_t x)486 static inline void bvvar_set_mark(bv_vartable_t *table, thvar_t x) {
487 assert(valid_bvvar(table, x));
488 table->kind[x] |= BVVAR_MARK_MASK;
489 }
490
bvvar_clr_mark(bv_vartable_t * table,thvar_t x)491 static inline void bvvar_clr_mark(bv_vartable_t *table, thvar_t x) {
492 assert(valid_bvvar(table, x));
493 table->kind[x] &= (uint8_t)(~BVVAR_MARK_MASK);
494 }
495
496
497 /*
498 * Set/clear the bit-blasted bit on x
499 */
bvvar_set_bitblasted(bv_vartable_t * table,thvar_t x)500 static inline void bvvar_set_bitblasted(bv_vartable_t *table, thvar_t x) {
501 assert(valid_bvvar(table, x));
502 table->kind[x] |= BVVAR_BLST_MASK;
503 }
504
bvvar_clr_bitblasted(bv_vartable_t * table,thvar_t x)505 static inline void bvvar_clr_bitblasted(bv_vartable_t *table, thvar_t x) {
506 assert(valid_bvvar(table, x));
507 table->kind[x] &= (uint8_t) (~BVVAR_BLST_MASK);
508 }
509
510
511
512 #endif /* __BV_VARTABLE_H */
513