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