boolector-1.5.118-6b56be4-121013/0000775000175000017500000000000012036253615014422 5ustar bierebiereboolector-1.5.118-6b56be4-121013/btorbtor.c0000664000175000017500000012367211761140525016435 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btorbtor.h" #include "btormem.h" #include "btorstack.h" #include "btorconst.h" #include "btorparse.h" #include "btorutil.h" #include #include #include #include #include typedef struct BtorBTORParser BtorBTORParser; typedef BtorNode *(*BtorOpParser) (BtorBTORParser *, int len); typedef BtorNode *(*Unary) (Btor *, BtorNode *); typedef BtorNode *(*Binary) (Btor *, BtorNode *, BtorNode *); typedef BtorNode *(*Shift) (Btor *, BtorNode *, BtorNode *); typedef BtorNode *(*Extend) (Btor *, BtorNode *, int); #define SIZE_PARSERS 128 typedef struct Info Info; struct Info { unsigned var : 1; unsigned array : 1; unsigned next : 1; }; BTOR_DECLARE_STACK (Info, Info); struct BtorBTORParser { BtorMemMgr *mem; Btor *btor; int nprefix; BtorCharStack * prefix; FILE *file; int lineno; int saved; /* boolean flag */ int saved_char; const char *name; char *error; BtorNodePtrStack exps; BtorInfoStack info; BtorNodePtrStack inputs; BtorNodePtrStack outputs; BtorNodePtrStack regs; BtorNodePtrStack nexts; BtorCharStack op; BtorCharStack constant; BtorCharStack symbol; BtorOpParser *parsers; const char **ops; int idx; int verbosity; int found_arrays; }; static unsigned btor_primes_btor[4] = { 111130391, 22237357, 33355519, 444476887 }; #define BTOR_PRIMES_BTOR \ ((sizeof btor_primes_btor) / sizeof btor_primes_btor[0]) static void btor_msg_btor (char *fmt, ...) { va_list ap; fprintf (stdout, "[btorbtor] "); va_start (ap, fmt); vfprintf (stdout, fmt, ap); va_end (ap); fputc ('\n', stdout); fflush (stdout); } static unsigned hash_op (const char *str, unsigned salt) { unsigned i, res; const char *p; assert (salt < BTOR_PRIMES_BTOR); res = 0; i = salt; for (p = str; *p; p++) { res += btor_primes_btor[i++] * (unsigned) *p; if (i == BTOR_PRIMES_BTOR) i = 0; } res &= SIZE_PARSERS - 1; return res; } static const char * btor_perr_btor (BtorBTORParser * parser, const char *fmt, ...) { size_t bytes; va_list ap; if (!parser->error) { va_start (ap, fmt); bytes = btor_parse_error_message_length (parser->name, fmt, ap); va_end (ap); va_start (ap, fmt); parser->error = btor_parse_error_message (parser->mem, parser->name, parser->lineno, fmt, ap, bytes); va_end (ap); } return parser->error; } static int btor_nextch_btor (BtorBTORParser * parser) { int ch; if (parser->saved) { ch = parser->saved_char; parser->saved = 0; } else if (parser->prefix && parser->nprefix < BTOR_COUNT_STACK (*parser->prefix)) { ch = parser->prefix->start[parser->nprefix++]; } else ch = getc (parser->file); if (ch == '\n') parser->lineno++; return ch; } static void btor_savech_btor (BtorBTORParser * parser, int ch) { assert (!parser->saved); parser->saved_char = ch; parser->saved = 1; if (ch == '\n') { assert (parser->lineno > 1); parser->lineno--; } } static const char * parse_non_negative_int (BtorBTORParser * parser, int *res_ptr) { int res, ch; ch = btor_nextch_btor (parser); if (!isdigit (ch)) return btor_perr_btor (parser, "expected digit"); if (ch == '0') { res = 0; ch = btor_nextch_btor (parser); if (isdigit (ch)) return btor_perr_btor (parser, "digit after '0'"); } else { res = ch - '0'; while (isdigit (ch = btor_nextch_btor (parser))) res = 10 * res + (ch - '0'); } btor_savech_btor (parser, ch); *res_ptr = res; return 0; } static const char * parse_positive_int (BtorBTORParser * parser, int *res_ptr) { int res, ch; ch = btor_nextch_btor (parser); if (!isdigit (ch)) return btor_perr_btor (parser, "expected digit"); if (ch == '0') return btor_perr_btor (parser, "expected non zero digit"); res = ch - '0'; while (isdigit (ch = btor_nextch_btor (parser))) res = 10 * res + (ch - '0'); btor_savech_btor (parser, ch); *res_ptr = res; return 0; } static const char * parse_non_zero_int (BtorBTORParser * parser, int *res_ptr) { int res, sign, ch; ch = btor_nextch_btor (parser); if (ch == '-') { sign = -1; ch = btor_nextch_btor (parser); if (!isdigit (ch) || ch == '0') return btor_perr_btor (parser, "expected non zero digit after '-'"); } else { sign = 1; if (!isdigit (ch) || ch == '0') return btor_perr_btor (parser, "expected non zero digit or '-'"); } res = ch - '0'; while (isdigit (ch = btor_nextch_btor (parser))) res = 10 * res + (ch - '0'); btor_savech_btor (parser, ch); res *= sign; *res_ptr = res; return 0; } static BtorNode * parse_exp (BtorBTORParser * parser, int expected_len, int can_be_array) { int lit, idx, len_res; BtorNode *res; lit = 0; if (parse_non_zero_int (parser, &lit)) return 0; idx = abs (lit); assert (idx); if (idx >= BTOR_COUNT_STACK (parser->exps) || !(res = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "literal '%d' undefined", lit); return 0; } if (!can_be_array && btor_is_array_exp (parser->btor, res)) { (void) btor_perr_btor (parser, "literal '%d' refers to an unexpected array expression", lit); return 0; } if (expected_len) { len_res = btor_get_exp_len (parser->btor, res); if (expected_len != len_res) { (void) btor_perr_btor (parser, "literal '%d' has length '%d' but expected '%d'", lit, len_res, expected_len); return 0; } } if (lit < 0) res = btor_not_exp (parser->btor, res); else res = btor_copy_exp (parser->btor, res); return res; } static const char * parse_space (BtorBTORParser * parser) { int ch; ch = btor_nextch_btor (parser); if (ch != ' ' && ch != '\t') return btor_perr_btor (parser, "expected space or tab"); SKIP: ch = btor_nextch_btor (parser); if (ch == ' ' || ch == '\t') goto SKIP; if (!ch) return btor_perr_btor (parser, "unexpected character"); btor_savech_btor (parser, ch); return 0; } static int parse_symbol (BtorBTORParser * parser) { char buffer[20]; const char * p; int ch; while ((ch = btor_nextch_btor (parser)) == ' ' || ch == '\t') ; if (ch == EOF) { UNEXPECTED_EOF: (void) btor_perr_btor (parser, "unexpected EOF"); return 0; } assert (BTOR_EMPTY_STACK (parser->symbol)); if (ch == '\n') { sprintf (buffer, "%d", parser->idx); for (p = buffer; *p; p++) BTOR_PUSH_STACK (parser->mem, parser->symbol, *p); } else { BTOR_PUSH_STACK (parser->mem, parser->symbol, ch); while (!isspace (ch = btor_nextch_btor (parser))) { if (ch == EOF) goto UNEXPECTED_EOF; BTOR_PUSH_STACK (parser->mem, parser->symbol, ch); } } btor_savech_btor (parser, ch); BTOR_PUSH_STACK (parser->mem, parser->symbol, 0); BTOR_RESET_STACK (parser->symbol); return 1; } static BtorNode * parse_var (BtorBTORParser * parser, int len) { BtorNode *res; if (!parse_symbol (parser)) return 0; res = btor_var_exp (parser->btor, len, parser->symbol.start); BTOR_PUSH_STACK (parser->mem, parser->inputs, res); parser->info.start[parser->idx].var = 1; return res; } static BtorNode * parse_array (BtorBTORParser * parser, int len) { BtorNode *res; int idx_len; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx_len)) return 0; if (!parse_symbol (parser)) return 0; res = btor_array_exp (parser->btor, len, idx_len, parser->symbol.start); BTOR_PUSH_STACK (parser->mem, parser->inputs, res); parser->info.start[parser->idx].array = 1; parser->found_arrays = 1; return res; } static BtorNode * parse_array_exp (BtorBTORParser * parser, int len) { BtorNode * res; res = parse_exp (parser, len, 1); if (!res) return 0; if (btor_is_array_exp (parser->btor, res)) return res; (void) btor_perr_btor (parser, "expected array expression"); btor_release_exp (parser->btor, res); return 0; } static BtorNode * parse_next (BtorBTORParser * parser, int len) { int idx; BtorNode * current, * next; Info info; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx)) return 0; if (idx >= BTOR_COUNT_STACK (parser->exps) || !(current = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "invalid next index %d", idx); return 0; } info = parser->info.start[idx]; if (!info.var) { (void) btor_perr_btor (parser, "next index %d is not a variable", idx); return 0; } if (info.next) { (void) btor_perr_btor (parser, "next index %d already used", idx); return 0; } if (parse_space (parser)) return 0; assert (!btor_is_array_exp (parser->btor, current)); if (!(next = parse_exp (parser, len, 0))) return 0; BTOR_PUSH_STACK (parser->mem, parser->regs, current); BTOR_PUSH_STACK (parser->mem, parser->nexts, next); parser->info.start[idx].next = 1; return next; } static BtorNode * parse_anext (BtorBTORParser * parser, int len) { int idx, current_idx_len, idx_len; BtorNode * current, * next; Info info; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx_len)) return 0; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx)) return 0; if (idx >= BTOR_COUNT_STACK (parser->exps) || !(current = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "invalid next index %d", idx); return 0; } info = parser->info.start[idx]; if (!info.array) { (void) btor_perr_btor (parser, "next index %d is not an array", idx); return 0; } if (info.next) { (void) btor_perr_btor (parser, "next index %d already used", idx); return 0; } if (parse_space (parser)) return 0; assert (btor_is_array_exp (parser->btor, current)); if (!(next = parse_array_exp (parser, len))) return 0; current_idx_len = btor_get_index_exp_len (parser->btor, current); if (idx_len != current_idx_len) { btor_release_exp (parser->btor, next); (void) btor_perr_btor (parser, "arrays with different index width %d and %d", current_idx_len, idx_len); return 0; } BTOR_PUSH_STACK (parser->mem, parser->regs, current); BTOR_PUSH_STACK (parser->mem, parser->nexts, next); parser->info.start[idx].next = 1; return next; } static BtorNode * parse_const (BtorBTORParser * parser, int len) { BtorNode *res; int ch, clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF && ch != ';') { if (ch != '0' && ch != '1') { (void) btor_perr_btor (parser, "expected '0' or '1'"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); } btor_savech_btor (parser, ch); clen = BTOR_COUNT_STACK (parser->constant); BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); if (clen != len) { (void) btor_perr_btor (parser, "binary constant '%s' exceeds bit width %d", parser->constant.start, len); return 0; } res = btor_const_exp (parser->btor, parser->constant.start); return res; } static BtorNode * parse_consth (BtorBTORParser * parser, int len) { char * tmp, * extended; BtorNode *res; int ch, clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF && ch != ';') { if (!isxdigit (ch)) { (void) btor_perr_btor (parser, "expected hexidecimal digit"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); } btor_savech_btor (parser, ch); clen = BTOR_COUNT_STACK (parser->constant); BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); tmp = btor_hex_to_const_n (parser->mem, parser->constant.start, clen); clen = (int) strlen (tmp); if (clen > len) { (void) btor_perr_btor (parser, "hexadecimal constant '%s' exceeds bit width %d", parser->constant.start, len); btor_freestr (parser->mem, tmp); return 0; } if (clen < len) { extended = btor_uext_const (parser->mem, tmp, len - clen); btor_delete_const (parser->mem, tmp); tmp = extended; } assert (len == (int) strlen (tmp)); res = btor_const_exp (parser->btor, tmp); btor_freestr (parser->mem, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; } static BtorNode * parse_constd (BtorBTORParser * parser, int len) { char ch, *tmp, * extended; BtorNode *res; int clen; if (parse_space (parser)) return 0; assert (BTOR_EMPTY_STACK (parser->constant)); ch = btor_nextch_btor (parser); if (!isdigit (ch)) { (void) btor_perr_btor (parser, "expected digit"); return 0; } BTOR_PUSH_STACK (parser->mem, parser->constant, ch); if (ch == '0') { ch = btor_nextch_btor (parser); if (isdigit (ch)) { (void) btor_perr_btor (parser, "digit after '0'"); return 0; } tmp = btor_strdup (parser->mem, ""); } else { while (isdigit (ch = btor_nextch_btor (parser))) BTOR_PUSH_STACK (parser->mem, parser->constant, ch); clen = BTOR_COUNT_STACK (parser->constant); tmp = btor_decimal_to_const_n (parser->mem, parser->constant.start, clen); } BTOR_PUSH_STACK (parser->mem, parser->constant, 0); BTOR_RESET_STACK (parser->constant); btor_savech_btor (parser, ch); clen = (int) strlen (tmp); if (clen > len) { (void) btor_perr_btor (parser, "decimal constant '%s' exceeds bit width %d", parser->constant.start, len); btor_freestr (parser->mem, tmp); return 0; } if (clen < len) { extended = btor_uext_const (parser->mem, tmp, len - clen); btor_delete_const (parser->mem, tmp); tmp = extended; } assert (len == (int) strlen (tmp)); res = btor_const_exp (parser->btor, tmp); btor_delete_const (parser->mem, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; } static BtorNode * parse_zero (BtorBTORParser * parser, int len) { return btor_zero_exp (parser->btor, len); } static BtorNode * parse_one (BtorBTORParser * parser, int len) { return btor_one_exp (parser->btor, len); } static BtorNode * parse_ones (BtorBTORParser * parser, int len) { return btor_ones_exp (parser->btor, len); } static BtorNode * parse_root (BtorBTORParser * parser, int len) { BtorNode *res; if (parse_space (parser)) return 0; if (!(res = parse_exp (parser, len, 0))) return 0; BTOR_PUSH_STACK (parser->mem, parser->outputs, res); return res; } static BtorNode * parse_unary (BtorBTORParser * parser, int len, Unary f) { BtorNode *tmp, *res; assert (len); if (parse_space (parser)) return 0; if (!(tmp = parse_exp (parser, len, 0))) return 0; res = f (parser->btor, tmp); btor_release_exp (parser->btor, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; } static BtorNode * parse_not (BtorBTORParser * parser, int len) { return parse_unary (parser, len, btor_not_exp); } static BtorNode * parse_neg (BtorBTORParser * parser, int len) { return parse_unary (parser, len, btor_neg_exp); } static BtorNode * parse_inc (BtorBTORParser * parser, int len) { return parse_unary (parser, len, btor_inc_exp); } static BtorNode * parse_dec (BtorBTORParser * parser, int len) { return parse_unary (parser, len, btor_dec_exp); } static BtorNode * parse_proxy (BtorBTORParser * parser, int len) { return parse_unary (parser, len, btor_copy_exp); } static BtorNode * parse_redunary (BtorBTORParser * parser, int len, Unary f) { BtorNode *tmp, *res; (void) len; assert (len == 1); if (parse_space (parser)) return 0; if (!(tmp = parse_exp (parser, 0, 0))) return 0; if (btor_get_exp_len (parser->btor, tmp) == 1) { (void) btor_perr_btor (parser, "argument of reduction operation of width 1"); btor_release_exp (parser->btor, tmp); return 0; } res = f (parser->btor, tmp); btor_release_exp (parser->btor, tmp); assert (btor_get_exp_len (parser->btor, res) == 1); return res; } static BtorNode * parse_redand (BtorBTORParser * parser, int len) { return parse_redunary (parser, len, btor_redand_exp); } static BtorNode * parse_redor (BtorBTORParser * parser, int len) { return parse_redunary (parser, len, btor_redor_exp); } static BtorNode * parse_redxor (BtorBTORParser * parser, int len) { return parse_redunary (parser, len, btor_redxor_exp); } static BtorNode * parse_binary (BtorBTORParser * parser, int len, Binary f) { BtorNode *l, *r, *res; assert (len); if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, len, 0))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, len, 0))) goto RELEASE_L_AND_RETURN_ERROR; res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == len); return res; } static BtorNode * parse_add (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_add_exp); } static BtorNode * parse_and (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_and_exp); } static BtorNode * parse_smod (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_smod_exp); } static BtorNode * parse_srem (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_srem_exp); } static BtorNode * parse_mul (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_mul_exp); } static BtorNode * parse_sub (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_sub_exp); } static BtorNode * parse_udiv (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_udiv_exp); } static BtorNode * parse_urem (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_urem_exp); } static BtorNode * parse_xor (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_xor_exp); } static BtorNode * parse_xnor (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_xnor_exp); } static BtorNode * parse_or (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_or_exp); } static BtorNode * parse_nor (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_nor_exp); } static BtorNode * parse_nand (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_nand_exp); } static BtorNode * parse_sdiv (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_sdiv_exp); } static BtorNode * parse_logical (BtorBTORParser * parser, int len, Binary f) { BtorNode * l, * r, * res; if (len != 1) { (void) btor_perr_btor (parser, "logical operator bit width '%d'", len); return 0; } if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, 0, 0))) return 0; if (btor_get_exp_len (parser->btor, l) != 1) { BIT_WIDTH_ERROR_RELEASE_L_AND_RETURN: (void) btor_perr_btor (parser, "expected argument of bit width '1'"); RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (parse_space (parser)) goto RELEASE_L_AND_RETURN_ERROR; if (!(r = parse_exp (parser, 0, 0))) goto RELEASE_L_AND_RETURN_ERROR; if (btor_get_exp_len (parser->btor, r) != 1) { btor_release_exp (parser->btor, r); goto BIT_WIDTH_ERROR_RELEASE_L_AND_RETURN; } res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == 1); return res; } static BtorNode * parse_implies (BtorBTORParser * parser, int len) { return parse_logical (parser, len, btor_implies_exp); } static BtorNode * parse_iff (BtorBTORParser * parser, int len) { return parse_logical (parser, len, btor_iff_exp); } static BtorNode * parse_compare_and_overflow (BtorBTORParser * parser, int len, Binary f, int can_be_array) { BtorNode *l, *r, *res; int llen, rlen; if (len != 1) { (void) btor_perr_btor (parser, "comparison or overflow operator returns %d bits", len); return 0; } if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, 0, can_be_array))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, 0, can_be_array))) goto RELEASE_L_AND_RETURN_ERROR; llen = btor_get_exp_len (parser->btor, l); rlen = btor_get_exp_len (parser->btor, r); if (llen != rlen) { (void) btor_perr_btor (parser, "operands have different bit width %d and %d", llen, rlen); RELEASE_L_AND_R_AND_RETURN_ZERO: btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); return 0; } if (can_be_array) { if (btor_is_array_exp (parser->btor, l) && !btor_is_array_exp (parser->btor, r)) { (void) btor_perr_btor (parser, "first operand is array and second not"); goto RELEASE_L_AND_R_AND_RETURN_ZERO; } if (!btor_is_array_exp (parser->btor, l) && btor_is_array_exp (parser->btor, r)) { (void) btor_perr_btor (parser, "second operand is array and first not"); goto RELEASE_L_AND_R_AND_RETURN_ZERO; } if (btor_is_array_exp (parser->btor, l) && btor_is_array_exp (parser->btor, r)) { llen = btor_get_index_exp_len (parser->btor, l); rlen = btor_get_index_exp_len (parser->btor, r); if (llen != rlen) { (void) btor_perr_btor ( parser, "array operands have different index width %d and %d", llen, rlen); goto RELEASE_L_AND_R_AND_RETURN_ZERO; } } } res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == 1); return res; } static BtorNode * parse_eq (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_eq_exp, 1); } static BtorNode * parse_ne (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_ne_exp, 1); } static BtorNode * parse_sgt (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_sgt_exp, 0); } static BtorNode * parse_sgte (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_sgte_exp, 0); } static BtorNode * parse_slt (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_slt_exp, 0); } static BtorNode * parse_slte (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_slte_exp, 0); } static BtorNode * parse_ugt (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_ugt_exp, 0); } static BtorNode * parse_ugte (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_ugte_exp, 0); } static BtorNode * parse_ult (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_ult_exp, 0); } static BtorNode * parse_ulte (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_ulte_exp, 0); } static BtorNode * parse_saddo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_saddo_exp, 0); } static BtorNode * parse_ssubo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_ssubo_exp, 0); } static BtorNode * parse_smulo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_smulo_exp, 0); } static BtorNode * parse_sdivo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_sdivo_exp, 0); } static BtorNode * parse_uaddo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_uaddo_exp, 0); } static BtorNode * parse_usubo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_usubo_exp, 0); } static BtorNode * parse_umulo (BtorBTORParser * parser, int len) { return parse_compare_and_overflow (parser, len, btor_umulo_exp, 0); } static BtorNode * parse_concat (BtorBTORParser * parser, int len) { BtorNode *l, *r, *res; int llen, rlen; if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, 0, 0))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, 0, 0))) goto RELEASE_L_AND_RETURN_ERROR; llen = btor_get_exp_len (parser->btor, l); rlen = btor_get_exp_len (parser->btor, r); if (llen + rlen != len) { (void) btor_perr_btor (parser, "operands widths %d and %d do not add up to %d", llen, rlen, len); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); return 0; } res = btor_concat_exp (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == len); return res; } static BtorNode * parse_shift (BtorBTORParser * parser, int len, Shift f) { BtorNode *l, *r, *res; int rlen; for (rlen = 1; rlen <= 30 && len != (1 << rlen); rlen++) ; if (len != (1 << rlen)) { (void) btor_perr_btor (parser, "length %d is not a power of two", len); return 0; } if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, len, 0))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, rlen, 0))) goto RELEASE_L_AND_RETURN_ERROR; res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == len); return res; } static BtorNode * parse_rol (BtorBTORParser * parser, int len) { return parse_shift (parser, len, btor_rol_exp); } static BtorNode * parse_ror (BtorBTORParser * parser, int len) { return parse_shift (parser, len, btor_ror_exp); } static BtorNode * parse_sll (BtorBTORParser * parser, int len) { return parse_shift (parser, len, btor_sll_exp); } static BtorNode * parse_sra (BtorBTORParser * parser, int len) { return parse_shift (parser, len, btor_sra_exp); } static BtorNode * parse_srl (BtorBTORParser * parser, int len) { return parse_shift (parser, len, btor_srl_exp); } static BtorNode * parse_cond (BtorBTORParser * parser, int len) { BtorNode *c, *t, *e, *res; if (parse_space (parser)) return 0; if (!(c = parse_exp (parser, 1, 0))) return 0; if (parse_space (parser)) { RELEASE_C_AND_RETURN_ERROR: btor_release_exp (parser->btor, c); return 0; } if (!(t = parse_exp (parser, len, 0))) goto RELEASE_C_AND_RETURN_ERROR; if (parse_space (parser)) { RELEASE_C_AND_T_AND_RETURN_ERROR: btor_release_exp (parser->btor, t); goto RELEASE_C_AND_RETURN_ERROR; } if (!(e = parse_exp (parser, len, 0))) goto RELEASE_C_AND_T_AND_RETURN_ERROR; res = btor_cond_exp (parser->btor, c, t, e); btor_release_exp (parser->btor, e); btor_release_exp (parser->btor, t); btor_release_exp (parser->btor, c); return res; } static BtorNode * parse_acond (BtorBTORParser * parser, int len) { BtorNode *c, *t, *e, *res; int idxlen; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idxlen)) return 0; if (parse_space (parser)) return 0; if (!(c = parse_exp (parser, 1, 0))) return 0; if (parse_space (parser)) { RELEASE_C_AND_RETURN_ERROR: btor_release_exp (parser->btor, c); return 0; } if (!(t = parse_array_exp (parser, len))) goto RELEASE_C_AND_RETURN_ERROR; if (idxlen != btor_get_index_exp_len (parser->btor, t)) { (void) btor_perr_btor (parser, "mismatch of index bit width of 'then' array"); RELEASE_C_AND_T_AND_RETURN_ERROR: btor_release_exp (parser->btor, t); goto RELEASE_C_AND_RETURN_ERROR; } if (parse_space (parser)) goto RELEASE_C_AND_T_AND_RETURN_ERROR; if (!(e = parse_array_exp (parser, len))) goto RELEASE_C_AND_T_AND_RETURN_ERROR; if (idxlen != btor_get_index_exp_len (parser->btor, e)) { (void) btor_perr_btor (parser, "mismatch of index bit width of 'else' array"); btor_release_exp (parser->btor, e); goto RELEASE_C_AND_T_AND_RETURN_ERROR; } res = btor_cond_exp (parser->btor, c, t, e); btor_release_exp (parser->btor, e); btor_release_exp (parser->btor, t); btor_release_exp (parser->btor, c); return res; } static BtorNode * parse_slice (BtorBTORParser * parser, int len) { int arglen, upper, lower, delta; BtorNode *res, *arg; if (parse_space (parser)) return 0; if (!(arg = parse_exp (parser, 0, 0))) return 0; if (parse_space (parser)) { RELEASE_ARG_AND_RETURN_ERROR: btor_release_exp (parser->btor, arg); return 0; } arglen = btor_get_exp_len (parser->btor, arg); if (parse_non_negative_int (parser, &upper)) goto RELEASE_ARG_AND_RETURN_ERROR; if (upper >= arglen) { (void) btor_perr_btor (parser, "upper index '%d' >= argument width '%d", upper, arglen); goto RELEASE_ARG_AND_RETURN_ERROR; } if (parse_space (parser)) goto RELEASE_ARG_AND_RETURN_ERROR; if (parse_non_negative_int (parser, &lower)) goto RELEASE_ARG_AND_RETURN_ERROR; if (upper < lower) { (void) btor_perr_btor (parser, "upper index '%d' smaller than lower index '%d'", upper, lower); goto RELEASE_ARG_AND_RETURN_ERROR; } delta = upper - lower + 1; if (delta != len) { (void) btor_perr_btor (parser, "slice width '%d' not equal to expected width '%d'", delta, len); goto RELEASE_ARG_AND_RETURN_ERROR; } res = btor_slice_exp (parser->btor, arg, upper, lower); btor_release_exp (parser->btor, arg); return res; } static BtorNode * parse_read (BtorBTORParser * parser, int len) { BtorNode *array, *idx, *res; int idxlen; if (parse_space (parser)) return 0; if (!(array = parse_array_exp (parser, len))) return 0; if (parse_space (parser)) { RELEASE_ARRAY_AND_RETURN_ERROR: btor_release_exp (parser->btor, array); return 0; } idxlen = btor_get_index_exp_len (parser->btor, array); if (!(idx = parse_exp (parser, idxlen, 0))) goto RELEASE_ARRAY_AND_RETURN_ERROR; res = btor_read_exp (parser->btor, array, idx); btor_release_exp (parser->btor, idx); btor_release_exp (parser->btor, array); return res; } static BtorNode * parse_write (BtorBTORParser * parser, int len) { BtorNode *array, *idx, *val, *res; int idxlen, vallen; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idxlen)) return 0; if (parse_space (parser)) return 0; if (!(array = parse_array_exp (parser, len))) return 0; if (parse_space (parser)) { RELEASE_ARRAY_AND_RETURN_ERROR: btor_release_exp (parser->btor, array); return 0; } if (!(idx = parse_exp (parser, idxlen, 0))) goto RELEASE_ARRAY_AND_RETURN_ERROR; if (parse_space (parser)) { RELEASE_ARRAY_AND_IDX_AND_RETURN_ERROR: btor_release_exp (parser->btor, idx); goto RELEASE_ARRAY_AND_RETURN_ERROR; } vallen = btor_get_exp_len (parser->btor, array); if (!(val = parse_exp (parser, vallen, 0))) goto RELEASE_ARRAY_AND_IDX_AND_RETURN_ERROR; res = btor_write_exp (parser->btor, array, idx, val); btor_release_exp (parser->btor, array); btor_release_exp (parser->btor, idx); btor_release_exp (parser->btor, val); return res; } static BtorNode * parse_ext (BtorBTORParser * parser, int len, Extend f) { BtorNode *res, *arg; int alen, elen; if (parse_space (parser)) return 0; if (!(arg = parse_exp (parser, 0, 0))) return 0; alen = btor_get_exp_len (parser->btor, arg); if (parse_space (parser)) { RELEASE_ARG_AND_RETURN_ERROR: btor_release_exp (parser->btor, arg); return 0; } if (parse_non_negative_int (parser, &elen)) goto RELEASE_ARG_AND_RETURN_ERROR; if (alen + elen != len) { (void) btor_perr_btor (parser, "argument length of %d plus %d does not match %d", alen, elen, len); goto RELEASE_ARG_AND_RETURN_ERROR; } res = f (parser->btor, arg, elen); assert (btor_get_exp_len (parser->btor, res) == len); btor_release_exp (parser->btor, arg); return res; } static BtorNode * parse_sext (BtorBTORParser * parser, int len) { return parse_ext (parser, len, btor_sext_exp); } static BtorNode * parse_uext (BtorBTORParser * parser, int len) { return parse_ext (parser, len, btor_uext_exp); } static void new_parser (BtorBTORParser * parser, BtorOpParser op_parser, const char *op) { unsigned p, d; p = hash_op (op, 0); assert (p < SIZE_PARSERS); if (parser->ops[p]) { d = hash_op (op, 1); if (!(d & 1)) d++; do { p += d; if (p >= SIZE_PARSERS) p -= SIZE_PARSERS; assert (p < SIZE_PARSERS); } while (parser->ops[p]); } parser->ops[p] = op; parser->parsers[p] = op_parser; } static BtorOpParser find_parser (BtorBTORParser * parser, const char *op) { const char *str; unsigned p, d; p = hash_op (op, 0); if ((str = parser->ops[p]) && strcasecmp (str, op)) { d = hash_op (op, 1); if (!(d & 1)) d++; do { p += d; if (p >= SIZE_PARSERS) p -= SIZE_PARSERS; } while ((str = parser->ops[p]) && strcasecmp (str, op)); } return str ? parser->parsers[p] : 0; } static BtorBTORParser * btor_new_btor_parser (Btor * btor, BtorParseOpt * opts) { BtorMemMgr *mem = btor->mm; BtorBTORParser *res; (void) opts->incremental; // TODO what about incremental? (void) opts->need_model; // TODO use at least this assert (opts->verbosity >= -1); BTOR_NEW (mem, res); BTOR_CLR (res); res->mem = mem; res->btor = btor; BTOR_NEWN (mem, res->parsers, SIZE_PARSERS); BTOR_NEWN (mem, res->ops, SIZE_PARSERS); BTOR_CLRN (res->ops, SIZE_PARSERS); new_parser (res, parse_add, "add"); new_parser (res, parse_and, "and"); new_parser (res, parse_array, "array"); new_parser (res, parse_concat, "concat"); new_parser (res, parse_cond, "cond"); new_parser (res, parse_acond, "acond"); new_parser (res, parse_const, "const"); new_parser (res, parse_constd, "constd"); new_parser (res, parse_consth, "consth"); new_parser (res, parse_eq, "eq"); new_parser (res, parse_iff, "iff"); new_parser (res, parse_implies, "implies"); new_parser (res, parse_mul, "mul"); new_parser (res, parse_nand, "nand"); new_parser (res, parse_neg, "neg"); new_parser (res, parse_inc, "inc"); new_parser (res, parse_dec, "dec"); new_parser (res, parse_ne, "ne"); new_parser (res, parse_next, "next"); /* only in parser */ new_parser (res, parse_anext, "anext"); /* only in parser */ new_parser (res, parse_nor, "nor"); new_parser (res, parse_not, "not"); new_parser (res, parse_one, "one"); new_parser (res, parse_ones, "ones"); new_parser (res, parse_or, "or"); new_parser (res, parse_proxy, "proxy"); new_parser (res, parse_read, "read"); new_parser (res, parse_redand, "redand"); new_parser (res, parse_redor, "redor"); new_parser (res, parse_redxor, "redxor"); new_parser (res, parse_rol, "rol"); new_parser (res, parse_root, "root"); /* only in parser */ new_parser (res, parse_ror, "ror"); new_parser (res, parse_saddo, "saddo"); new_parser (res, parse_sdivo, "sdivo"); new_parser (res, parse_sdiv, "sdiv"); new_parser (res, parse_sext, "sext"); new_parser (res, parse_sgte, "sgte"); new_parser (res, parse_sgt, "sgt"); new_parser (res, parse_slice, "slice"); new_parser (res, parse_sll, "sll"); new_parser (res, parse_slte, "slte"); new_parser (res, parse_slt, "slt"); new_parser (res, parse_smod, "smod"); new_parser (res, parse_smulo, "smulo"); new_parser (res, parse_sra, "sra"); new_parser (res, parse_srem, "srem"); new_parser (res, parse_srl, "srl"); new_parser (res, parse_ssubo, "ssubo"); new_parser (res, parse_sub, "sub"); new_parser (res, parse_uaddo, "uaddo"); new_parser (res, parse_udiv, "udiv"); new_parser (res, parse_uext, "uext"); new_parser (res, parse_ugte, "ugte"); new_parser (res, parse_ugt, "ugt"); new_parser (res, parse_ulte, "ulte"); new_parser (res, parse_ult, "ult"); new_parser (res, parse_umulo, "umulo"); new_parser (res, parse_urem, "urem"); new_parser (res, parse_usubo, "usubo"); new_parser (res, parse_var, "var"); new_parser (res, parse_write, "write"); new_parser (res, parse_xnor, "xnor"); new_parser (res, parse_xor, "xor"); new_parser (res, parse_zero, "zero"); res->verbosity = opts->verbosity; return res; } static void btor_delete_btor_parser (BtorBTORParser * parser) { BtorNode *e; int i; for (i = 0; i < BTOR_COUNT_STACK (parser->exps); i++) if ((e = parser->exps.start[i])) btor_release_exp (parser->btor, parser->exps.start[i]); BTOR_RELEASE_STACK (parser->mem, parser->exps); BTOR_RELEASE_STACK (parser->mem, parser->info); BTOR_RELEASE_STACK (parser->mem, parser->inputs); BTOR_RELEASE_STACK (parser->mem, parser->outputs); BTOR_RELEASE_STACK (parser->mem, parser->regs); BTOR_RELEASE_STACK (parser->mem, parser->nexts); BTOR_RELEASE_STACK (parser->mem, parser->op); BTOR_RELEASE_STACK (parser->mem, parser->constant); BTOR_RELEASE_STACK (parser->mem, parser->symbol); BTOR_DELETEN (parser->mem, parser->parsers, SIZE_PARSERS); BTOR_DELETEN (parser->mem, parser->ops, SIZE_PARSERS); btor_freestr (parser->mem, parser->error); BTOR_DELETE (parser->mem, parser); } static void remove_regs_from_vars (BtorBTORParser * parser) { BtorNode ** p, ** q, * e; Info info; int i; return; p = q = parser->inputs.start; for (i = 1; i <= parser->idx; i++) { info = parser->info.start[i]; if (!info.var && !info.array) continue; e = parser->exps.start[i]; assert (*p == e); p++; if (!info.next) *q++ = e; } assert (p == parser->inputs.top); parser->inputs.top = q; } static const char * btor_parse_btor_parser (BtorBTORParser * parser, BtorCharStack * prefix, FILE * file, const char *name, BtorParseResult * res) { BtorOpParser op_parser; int ch, len; BtorNode *e; assert (name); assert (file); if (parser->verbosity > 0) btor_msg_btor ("parsing %s", name); parser->nprefix = 0; parser->prefix = prefix; parser->file = file; parser->name = name; parser->lineno = 1; parser->saved = 0; BTOR_CLR (res); NEXT: assert (!parser->error); ch = btor_nextch_btor (parser); if (isspace (ch)) /* also skip empty lines */ goto NEXT; if (ch == EOF) { DONE: if (res) { remove_regs_from_vars (parser); if (parser->found_arrays) res->logic = BTOR_LOGIC_QF_AUFBV; else res->logic = BTOR_LOGIC_QF_BV; res->status = BTOR_PARSE_SAT_STATUS_UNKNOWN; res->ninputs = BTOR_COUNT_STACK (parser->inputs); res->inputs = parser->inputs.start; res->noutputs = BTOR_COUNT_STACK (parser->outputs); res->outputs = parser->outputs.start; res->nregs = BTOR_COUNT_STACK (parser->regs); res->regs = parser->regs.start; res->nexts = parser->nexts.start; if (parser->verbosity > 0) { btor_msg_btor ("parsed %d inputs", res->ninputs); btor_msg_btor ("parsed %d registers", res->nregs); btor_msg_btor ("parsed %d outputs", res->noutputs); } } return 0; } if (ch == ';') /* skip comments */ { COMMENTS: while ((ch = btor_nextch_btor (parser)) != '\n') if (ch == EOF) goto DONE; goto NEXT; } if (!isdigit (ch)) return btor_perr_btor (parser, "expected ';' or digit"); btor_savech_btor (parser, ch); if (parse_positive_int (parser, &parser->idx)) return parser->error; while (BTOR_COUNT_STACK (parser->exps) <= parser->idx) { Info info; memset (&info, 0, sizeof info); BTOR_PUSH_STACK (parser->mem, parser->info, info); BTOR_PUSH_STACK (parser->mem, parser->exps, 0); } if (parser->exps.start[parser->idx]) return btor_perr_btor (parser, "'%d' defined twice", parser->idx); if (parse_space (parser)) return parser->error; assert (BTOR_EMPTY_STACK (parser->op)); while (!isspace (ch = btor_nextch_btor (parser)) && ch != EOF) BTOR_PUSH_STACK (parser->mem, parser->op, ch); BTOR_PUSH_STACK (parser->mem, parser->op, 0); BTOR_RESET_STACK (parser->op); btor_savech_btor (parser, ch); if (parse_space (parser)) return parser->error; if (parse_positive_int (parser, &len)) return parser->error; if (!(op_parser = find_parser (parser, parser->op.start))) return btor_perr_btor (parser, "invalid operator '%s'", parser->op.start); if (!(e = op_parser (parser, len))) { assert (parser->error); return parser->error; } assert (btor_get_exp_len (parser->btor, e) == len); parser->exps.start[parser->idx] = e; SKIP: ch = btor_nextch_btor (parser); if (ch == ' ' || ch == '\t') goto SKIP; if (ch == ';') goto COMMENTS; /* ... and force new line */ if (ch != '\n') return btor_perr_btor (parser, "expected new line"); goto NEXT; } static BtorParserAPI static_btor_btor_parser_api = { (BtorInitParser) btor_new_btor_parser, (BtorResetParser) btor_delete_btor_parser, (BtorParse) btor_parse_btor_parser, }; const BtorParserAPI * btor_btor_parser_api () { return &static_btor_btor_parser_api; } boolector-1.5.118-6b56be4-121013/btorconst.c0000664000175000017500000007774511761140525016626 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btorconst.h" #include "btorutil.h" #include "btorstack.h" #include "btormem.h" #include #include #include /*------------------------------------------------------------------------*/ static const char *digit2const_table[10] = { "", "1", "10", "11", "100", "101", "110", "111", "1000", "1001", }; /*------------------------------------------------------------------------*/ #define BTOR_NOT_CONST_3VL(a) ((a) == 'x' ? 'x' : (a) ^ 1) #define BTOR_AND_CONST_3VL(a,b) \ (((a) == '0' || (b) == '0') ? \ '0' : (((a) == 'x' || (b) == 'x') ? 'x' : (a) & (b))) #define BTOR_OR_CONST_3VL(a,b) \ (((a) == '1' || (b) == '1') ? \ '1' : (((a) == 'x' || (b) == 'x') ? 'x' : (a) | (b))) #define BTOR_XOR_CONST_3VL(a,b) \ (((a) == 'x' || (b) == 'x') ? 'x' : (a) ^ (b)) /*------------------------------------------------------------------------*/ #ifndef NDEBUG /*------------------------------------------------------------------------*/ static int is_valid_const (const char *c) { const char *p; char ch; assert (c != NULL); for (p = c; (ch = *p); p++) if (ch != '0' && ch != '1') return 0; return 1; } static int is_valid_const_3vl (const char *c) { const char *p; char ch; assert (c != NULL); for (p = c; (ch = *p); p++) if (ch != '0' && ch != '1' && ch != 'x') return 0; return 1; } /*------------------------------------------------------------------------*/ #endif /*------------------------------------------------------------------------*/ static const char * digit2const (char ch) { assert ('0' <= ch); assert (ch <= '9'); return digit2const_table[ch - '0']; } static const char * strip_zeroes (const char *a) { assert (a != NULL); assert (is_valid_const (a)); while (*a == '0') a++; return a; } static void btor_SC_GATE_CO_const (char * CO, char R, char D, char CI) { char D_or_CI, D_and_CI, M; D_or_CI = BTOR_OR_CONST_3VL (D, CI); D_and_CI = BTOR_AND_CONST_3VL (D, CI); M = BTOR_AND_CONST_3VL (D_or_CI, R); *CO = BTOR_OR_CONST_3VL (M, D_and_CI); } static void btor_SC_GATE_S_const (char * S, char R, char D, char CI, char Q) { char D_and_CI, D_or_CI; char T2_or_R, T2_and_R; char T1, T2; D_or_CI = BTOR_OR_CONST_3VL (D, CI); D_and_CI = BTOR_AND_CONST_3VL (D, CI); T1 = BTOR_AND_CONST_3VL (D_or_CI, BTOR_NOT_CONST_3VL (D_and_CI)); T2 = BTOR_AND_CONST_3VL (T1, Q); T2_or_R = BTOR_OR_CONST_3VL (T2, R); T2_and_R = BTOR_AND_CONST_3VL (T2, R); *S = BTOR_AND_CONST_3VL (T2_or_R, BTOR_NOT_CONST_3VL (T2_and_R)); } static void udiv_urem_const (BtorMemMgr * mm, const char * Ain, const char * Din, char **Qptr, char **Rptr) { char *A, *nD, **S, **C; char *Q, *R; int size, i, j; assert (mm != NULL); assert (Ain != NULL); assert (Din != NULL); assert (Qptr != NULL); assert (Rptr != NULL); assert (is_valid_const_3vl (Ain)); assert (is_valid_const_3vl (Din)); assert (strlen (Ain) == strlen (Din)); size = (int) strlen (Ain); assert (size > 0); BTOR_NEWN (mm, A, size); for (i = 0; i < size; i++) A[i] = Ain[size - 1 - i]; BTOR_NEWN (mm, nD, size); for (i = 0; i < size; i++) nD[i] = BTOR_NOT_CONST_3VL(Din[size - 1 - i]); BTOR_NEWN (mm, S, size + 1); for (j = 0; j <= size; j++) { BTOR_NEWN (mm, S[j], size + 1); for (i = 0; i <= size; i++) S[j][i] = '0'; } BTOR_NEWN (mm, C, size + 1); for (j = 0; j <= size; j++) { BTOR_NEWN (mm, C[j], size + 1); for (i = 0; i <= size; i++) C[j][i] = '0'; } BTOR_NEWN (mm, R, size + 1); BTOR_NEWN (mm, Q, size + 1); R[size] = '\0'; Q[size] = '\0'; for (j = 0; j <= size - 1; j++) { S[j][0] = A[size - j - 1]; C[j][0] = '1'; for (i = 0; i <= size - 1; i++) btor_SC_GATE_CO_const (&C[j][i + 1], S[j][i], nD[i], C[j][i]); Q[j] = BTOR_OR_CONST_3VL (C[j][size], S[j][size]); for (i = 0; i <= size - 1; i++) btor_SC_GATE_S_const (&S[j + 1][i + 1], S[j][i], nD[i], C[j][i], Q[j]); } for (i = size; i >= 1; i--) R[size - i] = S[size][i]; for (j = 0; j <= size; j++) BTOR_DELETEN (mm, C[j], size + 1); BTOR_DELETEN (mm, C, size + 1); for (j = 0; j <= size; j++) BTOR_DELETEN (mm, S[j], size + 1); BTOR_DELETEN (mm, S, size + 1); BTOR_DELETEN (mm, nD, size); BTOR_DELETEN (mm, A, size); *Qptr = Q; *Rptr = R; } static char * btor_add_unbounded_const (BtorMemMgr * mm, const char *a, const char *b) { char *res, *r, c, x, y, s, *tmp; int alen, blen, rlen; const char *p, *q; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (is_valid_const (a)); assert (is_valid_const (b)); a = strip_zeroes (a); b = strip_zeroes (b); if (!*a) return btor_strdup (mm, b); if (!*b) return btor_strdup (mm, a); alen = (int) strlen (a); blen = (int) strlen (b); rlen = (alen < blen) ? blen : alen; rlen++; BTOR_NEWN (mm, res, rlen + 1); p = a + alen; q = b + blen; c = '0'; r = res + rlen; *r = 0; while (res < r) { x = (a < p) ? *--p : '0'; y = (b < q) ? *--q : '0'; s = x ^ y ^ c; c = (x & y) | (x & c) | (y & c); *--r = s; } p = strip_zeroes (res); if ((p != res)) { tmp = btor_copy_const (mm, p); btor_delete_const (mm, res); res = tmp; } return res; } static char * btor_mult_unbounded_const (BtorMemMgr * mm, const char *a, const char *b) { char *res, *r, c, x, y, s, m; int alen, blen, rlen, i; const char *p; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (is_valid_const (a)); assert (is_valid_const (b)); a = strip_zeroes (a); if (!*a) return btor_strdup (mm, ""); if (a[0] == '1' && !a[1]) return btor_strdup (mm, b); b = strip_zeroes (b); if (!*b) return btor_strdup (mm, ""); if (b[0] == '1' && !b[1]) return btor_strdup (mm, a); alen = (int) strlen (a); blen = (int) strlen (b); rlen = alen + blen; BTOR_NEWN (mm, res, rlen + 1); res[rlen] = 0; for (r = res; r < res + blen; r++) *r = '0'; for (p = a; p < a + alen; p++) *r++ = *p; assert (r == res + rlen); for (i = 0; i < alen; i++) { m = res[rlen - 1]; c = '0'; if (m == '1') { p = b + blen; r = res + blen; while (res < r && b < p) { assert (b < p); x = *--p; y = *--r; s = x ^ y ^ c; c = (x & y) | (x & c) | (y & c); *r = s; } } memmove (res + 1, res, rlen - 1); res[0] = c; } return res; } static int btor_cmp_const (const char *a, const char *b) { const char *p, *q, *s; int l, k, delta; assert (a != NULL); assert (b != NULL); assert (is_valid_const (a)); assert (is_valid_const (b)); a = strip_zeroes (a); b = strip_zeroes (b); l = (int) strlen (a); k = (int) strlen (b); delta = (l - k); if (delta < 0) { p = a; s = b - delta; for (q = b; q < s; q++) if (*q == '1') return -1; } else { s = a + delta; q = b; for (p = a; p < s; p++) if (*p == '1') return 1; } assert (strlen (p) == strlen (q)); return strcmp (p, q); } static char * btor_udiv_unbounded_const (BtorMemMgr * mem, const char *dividend, const char *divisor, char **rem_ptr) { char *quotient, *rest, *extended_divisor, *tmp; int delta, plen, qlen; const char *p, *q; assert (mem != NULL); assert (dividend != NULL); assert (divisor != NULL); assert (is_valid_const (dividend)); assert (is_valid_const (divisor)); dividend = strip_zeroes (dividend); divisor = strip_zeroes (divisor); for (p = dividend; *p && *p == '0'; p++) ; for (q = divisor; *q && *q == '0'; q++) ; assert (*q); /* in any case even if 'dividend == 0' */ if (!*p || btor_cmp_const (p, q) < 0) { if (rem_ptr) *rem_ptr = btor_strdup (mem, p); /* copy divident */ return btor_strdup (mem, ""); } plen = (int) strlen (p); qlen = (int) strlen (q); delta = plen - qlen; assert (delta >= 0); BTOR_NEWN (mem, extended_divisor, plen + 1); memset (extended_divisor, '0', delta); strcpy (extended_divisor + delta, divisor); udiv_urem_const (mem, dividend, extended_divisor, "ient, &rest); btor_delete_const (mem, extended_divisor); tmp = btor_strdup (mem, strip_zeroes (quotient)); btor_delete_const (mem, quotient); quotient = tmp; tmp = btor_strdup (mem, strip_zeroes (rest)); btor_delete_const (mem, rest); rest = tmp; assert (btor_cmp_const (rest, divisor) < 0); #ifndef NDEBUG { char *tmp1 = btor_mult_unbounded_const (mem, quotient, divisor); char *tmp2 = btor_add_unbounded_const (mem, tmp1, rest); assert (!btor_cmp_const (dividend, tmp2)); btor_freestr (mem, tmp1); btor_freestr (mem, tmp2); } #endif if (rem_ptr) *rem_ptr = rest; else btor_delete_const (mem, rest); return quotient; } #define MSB_INT ((int)(sizeof (int) * 8 - 1)) char * btor_zero_const (BtorMemMgr * mm, int len) { char *res; int i; assert (len > 0); BTOR_NEWN (mm, res, len + 1); for (i = 0; i < len; i++) res[i] = '0'; res[i] = '\0'; return res; } char * btor_one_const (BtorMemMgr * mm, int len) { char *res; int i; assert (mm != NULL); assert (len > 0); BTOR_NEWN (mm, res, len + 1); for (i = 0; i < len - 1; i++) res[i] = '0'; res[i++] = '1'; res[i] = '\0'; return res; } char * btor_ones_const (BtorMemMgr * mm, int len) { char *res; int i; assert (mm != NULL); assert (len > 0); BTOR_NEWN (mm, res, len + 1); for (i = 0; i < len; i++) res[i] = '1'; res[i] = '\0'; return res; } char * btor_int_to_const (BtorMemMgr * mm, int x, int len) { char msb, *result; int i; assert (mm != NULL); assert (len > 0); BTOR_NEWN (mm, result, len + 1); msb = (x & (1 << MSB_INT)) ? '1' : '0'; for (i = len - 1; i >= MSB_INT; i--) result[len - 1 - i] = msb; while (i >= 0) { result[len - 1 - i] = (x & (1 << i)) ? '1' : '0'; i--; } result[len] = '\0'; return result; } #define MSB_UNSIGNED ((int)(sizeof (unsigned) * 8 - 1)) char * btor_unsigned_to_const (BtorMemMgr * mm, unsigned x, int len) { char *result; int i; assert (mm != NULL); assert (len > 0); BTOR_NEWN (mm, result, len + 1); for (i = len - 1; i > MSB_UNSIGNED; i--) result[len - 1 - i] = '0'; while (i >= 0) { result[len - 1 - i] = (x & (1u << i)) ? '1' : '0'; i--; } result[len] = '\0'; return result; } char * btor_decimal_to_const_n (BtorMemMgr * mem, const char *str, int len) { const char *end, *p; char *res, *tmp; assert (mem != NULL); assert (str != NULL); assert (len >= 0); res = btor_strdup (mem, ""); end = str + len; for (p = str; p < end; p++) { tmp = btor_mult_unbounded_const (mem, res, "1010"); /* *10 */ btor_delete_const (mem, res); res = tmp; tmp = btor_add_unbounded_const (mem, res, digit2const (*p)); btor_delete_const (mem, res); res = tmp; } assert (strip_zeroes (res) == res); return res; } char * btor_decimal_to_const (BtorMemMgr * mem, const char *str) { assert (mem != NULL); assert (str != NULL); return btor_decimal_to_const_n (mem, str, (int) strlen (str)); } char * btor_hex_to_const_n (BtorMemMgr * mem, const char *str, int hlen) { const char *p, *end; char *tmp, *res, *q; int len; assert (mem != NULL); assert (str != NULL); assert (hlen >= 0); len = 4 * hlen; BTOR_NEWN (mem, tmp, len + 1); q = tmp; end = str + hlen; for (p = str; p < end; p++) switch (*p) { case '0': *q++ = '0'; *q++ = '0'; *q++ = '0'; *q++ = '0'; break; case '1': *q++ = '0'; *q++ = '0'; *q++ = '0'; *q++ = '1'; break; case '2': *q++ = '0'; *q++ = '0'; *q++ = '1'; *q++ = '0'; break; case '3': *q++ = '0'; *q++ = '0'; *q++ = '1'; *q++ = '1'; break; case '4': *q++ = '0'; *q++ = '1'; *q++ = '0'; *q++ = '0'; break; case '5': *q++ = '0'; *q++ = '1'; *q++ = '0'; *q++ = '1'; break; case '6': *q++ = '0'; *q++ = '1'; *q++ = '1'; *q++ = '0'; break; case '7': *q++ = '0'; *q++ = '1'; *q++ = '1'; *q++ = '1'; break; case '8': *q++ = '1'; *q++ = '0'; *q++ = '0'; *q++ = '0'; break; case '9': *q++ = '1'; *q++ = '0'; *q++ = '0'; *q++ = '1'; break; case 'A': case 'a': *q++ = '1'; *q++ = '0'; *q++ = '1'; *q++ = '0'; break; case 'B': case 'b': *q++ = '1'; *q++ = '0'; *q++ = '1'; *q++ = '1'; break; case 'C': case 'c': *q++ = '1'; *q++ = '1'; *q++ = '0'; *q++ = '0'; break; case 'D': case 'd': *q++ = '1'; *q++ = '1'; *q++ = '0'; *q++ = '1'; break; case 'E': case 'e': *q++ = '1'; *q++ = '1'; *q++ = '1'; *q++ = '0'; break; case 'F': case 'f': default: assert (*p == 'f' || *p == 'F'); *q++ = '1'; *q++ = '1'; *q++ = '1'; *q++ = '1'; break; } assert (tmp + len == q); *q++ = 0; res = btor_strdup (mem, strip_zeroes (tmp)); btor_freestr (mem, tmp); return res; } char * btor_hex_to_const (BtorMemMgr * mem, const char *str) { assert (mem != NULL); assert (str != NULL); return btor_hex_to_const_n (mem, str, (int) strlen (str)); } char * btor_ground_const_3vl (BtorMemMgr * mm, const char *c) { char *res, *q; const char *p; char ch; assert (mm != NULL); assert (c != NULL); assert ((int) strlen (c) > 0); assert (is_valid_const_3vl (c)); BTOR_NEWN (mm, res, (int) strlen (c) + 1); q = res; for (p = c; (ch = *p); p++) *q++ = (ch == '1') ? '1' : '0'; /* 'x' -> '0' */ *q = 0; return res; } int btor_is_zero_const (const char *str) { const char *p; assert (str != NULL); assert ((int) strlen (str) > 0); assert (is_valid_const (str)); for (p = str; *p; p++) if (*p != '0') return 0; return 1; } int btor_is_one_const (const char *str) { int len, i; assert (str != NULL); assert ((int) strlen (str) > 0); assert (is_valid_const (str)); len = (int) strlen (str); if (str[len - 1] != '1') return 0; for (i = 0; i < len - 1; i++) if (str[i] != '0') return 0; return 1; } int btor_is_ones_const (const char *str) { const char *p; assert (str != NULL); assert ((int) strlen (str) > 0); assert (is_valid_const (str)); for (p = str; *p; p++) if (*p != '1') return 0; return 1; } BtorSpecialConst btor_is_special_const (const char *str) { char c; const char *p; assert (str != NULL); assert ((int) strlen (str) > 0); assert (is_valid_const (str)); c = *str; p = str + 1; while (*p) { if (*p != c) { p++; if (c == '0' && !*p) return BTOR_SPECIAL_CONST_ONE; else return BTOR_SPECIAL_CONST_NONE; } else p++; } if (c == '0') return BTOR_SPECIAL_CONST_ZERO; assert (c == '1'); /* bit-width == 1 ? */ if (p == str + 1) { assert ((int) strlen (str) == 1); return BTOR_SPECIAL_CONST_ONE_ONES; } return BTOR_SPECIAL_CONST_ONES; } char * btor_copy_const (BtorMemMgr * mm, const char *c) { assert (mm != NULL); assert (c != NULL); assert (is_valid_const_3vl (c)); return btor_strdup (mm, c); } void btor_delete_const (BtorMemMgr * mm, char *c) { assert (mm != NULL); assert (c != NULL); assert (is_valid_const_3vl (c)); btor_freestr (mm, c); } int btor_get_num_leading_zeros_const (BtorMemMgr * mm, const char * c) { const char *p; int result; assert (mm != NULL); assert (c != NULL); assert (*c != '\0'); assert (is_valid_const_3vl (c)); (void) mm; result = 0; for (p = c; *p == '0'; p++) result++; return result; } int btor_get_num_leading_ones_const (BtorMemMgr * mm, const char * c) { const char *p; int result; assert (mm != NULL); assert (c != NULL); assert (*c != '\0'); assert (is_valid_const_3vl (c)); (void) mm; result = 0; for (p = c; *p == '1'; p++) result++; return result; } static char * slice_const (BtorMemMgr * mm, const char *a, int upper, int lower) { const char *p, *eoa; char *res, *q; int len, delta; assert (mm != NULL); assert (a != NULL); assert (upper < (int) strlen (a)); assert (upper >= lower); assert (lower >= 0); assert (is_valid_const_3vl (a)); len = (int) strlen (a); delta = upper - lower + 1; BTOR_NEWN (mm, res, delta + 1); p = a + len - 1 - upper; q = res; eoa = a + len - 1 - lower; while (p <= eoa) *q++ = *p++; *q = 0; assert ((int) strlen (res) == delta); return res; } char * btor_slice_const (BtorMemMgr * mm, const char *a, int upper, int lower) { assert (mm != NULL); assert (a != NULL); assert (upper < (int) strlen (a)); assert (upper >= lower); assert (lower >= 0); assert (is_valid_const (a)); return slice_const (mm, a, upper, lower); } static void invert_const (BtorMemMgr * mm, char *a) { int len, i; assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); (void) mm; len = (int) strlen (a); for (i = 0; i < len; i++) if (a[i] != 'x') a[i] = (char) (1 ^ a[i]); } void btor_invert_const (BtorMemMgr * mm, char *a) { assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); invert_const (mm, a); } static char * not_const (BtorMemMgr * mm, const char *a) { char *result; int len, i; assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); len = (int) strlen (a); BTOR_NEWN (mm, result, len + 1); for (i = 0; i < len; i++) result[i] = BTOR_NOT_CONST_3VL (a[i]); result[len] = '\0'; return result; } char * btor_not_const (BtorMemMgr * mm, const char *a) { assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); return not_const (mm, a); } static char * and_const (BtorMemMgr * mm, const char *a, const char *b) { char *result; int len, i; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); len = (int) strlen (a); BTOR_NEWN (mm, result, len + 1); for (i = len - 1; i >= 0; i--) result[i] = BTOR_AND_CONST_3VL (a[i], b[i]); result[len] = '\0'; return result; } char * btor_and_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); return and_const (mm, a, b); } static char * eq_const (BtorMemMgr * mm, const char *a, const char *b) { char *result; int len, i, has_x; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); len = (int) strlen (a); BTOR_NEWN (mm, result, 2); result[0] = '1'; has_x = 0; for (i = len - 1; i >= 0; i--) { if (a[i] == 'x' || b[i] == 'x') has_x = 1; else if (a[i] != b[i]) { result[0] = '0'; break; } } result[1] = '\0'; if (result[0] == '1' && has_x) result[0] = 'x'; return result; } char * btor_eq_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); return eq_const (mm, a, b); } static char * add_const (BtorMemMgr * mm, const char *a, const char *b) { char carry, p0, p1, p2, *result; int len, i; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); carry = '0'; len = (int) strlen (a); BTOR_NEWN (mm, result, len + 1); for (i = len - 1; i >= 0; i--) { result[i] = BTOR_XOR_CONST_3VL (BTOR_XOR_CONST_3VL (a[i], b[i]), carry); p0 = BTOR_AND_CONST_3VL (a[i], b[i]); p1 = BTOR_AND_CONST_3VL (a[i], carry); p2 = BTOR_AND_CONST_3VL (b[i], carry); carry = BTOR_OR_CONST_3VL (BTOR_OR_CONST_3VL (p0, p1), p2); } result[len] = '\0'; return result; } char * btor_add_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); return add_const (mm, a, b); } char * btor_neg_const (BtorMemMgr * mm, const char *a) { char *result, *not_a, *one; int len; assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); len = (int) strlen (a); not_a = btor_not_const (mm, a); one = btor_int_to_const (mm, 1, len); result = btor_add_const (mm, not_a, one); btor_delete_const (mm, not_a); btor_delete_const (mm, one); return result; } char * btor_sub_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *neg_b; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); neg_b = btor_neg_const (mm, b); result = btor_add_const (mm, a, neg_b); btor_delete_const (mm, neg_b); return result; } static char * btor_sll_n_bits_const (BtorMemMgr * mm, const char *a, int n) { char *result; int len, i; assert (mm != NULL); assert (a != NULL); assert (is_valid_const_3vl (a)); assert (n >= 0); assert (n < (int) strlen (a)); len = (int) strlen (a); if (len == 0) return btor_strdup (mm, a); BTOR_NEWN (mm, result, len + 1); for (i = 0; i < len - n; i++) result[i] = a[i + n]; for (i = len - n; i < len; i++) result[i] = '0'; result[len] = '\0'; return result; } static char * mul_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *and, *add, *shift; int i, j, len; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); len = (int) strlen (a); result = btor_int_to_const (mm, 0, len); for (i = len - 1; i >= 0; i--) { BTOR_NEWN (mm, and, len + 1); for (j = 0; j < len; j++) and[j] = BTOR_AND_CONST_3VL (a[j], b[i]); and[len] = '\0'; shift = btor_sll_n_bits_const (mm, and, len - 1 - i); add = add_const (mm, result, shift); btor_delete_const (mm, result); btor_delete_const (mm, and); btor_delete_const (mm, shift); result = add; } return result; } char * btor_mul_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); return mul_const (mm, a, b); } static char * btor_srl_n_bits_const (BtorMemMgr * mm, const char *a, int n) { char *result; int len, i; assert (mm != NULL); assert (a != NULL); assert (is_valid_const_3vl (a)); assert (n >= 0); assert (n < (int) strlen (a)); len = (int) strlen (a); if (len == 0) return btor_strdup (mm, a); BTOR_NEWN (mm, result, len + 1); for (i = 0; i < n; i++) result[i] = '0'; for (i = n; i < len; i++) result[i] = a[i - n]; result[len] = '\0'; return result; } char * btor_udiv_const (BtorMemMgr * mm, const char *a, const char *b) { char *quotient, *remainder; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); udiv_urem_const (mm, a, b, "ient, &remainder); btor_delete_const (mm, remainder); return quotient; } char * btor_urem_const (BtorMemMgr * mm, const char *a, const char *b) { char *quotient, *remainder; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); udiv_urem_const (mm, a, b, "ient, &remainder); btor_delete_const (mm, quotient); return remainder; } static char * sll_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *temp; int i, len; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 1); assert (btor_is_power_of_2_util ((int) strlen (a))); assert (btor_log_2_util ((int) strlen (a)) == (int) strlen (b)); assert (is_valid_const_3vl (a)); assert (is_valid_const (b)); len = (int) strlen (b); if (b[len - 1] == '1') result = btor_sll_n_bits_const (mm, a, 1); else result = btor_copy_const (mm, a); for (i = len - 2; i >= 0; i--) { temp = result; if (b[i] == '1') result = btor_sll_n_bits_const (mm, temp, btor_pow_2_util (len - i - 1)); else result = btor_copy_const (mm, temp); btor_delete_const (mm, temp); } return result; } char * btor_sll_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 1); assert (btor_is_power_of_2_util ((int) strlen (a))); assert (btor_log_2_util ((int) strlen (a)) == (int) strlen (b)); assert (is_valid_const (a)); assert (is_valid_const (b)); return sll_const (mm, a, b); } static char * srl_const (BtorMemMgr * mm, const char *a, const char *b) { char *result, *temp; int i, len; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 1); assert (btor_is_power_of_2_util ((int) strlen (a))); assert (btor_log_2_util ((int) strlen (a)) == (int) strlen (b)); assert (is_valid_const_3vl (a)); assert (is_valid_const (b)); len = (int) strlen (b); if (b[len - 1] == '1') result = btor_srl_n_bits_const (mm, a, 1); else result = btor_copy_const (mm, a); for (i = len - 2; i >= 0; i--) { temp = result; if (b[i] == '1') result = btor_srl_n_bits_const (mm, temp, btor_pow_2_util (len - i - 1)); else result = btor_copy_const (mm, temp); btor_delete_const (mm, temp); } return result; } char * btor_srl_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 1); assert (btor_is_power_of_2_util ((int) strlen (a))); assert (btor_log_2_util ((int) strlen (a)) == (int) strlen (b)); assert (is_valid_const (a)); assert (is_valid_const (b)); return srl_const (mm, a, b); } char * btor_ult_const (BtorMemMgr * mm, const char *a, const char *b) { char *result; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert (strlen (a) == strlen (b)); assert ((int) strlen (a) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); BTOR_NEWN (mm, result, 2); if (strcmp (a, b) == -1) result[0] = '1'; else result[0] = '0'; result[1] = '\0'; return result; } static char * concat_const (BtorMemMgr * mm, const char *a, const char *b) { char *result; assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 0); assert ((int) strlen (b) > 0); assert (is_valid_const_3vl (a)); assert (is_valid_const_3vl (b)); BTOR_NEWN (mm, result, (int) strlen (a) + (int) strlen (b) + 1); strcpy (result, a); strcat (result, b); return result; } char * btor_concat_const (BtorMemMgr * mm, const char *a, const char *b) { assert (mm != NULL); assert (a != NULL); assert (b != NULL); assert ((int) strlen (a) > 0); assert ((int) strlen (b) > 0); assert (is_valid_const (a)); assert (is_valid_const (b)); return concat_const (mm, a, b); } char * btor_uext_const (BtorMemMgr * mm, const char *c, int len) { char *res, *q; const char *p; int rlen; assert (mm != NULL); assert (c != NULL); assert (len > 0); assert (is_valid_const (c)); rlen = (int) strlen (c) + len; BTOR_NEWN (mm, res, rlen + 1); for (q = res; len; len--, q++) *q = '0'; for (p = c; *p; p++, q++) *q = *p; assert (res + rlen == q); *q = 0; return res; } char * btor_inverse_const (BtorMemMgr * mm, const char *c) { char *a, *b, *y, *ly, *r, *q, *yq, *res, *ty; int len = strlen (c); assert (mm != NULL); assert (c != NULL); assert (len > 0); assert (c[len - 1] == '1'); /* odd */ assert (is_valid_const (c)); BTOR_NEWN (mm, a, len + 2); a[0] = '1'; memset (a + 1, '0', len); a[len + 1] = 0; BTOR_NEWN (mm, b, len + 2); b[0] = '0'; memcpy (b + 1, c, len); b[len + 1] = 0; y = btor_unsigned_to_const (mm, 1, len + 1); ly = btor_unsigned_to_const (mm, 0, len + 1); while (!btor_is_zero_const (b)) { udiv_urem_const (mm, a, b, &q, &r); btor_delete_const (mm, a); a = b; b = r; ty = y; yq = btor_mul_const (mm, y, q); btor_delete_const (mm, q); y = btor_sub_const (mm, ly, yq); btor_delete_const (mm, yq); btor_delete_const (mm, ly); ly = ty; } res = btor_slice_const (mm, ly, len - 1, 0); #ifndef NDEBUG assert (strlen (res) == strlen (c)); ty = btor_mul_const (mm, c, res); assert (btor_is_one_const (ty)); btor_delete_const (mm, ty); #endif btor_delete_const (mm, ly); btor_delete_const (mm, y); btor_delete_const (mm, b); btor_delete_const (mm, a); return res; } char * btor_const_to_hex (BtorMemMgr * mem, const char *c) { int clen, rlen, i, j, tmp; char *res, ch; assert (mem != NULL); assert (c != NULL); assert (is_valid_const (c)); clen = (int) strlen (c); rlen = (clen + 3) / 4; if (rlen) { BTOR_NEWN (mem, res, rlen + 1); i = clen - 1; j = rlen; res[j--] = 0; while (i >= 0) { tmp = (c[i--] == '1'); if (i >= 0) { tmp |= (c[i--] == '1') << 1; if (i >= 0) { tmp |= (c[i--] == '1') << 2; if (i >= 0) tmp |= (c[i--] == '1') << 3; } } if (tmp < 10) ch = '0' + tmp; else ch = 'a' + (tmp - 10); res[j--] = ch; } } else res = btor_strdup (mem, "0"); return res; } char * btor_const_to_decimal (BtorMemMgr * mem, const char *c) { char *res, *q, *tmp, *rem, ch; BtorCharStack stack; const char *p; int len; BTOR_INIT_STACK (stack); assert (mem != NULL); assert (c != NULL); assert (is_valid_const (c)); res = btor_copy_const (mem, c); while (*res) { tmp = btor_udiv_unbounded_const (mem, res, "1010", &rem); /* / 10 */ assert ((int) strlen (rem) <= 4); ch = 0; for (p = strip_zeroes (rem); *p; p++) { ch <<= 1; if (*p == '1') ch++; } assert (ch < 10); ch += '0'; BTOR_PUSH_STACK (mem, stack, ch); btor_delete_const (mem, rem); btor_delete_const (mem, res); res = tmp; } btor_delete_const (mem, res); if (BTOR_EMPTY_STACK (stack)) BTOR_PUSH_STACK (mem, stack, '0'); len = BTOR_COUNT_STACK (stack); BTOR_NEWN (mem, res, len + 1); q = res; p = stack.top; while (p > stack.start) *q++ = *--p; assert (res + len == q); *q = 0; assert (len == (int) strlen (res)); BTOR_RELEASE_STACK (mem, stack); return res; } char * btor_x_const_3vl (BtorMemMgr * mm, int len) { char *res; int i; assert (mm != NULL); assert (len > 0); BTOR_NEWN (mm, res, len + 1); for (i = 0; i < len; i++) res[i] = 'x'; res[i] = '\0'; return res; } char * btor_not_const_3vl (BtorMemMgr * mm, const char *a) { assert (mm != NULL); assert (a != NULL); assert ((int) strlen (a) > 0); assert (is_valid_const_3vl (a)); return not_const (mm, a); } int btor_is_const_2vl (BtorMemMgr * mm, const char *c) { assert (mm != NULL); assert (c != NULL); (void) mm; return strchr (c, 'x') == NULL; } boolector-1.5.118-6b56be4-121013/boolectormain.c0000664000175000017500000000057611761140525017432 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btormain.h" int main (int argc, char **argv) { return boolector_main (argc, argv); } boolector-1.5.118-6b56be4-121013/btormain.h0000664000175000017500000000061111761140525016403 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTORMAIN_H_INCLUDED #define BTORMAIN_H_INCLUDED int boolector_main (int argc, char **argv); #endif boolector-1.5.118-6b56be4-121013/btorutil.h0000664000175000017500000000155211761140525016441 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTORUTIL_H_INCLUDED #define BTORUTIL_H_INCLUDED #define BTOR_HAVE_GETRUSAGE // TODO make this a configuration option #define BTOR_MAX_UTIL(x,y) ((x) > (y) ? (x) : (y)) #define BTOR_MIN_UTIL(x,y) ((x) < (y) ? (x) : (y)) #define BTOR_AVERAGE_UTIL(a,b) ((b) ? ((double)(a))/((double)(b)) : 0.0) int btor_is_power_of_2_util (int x); int btor_log_2_util (int x); int btor_pow_2_util (int x); int btor_next_power_of_2_util (int x); int btor_num_digits_util (int x); #ifdef BTOR_HAVE_GETRUSAGE double btor_time_stamp (void); #endif int btor_file_exists (const char *); #endif boolector-1.5.118-6b56be4-121013/btoraigvec.h0000664000175000017500000001241511761140525016722 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTORAIGVEC_H_INCLUDED #define BTORAIGVEC_H_INCLUDED #include "btormem.h" #include "btoraig.h" /*------------------------------------------------------------------------*/ struct BtorAIGVec { BtorAIG **aigs; /* vector of AIGs */ int len; /* length of the AIG vector */ }; typedef struct BtorAIGVec BtorAIGVec; typedef struct BtorAIGVecMgr BtorAIGVecMgr; /*------------------------------------------------------------------------*/ /* Creates new AIG vector manager. An AIG vector manager is used by nearly * all functions of the AIG vector layer. */ BtorAIGVecMgr *btor_new_aigvec_mgr (BtorMemMgr * mm); /* Sets verbosity [-1,3] */ void btor_set_verbosity_aigvec_mgr (BtorAIGVecMgr * avmgr, int verbosity); /* Returns AIG manager of the AIG vector manager. */ BtorAIGMgr *btor_get_aig_mgr_aigvec_mgr (const BtorAIGVecMgr * avmgr); /* Deletes AIG vector manager from memory. */ void btor_delete_aigvec_mgr (BtorAIGVecMgr * avmgr); /* Implicit precondition of all functions taking AIG vectors as inputs: * The length of all input AIG vectors have to be greater than zero. */ /* Creates new AIG vector representing a constant specified by bits. * len(result) = strlen(bits) */ BtorAIGVec *btor_const_aigvec (BtorAIGVecMgr * avmgr, const char *bits); /* Creates new AIG vector representing a variable. * len > 0 * len(result) = len */ BtorAIGVec *btor_var_aigvec (BtorAIGVecMgr * avmgr, int len); /* Inverts all AIGs of the AIG vector */ void btor_invert_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av); /* Creates new AIG vector representing ones's complement of av. * len(result) = len(av) */ BtorAIGVec *btor_not_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av); /* Creates new AIG vector representing a slice of av. * upper < len(av) * lower >= 0 * upper >= lower * len(result) = upper - lower + 1 */ BtorAIGVec *btor_slice_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av, int upper, int lower); /* Creates new AIG vector representing av1 AND av2. * len(av1) = len(av2) * len(result) = len(av1) = len(av2) */ BtorAIGVec *btor_and_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 less than av2 (unsigned). * len(av1) = len(av2) * len(result) = 1 */ BtorAIGVec *btor_ult_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 equal av2. * len(av1) = len(av2) * len(result) = 1 */ BtorAIGVec *btor_eq_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 + av2. * len(av1) = len(av2) * len(result) = len(av1) = len(av2) */ BtorAIGVec *btor_add_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 shift left logical by av2. * is_power_of_2(len(av1)) * len(av2) = log2(len(av1)) * len(result) = len(av1) */ BtorAIGVec *btor_sll_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 shift right logical by av2. * is_power_of_2(len(av1)) * len(av2) = log2(len(av1)) * len(result) = len(av1) */ BtorAIGVec *btor_srl_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 * av2. * len(av1) = len(av2) * len(result) = len(av1) = len(av2) */ BtorAIGVec *btor_mul_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 / av2 (unsigned). * len(av1) = len(av2) * len(result) = len(av1) = len(av2) */ BtorAIGVec *btor_udiv_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av1 % av2 (unsigned). * len(av1) = len(av2) * len(result) = len(av1) = len(av2) */ BtorAIGVec *btor_urem_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing the concatenation av1.av2. * len(result) = len(av1) + len(av2) */ BtorAIGVec *btor_concat_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2); /* Creates new AIG vector representing av_cond ? av_if : av_else. * len(av_cond) = 1 * len(av_if) = len(av_else) * len(result) = len(av_if) = len(av_else) */ BtorAIGVec *btor_cond_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av_cond, BtorAIGVec * av_if, BtorAIGVec * av_else); /* Creates new AIG vector representing a copy of av. * len(result) = len(av) */ BtorAIGVec *btor_copy_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av); /* Translates every AIG of the AIG vector into SAT in both phases */ void btor_aigvec_to_sat_tseitin (BtorAIGVecMgr * avmgr, BtorAIGVec * av); /* Release all AIGs of the AIG vector and delete AIG vector from memory. */ void btor_release_delete_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av); /* Builds current assignment string of AIG vector (in the SAT case) * and returns it. */ char *btor_assignment_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av); #endif boolector-1.5.118-6b56be4-121013/README0000664000175000017500000000550312036253615015305 0ustar bierebiereBoolector 1.5.118 Sat Oct 13 13:59:09 CEST 2012 Source code release of Boolector. Boolector is an efficient SMT solver for the quantifier-free theory of bit-vectors in combination with the quantifier-free extensional theory of arrays. For compilation please obtain the latest source code of Lingeling from http://fmv.jku.at/lingeling Then extract from the archive the Lingeling sources in the same directory in which you extracted the Boolector sources. Rename or link the Lingeling source directory to 'lingeling'. Then compile Lingeling. For version al6 of Lingeling this works as follows: cd wget http://fmv.jku.at/lingeling/lingeling-al6-080d45d-120922.tar.gz tar xf lingeling-al6-080d45d-120922.tar.gz ln -s lingeling-al6-080d45d-120922 lingeling cd lingeling ./configure make In the same way you can optionally include version 953 of PicoSAT: cd wget http://fmv.jku.at/picosat/picosat-953.tar.gz tar xf picosat-953.tar.gz ln -s picosat-953 picosat cd picosat ./configure -O # this will improve performance make For additionally using MiniSAT as back-end do the following: cd git clone https://github.com/niklasso/minisat.git cd minisat make You need Lingeling, while PicoSAT and MiniSAT are optional. Then issue ./configure make or ./configure -precosat make Using MiniSAT will force 'libboolector.a' to depend not only on 'libz.so' but also on 'libstdc++.so'. Thus if you want to link 'libboolector.a' with MiniSAT backend against your own programs, then you need to use '-lz -lstdc++' as linking options. This will produce the library 'libboolector.a' with its API 'boolector.h', the stand-alone SMT solver 'boolector', a simple delta debugger 'deltabtor', and a small tool 'synthebtor', which can be used to synthesize AIGs in Aiger format from BV. In the 'examples' sub-directory you find two examples for using the API, which are also described in the API documentation. You can generate the documentation on the API with 'doxygen'. Run doxygen in the top level source directory. Then point your browser at doc/html/index.html You may find more information on Booleactor at the website http://fmv.jku.at/boolector See the COPYING file for license and copying information. In particular, this version of Boolector uses GPL. In essence you can not distribute a program that uses this version of Boolector unless you make your program available under GPL as well. If you need another license in order to use Boolector as part of a program which is not going to be distributed under GPL, please contact Armin Biere . Robert Daniel Brummayer, Armin Biere, Johannes Kepler University. Linz, Austria, 2010. boolector-1.5.118-6b56be4-121013/btorsmt2.c0000664000175000017500000023452712024635403016353 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2011-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btorsmt2.h" #include "btormem.h" #include "btorexp.h" #include "btorutil.h" #include "btorconst.h" #include #include #include /*------------------------------------------------------------------------*/ typedef enum BtorSMT2TagClass { BTOR_CLASS_BITS_SMT2 = 6, BTOR_CLASS_SIZE_SMT2 = (1 << BTOR_CLASS_BITS_SMT2), BTOR_CLASS_MASK_SMT2 = (BTOR_CLASS_SIZE_SMT2 - 1), BTOR_OTHER_TAG_CLASS_SMT2 = 0, BTOR_CONSTANT_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 0), BTOR_RESERVED_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 1), BTOR_COMMAND_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 2), BTOR_KEYWORD_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 3), BTOR_CORE_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 4), BTOR_ARRAY_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 5), BTOR_BITVEC_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 6), BTOR_LOGIC_TAG_CLASS_SMT2 = (BTOR_CLASS_SIZE_SMT2 << 7), } BtorSMT2TagClass; typedef enum BtorSMT2Tag { BTOR_INVALID_TAG_SMT2 = 0 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_PARENT_TAG_SMT2 = 1 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_LPAR_TAG_SMT2 = 2 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_RPAR_TAG_SMT2 = 3 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_SYMBOL_TAG_SMT2 = 4 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_ATTRIBUTE_TAG_SMT2 = 5 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_EXP_TAG_SMT2 = 6 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_LETBIND_TAG_SMT2 = 7 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_PARLETBINDING_TAG_SMT2 = 8 + BTOR_OTHER_TAG_CLASS_SMT2, BTOR_DECIMAL_CONSTANT_TAG_SMT2 = 0 + BTOR_CONSTANT_TAG_CLASS_SMT2, BTOR_HEXADECIMAL_CONSTANT_TAG_SMT2 = 1 + BTOR_CONSTANT_TAG_CLASS_SMT2, BTOR_BINARY_CONSTANT_TAG_SMT2 = 2 + BTOR_CONSTANT_TAG_CLASS_SMT2, BTOR_STRING_CONSTANT_TAG_SMT2 = 3 + BTOR_CONSTANT_TAG_CLASS_SMT2, BTOR_PAR_TAG_SMT2 = 0 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_NUMERAL_RESERVED_WORD_TAG_SMT2 = 1 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_DECIMAL_RESERVED_WORD_TAG_SMT2 = 2 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_STRING_RESERVED_WORD_TAG_SMT2 = 3 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_UNDERSCORE_TAG_SMT2 = 4 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_BANG_TAG_SMT2 = 5 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_AS_TAG_SMT2 = 6 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_LET_TAG_SMT2 = 7 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_FORALL_TAG_SMT2 = 8 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_EXISTS_TAG_SMT2 = 9 + BTOR_RESERVED_TAG_CLASS_SMT2, BTOR_SET_LOGIC_TAG_SMT2 = 0 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_SET_OPTION_TAG_SMT2 = 1 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_SET_INFO_TAG_SMT2 = 2 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_DECLARE_SORT_TAG_SMT2 = 3 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_DEFINE_SORT_TAG_SMT2 = 4 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_DECLARE_FUN_TAG_SMT2 = 5 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_DEFINE_FUN_TAG_SMT2 = 6 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_PUSH_TAG_SMT2 = 7 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_POP_TAG_SMT2 = 8 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_ASSERT_TAG_SMT2 = 9 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_CHECK_SAT_TAG_SMT2 = 10 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_ASSERTIONS_TAG_SMT2 = 11 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_PROOF_TAG_SMT2 = 12 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_UNSAT_CORE_TAG_SMT2 = 13 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_VALUE_TAG_SMT2 = 14 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_ASSIGNMENT_TAG_SMT2 = 15 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_OPTION_TAG_SMT2 = 16 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_GET_INFO_TAG_SMT2 = 17 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_EXIT_TAG_SMT2 = 18 + BTOR_COMMAND_TAG_CLASS_SMT2, BTOR_ALL_STATISTICS_TAG_SMT2 = 0 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_AUTHORS_TAG_SMT2 = 1 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_AXIOMS_TAG_SMT2 = 2 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_CHAINABLE_TAG_SMT2 = 3 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_DEFINITION_TAG_SMT2 = 4 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_DIAG_OUTPUT_CHANNEL_TAG_SMT2 = 5 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_ERROR_BEHAVIOR_TAG_SMT2 = 6 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_EXPAND_DEFINITIONS_TAG_SMT2 = 7 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_EXTENSIONS_TAG_SMT2 = 8 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_FUNS_TAG_SMT2 = 9 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_FUNS_DESCRIPTION_TAG_SMT2 = 10 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_INTERACTIVE_MODE_TAG_SMT2 = 11 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_LANGUAGE_TAG_SMT2 = 12 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_LEFT_ASSOC_TAG_SMT2 = 13 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_NAME_TAG_SMT2 = 14 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_NAMED_TAG_SMT2 = 15 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_NOTES_TAG_SMT2 = 16 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_PRINT_SUCCESS_TAG_SMT2 = 17 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_PRODUCE_ASSIGNMENTS_TAG_SMT2 = 18 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_PRODUCE_MODELS_TAG_SMT2 = 19 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_PRODUCE_PROOFS_TAG_SMT2 = 20 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_PRODUCE_UNSAT_CORES_TAG_SMT2 = 21 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_RANDOM_SEED_TAG_SMT2 = 22 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_REASON_UNKNOWN_TAG_SMT2 = 23 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_REGULAR_OUTPUT_CHANNEL_TAG_SMT2 = 24 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_RIGHT_ASSOC_TAG_SMT2 = 25 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_SORTS_TAG_SMT2 = 26 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_SORTS_DESCRIPTION_TAG_SMT2 = 27 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_STATUS_TAG_SMT2 = 28 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_THEORIES_TAG_SMT2 = 29 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_VALUES_TAG_SMT2 = 30 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_VERBOSITY_TAG_SMT2 = 31 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_VERSION_TAG_SMT2 = 32 + BTOR_KEYWORD_TAG_CLASS_SMT2, BTOR_BOOL_TAG_SMT2 = 0 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_TRUE_TAG_SMT2 = 1 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_FALSE_TAG_SMT2 = 2 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_NOT_TAG_SMT2 = 3 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_IMPLIES_TAG_SMT2 = 4 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_AND_TAG_SMT2 = 5 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_OR_TAG_SMT2 = 6 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_XOR_TAG_SMT2 = 7 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_EQUAL_TAG_SMT2 = 8 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_DISTINCT_TAG_SMT2 = 9 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_ITE_TAG_SMT2 = 10 + BTOR_CORE_TAG_CLASS_SMT2, BTOR_ARRAY_TAG_SMT2 = 0 + BTOR_ARRAY_TAG_CLASS_SMT2, BTOR_SELECT_TAG_SMT2 = 1 + BTOR_ARRAY_TAG_CLASS_SMT2, BTOR_STORE_TAG_SMT2 = 2 + BTOR_ARRAY_TAG_CLASS_SMT2, BTOR_BITVEC_TAG_SMT2 = 0 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_CONCAT_TAG_SMT2 = 1 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_EXTRACT_TAG_SMT2 = 2 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVNOT_TAG_SMT2 = 3 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVNEG_TAG_SMT2 = 4 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVAND_TAG_SMT2 = 5 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVOR_TAG_SMT2 = 6 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVADD_TAG_SMT2 = 7 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVMUL_TAG_SMT2 = 8 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVUDIV_TAG_SMT2 = 9 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVUREM_TAG_SMT2 = 10 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSHL_TAG_SMT2 = 11 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVLSHR_TAG_SMT2 = 12 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVULT_TAG_SMT2 = 13 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVNAND_TAG_SMT2 = 14 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVNOR_TAG_SMT2 = 15 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVXOR_TAG_SMT2 = 16 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVXNOR_TAG_SMT2 = 17 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVCOMP_TAG_SMT2 = 18 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSUB_TAG_SMT2 = 19 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSDIV_TAG_SMT2 = 20 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSREM_TAG_SMT2 = 21 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSMOD_TAG_SMT2 = 22 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVASHR_TAG_SMT2 = 23 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_REPEAT_TAG_SMT2 = 24 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_ZERO_EXTEND_TAG_SMT2 = 25 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_SIGN_EXTEND_TAG_SMT2 = 26 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_ROTATE_LEFT_TAG_SMT2 = 27 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_ROTATE_RIGHT_TAG_SMT2 = 28 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVULE_TAG_SMT2 = 29 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVUGT_TAG_SMT2 = 30 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVUGE_TAG_SMT2 = 31 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSLT_TAG_SMT2 = 32 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSLE_TAG_SMT2 = 33 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSGT_TAG_SMT2 = 34 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_BVSGE_TAG_SMT2 = 35 + BTOR_BITVEC_TAG_CLASS_SMT2, BTOR_QF_BV_TAG_SMT2 = 0 + BTOR_LOGIC_TAG_CLASS_SMT2, BTOR_QF_ABV_TAG_SMT2 = 1 + BTOR_LOGIC_TAG_CLASS_SMT2, BTOR_QF_UFBV_TAG_SMT2 = 2 + BTOR_LOGIC_TAG_CLASS_SMT2, BTOR_QF_AUFBV_TAG_SMT2 = 3 + BTOR_LOGIC_TAG_CLASS_SMT2, } BtorSMT2Tag; typedef struct BtorSMT2Node { BtorSMT2Tag tag; unsigned bound:1; int lineno; char * name; BtorNode * exp; struct BtorSMT2Node * next; } BtorSMT2Node; typedef struct BtorSMT2Item { BtorSMT2Tag tag; int lineno; union { int num; struct { int hi, lo; }; }; union { BtorSMT2Node * node; BtorNode * exp; char * str; }; } BtorSMT2Item; BTOR_DECLARE_STACK(SMT2Item,BtorSMT2Item); /*------------------------------------------------------------------------*/ static const char * btor_printable_ascii_chars_smt2 = "!\"#$%&'()*+,-./" "0123456789" ":;<=>?@" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "[\\]^_`" "abcdefghijklmnopqrstuvwxyz" "{|}~" " \t\r\n" ; static const char * btor_letters_smt2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" ; static const char * btor_decimal_digits_smt2 = "0123456789"; static const char * btor_hexadecimal_digits_smt2 = "0123456789abcdefABCDEF"; static const char * btor_extra_symbol_chars_smt2 = "+-/*=%?!.$_~&^<>@"; static const char * btor_extra_keyword_chars_smt2 = "+-/*=%?!.$_~&^<>@"; typedef enum BtorSMT2CharClass { BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2 = (1<<0), BTOR_HEXADECIMAL_DIGIT_CHAR_CLASS_SMT2 = (1<<1), BTOR_STRING_CHAR_CLASS_SMT2 = (1<<2), BTOR_SYMBOL_CHAR_CLASS_SMT2 = (1<<3), BTOR_QUOTED_SYMBOL_CHAR_CLASS_SMT2 = (1<<4), BTOR_KEYWORD_CHAR_CLASS_SMT2 = (1<<5), } BtorSMT2CharClass; typedef struct BtorSMT2Parser { Btor * btor; BtorMemMgr * mem; int verbosity, incremental, model, need_arrays; char * name; int lineno, perrlineno; FILE * file; int saved; char savedch; BtorSMT2Node * last_node; int nprefix; BtorCharStack * prefix; char * error; struct { unsigned size, count; BtorSMT2Node ** table; } symbol; unsigned char cc[256]; BtorNodePtrStack outputs, inputs; BtorCharStack token; BtorSMT2ItemStack work; BtorParseResult * res; struct { int all, set_logic, asserts, check_sat, exits; } commands; int binding; } BtorSMT2Parser; static char * btor_perr_smt2 (BtorSMT2Parser * parser, const char * fmt, ...) { size_t bytes; va_list ap; if (!parser->error) { va_start (ap, fmt); bytes = btor_parse_error_message_length (parser->name, fmt, ap); va_end (ap); va_start (ap, fmt); parser->error = btor_parse_error_message (parser->mem, parser->name, (parser->perrlineno ? parser->perrlineno : parser->lineno), fmt, ap, bytes); va_end (ap); } return parser->error; } static unsigned btor_primes_smt2[] = { 1000000007u, 2000000011u, 3000000019u, 4000000007u }; #define BTOR_NPRIMES_SMT2 (sizeof btor_primes_smt2/sizeof*btor_primes_smt2) static unsigned btor_hash_name_smt2 (BtorSMT2Parser * parser, const char * name) { unsigned res = 0, i = 0; unsigned char ch; const char * p; for (p = name; (ch = *p); p++) { res += ch; res *= btor_primes_smt2[i++]; if (i == BTOR_NPRIMES_SMT2) i = 0; } return res & (parser->symbol.size - 1); } static BtorSMT2Node ** btor_symbol_position_smt2 (BtorSMT2Parser * parser, const char * name) { unsigned h = btor_hash_name_smt2 (parser, name); BtorSMT2Node ** p, * s; for (p = parser->symbol.table + h; (s = *p) && strcmp (s->name, name); p = &s->next) ; return p; } static int btor_nextch_smt2 (BtorSMT2Parser * parser) { int res; if (parser->saved) res = parser->savedch, parser->saved = 0; else if (parser->prefix && parser->nprefix < BTOR_COUNT_STACK (*parser->prefix)) res = parser->prefix->start[parser->nprefix++]; else res = getc (parser->file); if (res == '\n') parser->lineno++; return res; } static void btor_savech_smt2 (BtorSMT2Parser * parser, char ch) { assert (!parser->saved); parser->saved = 1; parser->savedch = ch; if (ch == '\n') assert (parser->lineno > 1), parser->lineno--; } static void btor_enlarge_symbol_table_smt2 (BtorSMT2Parser * parser) { unsigned old_size = parser->symbol.size; unsigned new_size = old_size ? 2*old_size : 1; BtorSMT2Node ** old_table = parser->symbol.table, * p, * next, ** q; unsigned h, i; BTOR_NEWN (parser->mem, parser->symbol.table, new_size); BTOR_CLRN (parser->symbol.table, new_size); parser->symbol.size = new_size; for (i = 0; i < old_size; i++) for (p = old_table[i]; p; p = next) { next = p->next; h = btor_hash_name_smt2 (parser, p->name); p->next = *(q = parser->symbol.table + h); *q = p; } BTOR_DELETEN (parser->mem, old_table, old_size); } static void btor_insert_symbol_smt2 (BtorSMT2Parser * parser, BtorSMT2Node * symbol) { BtorSMT2Node ** p; if (parser->symbol.size <= parser->symbol.count) btor_enlarge_symbol_table_smt2 (parser); p = btor_symbol_position_smt2 (parser, symbol->name); assert (!*p); *p = symbol; parser->symbol.count++; assert (parser->symbol.count > 0); } static BtorSMT2Node * btor_find_symbol_smt2 (BtorSMT2Parser * parser, const char * name) { return *btor_symbol_position_smt2 (parser, name); } static BtorSMT2Node * btor_new_node_smt2 (BtorSMT2Parser * parser, BtorSMT2Tag tag) { BtorSMT2Node * res; BTOR_NEW (parser->mem, res); BTOR_CLR (res); res->tag = tag; return res; } static void btor_release_symbol_smt2 (BtorSMT2Parser * parser, BtorSMT2Node * symbol) { assert (symbol->tag != BTOR_PARENT_TAG_SMT2); if (symbol->exp) btor_release_exp (parser->btor, symbol->exp); btor_freestr (parser->mem, symbol->name); BTOR_DELETE (parser->mem, symbol); } static void btor_remove_symbol_smt2 (BtorSMT2Parser * parser, BtorSMT2Node * symbol) { BtorSMT2Node ** p; p = btor_symbol_position_smt2 (parser, symbol->name); assert (*p == symbol); *p = symbol->next; btor_release_symbol_smt2 (parser, symbol); assert (parser->symbol.count > 0); parser->symbol.count--; } static void btor_release_symbols_smt2 (BtorSMT2Parser * parser) { BtorSMT2Node * p, *next; unsigned i; for (i = 0; i < parser->symbol.size; i++) for (p = parser->symbol.table[i]; p; p = next) next = p->next, btor_release_symbol_smt2 (parser, p); BTOR_DELETEN (parser->mem, parser->symbol.table, parser->symbol.size); } static void btor_init_char_classes_smt2 (BtorSMT2Parser * parser) { unsigned char * cc = parser->cc; const char * p; BTOR_CLRN (cc, 256); for (p = btor_decimal_digits_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2; for (p = btor_hexadecimal_digits_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_HEXADECIMAL_DIGIT_CHAR_CLASS_SMT2; for (p = btor_printable_ascii_chars_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_STRING_CHAR_CLASS_SMT2; for (p = btor_letters_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_SYMBOL_CHAR_CLASS_SMT2; for (p = btor_decimal_digits_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_SYMBOL_CHAR_CLASS_SMT2; for (p = btor_extra_symbol_chars_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_SYMBOL_CHAR_CLASS_SMT2; for (p = btor_printable_ascii_chars_smt2; *p; p++) if (*p != '\\' && *p != '|') cc[(unsigned char)*p] |= BTOR_QUOTED_SYMBOL_CHAR_CLASS_SMT2; for (p = btor_letters_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_KEYWORD_CHAR_CLASS_SMT2; for (p = btor_decimal_digits_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_KEYWORD_CHAR_CLASS_SMT2; for (p = btor_extra_keyword_chars_smt2; *p; p++) cc[(unsigned char)*p] |= BTOR_KEYWORD_CHAR_CLASS_SMT2; } #define INSERT(STR,TAG) \ do { \ BtorSMT2Node * NODE = btor_new_node_smt2 (parser, (TAG)); \ NODE->name = btor_strdup (parser->mem, (STR)); \ btor_insert_symbol_smt2 (parser, NODE); \ } while (0) static void btor_insert_keywords_smt2 (BtorSMT2Parser * parser) { INSERT (":all-statistics", BTOR_ALL_STATISTICS_TAG_SMT2); INSERT (":authors", BTOR_AUTHORS_TAG_SMT2); INSERT (":axioms", BTOR_AXIOMS_TAG_SMT2); INSERT (":chainable", BTOR_CHAINABLE_TAG_SMT2); INSERT (":definition", BTOR_DEFINITION_TAG_SMT2); INSERT (":diagnostic-output-channel", BTOR_DIAG_OUTPUT_CHANNEL_TAG_SMT2); INSERT (":error-behavior", BTOR_ERROR_BEHAVIOR_TAG_SMT2); INSERT (":expand-definitions", BTOR_EXPAND_DEFINITIONS_TAG_SMT2); INSERT (":extensions", BTOR_EXTENSIONS_TAG_SMT2); INSERT (":funs", BTOR_FUNS_TAG_SMT2); INSERT (":funs-description", BTOR_FUNS_DESCRIPTION_TAG_SMT2); INSERT (":interactive-mode", BTOR_INTERACTIVE_MODE_TAG_SMT2); INSERT (":language", BTOR_LANGUAGE_TAG_SMT2); INSERT (":left-assoc", BTOR_LEFT_ASSOC_TAG_SMT2); INSERT (":name", BTOR_NAME_TAG_SMT2); INSERT (":named", BTOR_NAMED_TAG_SMT2); INSERT (":notes", BTOR_NOTES_TAG_SMT2); INSERT (":print-success", BTOR_PRINT_SUCCESS_TAG_SMT2); INSERT (":produce-assignments", BTOR_PRODUCE_ASSIGNMENTS_TAG_SMT2); INSERT (":produce-models", BTOR_PRODUCE_MODELS_TAG_SMT2); INSERT (":produce-proofs", BTOR_PRODUCE_PROOFS_TAG_SMT2); INSERT (":produce-unsat-cores", BTOR_PRODUCE_UNSAT_CORES_TAG_SMT2); INSERT (":random-seed", BTOR_RANDOM_SEED_TAG_SMT2); INSERT (":reason-unknown", BTOR_REASON_UNKNOWN_TAG_SMT2); INSERT (":regular-output-channel", BTOR_REGULAR_OUTPUT_CHANNEL_TAG_SMT2); INSERT (":right-assoc", BTOR_RIGHT_ASSOC_TAG_SMT2); INSERT (":sorts", BTOR_SORTS_TAG_SMT2); INSERT (":sorts-description", BTOR_SORTS_DESCRIPTION_TAG_SMT2); INSERT (":status", BTOR_STATUS_TAG_SMT2); INSERT (":theories", BTOR_THEORIES_TAG_SMT2); INSERT (":values", BTOR_VALUES_TAG_SMT2); INSERT (":verbosity", BTOR_VERBOSITY_TAG_SMT2); INSERT (":version", BTOR_VERSION_TAG_SMT2); } static void btor_insert_reserved_words_smt2 (BtorSMT2Parser * parser) { INSERT ("!", BTOR_BANG_TAG_SMT2); INSERT ("_", BTOR_UNDERSCORE_TAG_SMT2); INSERT ("as", BTOR_AS_TAG_SMT2); INSERT ("DECIMAL", BTOR_DECIMAL_RESERVED_WORD_TAG_SMT2); INSERT ("exists", BTOR_EXISTS_TAG_SMT2); INSERT ("forall", BTOR_FORALL_TAG_SMT2); INSERT ("let", BTOR_LET_TAG_SMT2); INSERT ("par", BTOR_PAR_TAG_SMT2); INSERT ("STRING", BTOR_STRING_RESERVED_WORD_TAG_SMT2); } static void btor_insert_commands_smt2 (BtorSMT2Parser * parser) { INSERT ("assert", BTOR_ASSERT_TAG_SMT2); INSERT ("check-sat", BTOR_CHECK_SAT_TAG_SMT2); INSERT ("declare-sort", BTOR_DECLARE_SORT_TAG_SMT2); INSERT ("declare-fun", BTOR_DECLARE_FUN_TAG_SMT2); INSERT ("define-sort", BTOR_DEFINE_SORT_TAG_SMT2); INSERT ("define-fun", BTOR_DEFINE_FUN_TAG_SMT2); INSERT ("exit", BTOR_EXIT_TAG_SMT2); INSERT ("get-assertions", BTOR_GET_ASSERTIONS_TAG_SMT2); INSERT ("get-assignment", BTOR_GET_ASSIGNMENT_TAG_SMT2); INSERT ("get-info", BTOR_GET_INFO_TAG_SMT2); INSERT ("get-option", BTOR_GET_OPTION_TAG_SMT2); INSERT ("get-proof", BTOR_GET_PROOF_TAG_SMT2); INSERT ("get-unsat-core", BTOR_GET_UNSAT_CORE_TAG_SMT2); INSERT ("get-value", BTOR_GET_VALUE_TAG_SMT2); INSERT ("pop", BTOR_POP_TAG_SMT2); INSERT ("push", BTOR_PUSH_TAG_SMT2); INSERT ("set-logic", BTOR_SET_LOGIC_TAG_SMT2); INSERT ("set-info", BTOR_SET_INFO_TAG_SMT2); INSERT ("set-option", BTOR_SET_OPTION_TAG_SMT2); } static void btor_insert_core_symbols_smt2 (BtorSMT2Parser * parser) { INSERT ("Bool", BTOR_BOOL_TAG_SMT2); INSERT ("true", BTOR_TRUE_TAG_SMT2); INSERT ("false", BTOR_FALSE_TAG_SMT2); INSERT ("not", BTOR_NOT_TAG_SMT2); INSERT ("=>", BTOR_IMPLIES_TAG_SMT2); INSERT ("and", BTOR_AND_TAG_SMT2); INSERT ("or", BTOR_OR_TAG_SMT2); INSERT ("xor", BTOR_XOR_TAG_SMT2); INSERT ("=", BTOR_EQUAL_TAG_SMT2); INSERT ("distinct", BTOR_DISTINCT_TAG_SMT2); INSERT ("ite", BTOR_ITE_TAG_SMT2); } static void btor_insert_array_symbols_smt2 (BtorSMT2Parser * parser) { INSERT ("Array", BTOR_ARRAY_TAG_SMT2); INSERT ("select", BTOR_SELECT_TAG_SMT2); INSERT ("store", BTOR_STORE_TAG_SMT2); } static void btor_insert_bitvec_symbols_smt2 (BtorSMT2Parser * parser) { INSERT ("BitVec", BTOR_BITVEC_TAG_SMT2); INSERT ("concat", BTOR_CONCAT_TAG_SMT2); INSERT ("extract", BTOR_EXTRACT_TAG_SMT2); INSERT ("bvnot", BTOR_BVNOT_TAG_SMT2); INSERT ("bvneg", BTOR_BVNEG_TAG_SMT2); INSERT ("bvand", BTOR_BVAND_TAG_SMT2); INSERT ("bvor", BTOR_BVOR_TAG_SMT2); INSERT ("bvadd", BTOR_BVADD_TAG_SMT2); INSERT ("bvmul", BTOR_BVMUL_TAG_SMT2); INSERT ("bvudiv", BTOR_BVUDIV_TAG_SMT2); INSERT ("bvurem", BTOR_BVUREM_TAG_SMT2); INSERT ("bvshl", BTOR_BVSHL_TAG_SMT2); INSERT ("bvlshr", BTOR_BVLSHR_TAG_SMT2); INSERT ("bvult", BTOR_BVULT_TAG_SMT2); INSERT ("bvnand", BTOR_BVNAND_TAG_SMT2); INSERT ("bvnor", BTOR_BVNOR_TAG_SMT2); INSERT ("bvxor", BTOR_BVXOR_TAG_SMT2); INSERT ("bvxnor", BTOR_BVXNOR_TAG_SMT2); INSERT ("bvcomp", BTOR_BVCOMP_TAG_SMT2); INSERT ("bvsub", BTOR_BVSUB_TAG_SMT2); INSERT ("bvsdiv", BTOR_BVSDIV_TAG_SMT2); INSERT ("bvsrem", BTOR_BVSREM_TAG_SMT2); INSERT ("bvsmod", BTOR_BVSMOD_TAG_SMT2); INSERT ("bvashr", BTOR_BVASHR_TAG_SMT2); INSERT ("repeat", BTOR_REPEAT_TAG_SMT2); INSERT ("zero_extend", BTOR_ZERO_EXTEND_TAG_SMT2); INSERT ("sign_extend", BTOR_SIGN_EXTEND_TAG_SMT2); INSERT ("rotate_left", BTOR_ROTATE_LEFT_TAG_SMT2); INSERT ("rotate_right", BTOR_ROTATE_RIGHT_TAG_SMT2); INSERT ("bvule", BTOR_BVULE_TAG_SMT2); INSERT ("bvugt", BTOR_BVUGT_TAG_SMT2); INSERT ("bvuge", BTOR_BVUGE_TAG_SMT2); INSERT ("bvslt", BTOR_BVSLT_TAG_SMT2); INSERT ("bvsle", BTOR_BVSLE_TAG_SMT2); INSERT ("bvsgt", BTOR_BVSGT_TAG_SMT2); INSERT ("bvsge", BTOR_BVSGE_TAG_SMT2); } static void btor_insert_logics_smt2 (BtorSMT2Parser * parser) { INSERT ("QF_BV", BTOR_QF_BV_TAG_SMT2); INSERT ("QF_ABV", BTOR_QF_ABV_TAG_SMT2); INSERT ("QF_UFBV", BTOR_QF_UFBV_TAG_SMT2); INSERT ("QF_AUFBV", BTOR_QF_AUFBV_TAG_SMT2); } static BtorSMT2Parser * btor_new_smt2_parser (Btor * btor, BtorParseOpt * opts) { BtorSMT2Parser * res; BTOR_NEW (btor->mm, res); BTOR_CLR (res); res->verbosity = opts->verbosity; res->incremental = opts->incremental; res->model = opts->need_model; res->btor = btor; res->mem = btor->mm; btor_init_char_classes_smt2 (res); btor_insert_keywords_smt2 (res); btor_insert_reserved_words_smt2 (res); btor_insert_commands_smt2 (res); btor_insert_core_symbols_smt2 (res); btor_insert_array_symbols_smt2 (res); btor_insert_bitvec_symbols_smt2 (res); btor_insert_logics_smt2 (res); return res; } static void btor_release_item_smt2 (BtorSMT2Parser * parser, BtorSMT2Item * item) { if (item->tag == BTOR_EXP_TAG_SMT2) { btor_release_exp (parser->btor, item->exp); } else if (item->tag & BTOR_CONSTANT_TAG_CLASS_SMT2) btor_freestr (parser->mem, item->str); } static void btor_release_work_smt2 (BtorSMT2Parser * parser) { BtorSMT2Item item; while (!BTOR_EMPTY_STACK (parser->work)) { item = BTOR_POP_STACK (parser->work); btor_release_item_smt2 (parser, &item); } BTOR_RELEASE_STACK (parser->mem, parser->work); } static void btor_delete_smt2_parser (BtorSMT2Parser * parser) { BtorMemMgr * mem = parser->mem; btor_release_symbols_smt2 (parser); btor_release_work_smt2 (parser); if (parser->name) btor_freestr (mem, parser->name); if (parser->error) btor_freestr (mem, parser->error); while (!BTOR_EMPTY_STACK (parser->inputs)) btor_release_exp (parser->btor, BTOR_POP_STACK (parser->inputs)); BTOR_RELEASE_STACK (mem, parser->inputs); while (!BTOR_EMPTY_STACK (parser->outputs)) btor_release_exp (parser->btor, BTOR_POP_STACK (parser->outputs)); BTOR_RELEASE_STACK (mem, parser->outputs); BTOR_RELEASE_STACK (mem, parser->token); BTOR_DELETE (mem, parser); } static void btor_msg_smt2 (BtorSMT2Parser * parser, int level, const char * fmt, ...) { va_list ap; if (parser->verbosity < level) return; printf ("[btorsmt2] "); va_start (ap, fmt); vprintf (fmt, ap); va_end (ap); printf ("\n"); fflush (stdout); } static int btor_isspace_smt2 (int ch) { return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; } static unsigned btor_cc_smt2 (BtorSMT2Parser * parser, int ch) { if (ch == EOF) return 0; assert (0 <= ch && ch < 256); return parser->cc[(unsigned char) ch]; } static void btor_pushch_smt2 (BtorSMT2Parser * parser, int ch) { assert (ch != EOF); BTOR_PUSH_STACK (parser->mem, parser->token, ch); } static int btor_read_token_aux_smt2 (BtorSMT2Parser * parser) { BtorSMT2Node * node; unsigned char cc; int ch; assert (!BTOR_INVALID_TAG_SMT2); // error code: 0 BTOR_RESET_STACK (parser->token); parser->last_node = 0; RESTART: do { if ((ch = btor_nextch_smt2 (parser)) == EOF) { assert (EOF < 0); return EOF; // end of tokens: EOF } } while (btor_isspace_smt2 (ch)); if (ch == ';') { while ((ch = btor_nextch_smt2 (parser)) != '\n') if (ch == EOF) { assert (!BTOR_INVALID_TAG_SMT2); return !btor_perr_smt2 (parser, "unexpected end-of-file in comment"); } goto RESTART; } cc = btor_cc_smt2 (parser, ch); if (ch == '(') { btor_pushch_smt2 (parser, '('); btor_pushch_smt2 (parser, 0); return BTOR_LPAR_TAG_SMT2; } if (ch == ')') { btor_pushch_smt2 (parser, ')'); btor_pushch_smt2 (parser, 0); return BTOR_RPAR_TAG_SMT2; } if (ch == '#') { btor_pushch_smt2 (parser, '#'); if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '#'"); if (ch == 'b') { btor_pushch_smt2 (parser, 'b'); if((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '#b'"); if (ch != '0' && ch != '1') return !btor_perr_smt2 (parser, "expected '0' or '1' after '#b'"); btor_pushch_smt2 (parser, ch); for (;;) { ch = btor_nextch_smt2 (parser); if (ch != '0' && ch != '1') break; btor_pushch_smt2 (parser, ch); } btor_savech_smt2 (parser, ch); btor_pushch_smt2 (parser, 0); return BTOR_BINARY_CONSTANT_TAG_SMT2; } else if (ch == 'x') { btor_pushch_smt2 (parser, 'x'); if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '#x'"); if (!(btor_cc_smt2 (parser, ch) & BTOR_HEXADECIMAL_DIGIT_CHAR_CLASS_SMT2)) return !btor_perr_smt2 (parser, "expected hexa-decimal digit after '#x'"); btor_pushch_smt2 (parser, ch); for (;;) { ch = btor_nextch_smt2 (parser); if (!(btor_cc_smt2 (parser, ch) & BTOR_HEXADECIMAL_DIGIT_CHAR_CLASS_SMT2)) break; btor_pushch_smt2 (parser, ch); } btor_savech_smt2 (parser, ch); btor_pushch_smt2 (parser, 0); return BTOR_HEXADECIMAL_CONSTANT_TAG_SMT2; } else return !btor_perr_smt2 (parser, "expected 'x' or 'b' after '#'"); } else if (ch == '"') { btor_pushch_smt2 (parser, '"'); for (;;) { if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file in string"); if (ch == '"') { btor_pushch_smt2 (parser, '"'); btor_pushch_smt2 (parser, 0); return BTOR_STRING_CONSTANT_TAG_SMT2; } if (ch == '\\') { if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '\\'"); if (ch != '"' && ch != '\\') return !btor_perr_smt2 (parser, "expected '\"' or '\\' after '\\'"); } else if (!(btor_cc_smt2 (parser, ch) & BTOR_STRING_CHAR_CLASS_SMT2)) return !btor_perr_smt2 (parser, "invalid character code %d in string", ch); btor_pushch_smt2 (parser, ch); } } else if (ch == '|') { btor_pushch_smt2 (parser, '|'); for (;;) { if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file in quoted symbol"); if (ch == '|') { btor_pushch_smt2 (parser, '|'); btor_pushch_smt2 (parser, 0); if (!(node = btor_find_symbol_smt2 (parser, parser->token.start))) { node = btor_new_node_smt2 (parser, BTOR_SYMBOL_TAG_SMT2); node->name = btor_strdup (parser->mem, parser->token.start); btor_insert_symbol_smt2 (parser, node); } parser->last_node = node; return BTOR_SYMBOL_TAG_SMT2; } if (!(btor_cc_smt2 (parser, ch) & BTOR_QUOTED_SYMBOL_CHAR_CLASS_SMT2)) return !btor_perr_smt2 (parser, "invalid character code %d in quoted symbol", ch); btor_pushch_smt2 (parser, ch); } } else if (ch == ':') { btor_pushch_smt2 (parser, ':'); if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after ':'"); if (!(btor_cc_smt2 (parser, ch) & BTOR_KEYWORD_CHAR_CLASS_SMT2)) return !btor_perr_smt2 (parser, "unexpected character code %d after ':'", ch); btor_pushch_smt2 (parser, ch); while ((btor_cc_smt2 (parser, ch = btor_nextch_smt2 (parser)) & BTOR_KEYWORD_CHAR_CLASS_SMT2)) { assert (ch != EOF); btor_pushch_smt2 (parser, ch); } btor_savech_smt2 (parser, ch); btor_pushch_smt2 (parser, 0); if (!(node = btor_find_symbol_smt2 (parser, parser->token.start))) { node = btor_new_node_smt2 (parser, BTOR_ATTRIBUTE_TAG_SMT2); node->name = btor_strdup (parser->mem, parser->token.start); btor_insert_symbol_smt2 (parser, node); } parser->last_node = node; return node->tag; } else if (ch == '0') { btor_pushch_smt2 (parser, '0'); ch = btor_nextch_smt2 (parser); if (ch == '.') { btor_pushch_smt2 (parser, '.'); if ((ch = btor_nextch_smt2 (parser)) == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '0.'"); if (!(btor_cc_smt2 (parser, ch) & BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2)) return !btor_perr_smt2 (parser, "expected decimal digit after '0.'"); btor_pushch_smt2 (parser, ch); for (;;) { ch = btor_nextch_smt2 (parser); if (!(btor_cc_smt2 (parser, ch) & BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2)) break; btor_pushch_smt2 (parser, ch); } } btor_savech_smt2 (parser, ch); btor_pushch_smt2 (parser, 0); return BTOR_DECIMAL_CONSTANT_TAG_SMT2; } else if (cc & BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2) { btor_pushch_smt2 (parser, ch); for (;;) { ch = btor_nextch_smt2 (parser); if (!(btor_cc_smt2 (parser, ch) & BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2)) break; btor_pushch_smt2 (parser, ch); } if (ch == '.') { btor_pushch_smt2 (parser, '.'); if ((ch = btor_nextch_smt2 (parser)) == EOF) { btor_pushch_smt2 (parser, 0); return !btor_perr_smt2 (parser, "unexpected end-of-file after '%s'", parser->token.start); } if (!(btor_cc_smt2 (parser, ch) & BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2)) { btor_pushch_smt2 (parser, 0); return !btor_perr_smt2 (parser, "expected decimal digit after '%s'", parser->token.start); } btor_pushch_smt2 (parser, ch); for (;;) { ch = btor_nextch_smt2 (parser); if (!(btor_cc_smt2 (parser, ch) & BTOR_DECIMAL_DIGIT_CHAR_CLASS_SMT2)) break; btor_pushch_smt2 (parser, ch); } } btor_savech_smt2 (parser, ch); btor_pushch_smt2 (parser, 0); return BTOR_DECIMAL_CONSTANT_TAG_SMT2; } else if (cc & BTOR_SYMBOL_CHAR_CLASS_SMT2) { btor_pushch_smt2 (parser, ch); for (;;) { ch = btor_nextch_smt2 (parser); if (!(btor_cc_smt2 (parser, ch) & BTOR_SYMBOL_CHAR_CLASS_SMT2)) break; btor_pushch_smt2 (parser, ch); } btor_savech_smt2 (parser, ch); btor_pushch_smt2 (parser, 0); if (!strcmp (parser->token.start, "_")) return BTOR_UNDERSCORE_TAG_SMT2; if (!(node = btor_find_symbol_smt2 (parser, parser->token.start))) { node = btor_new_node_smt2 (parser, BTOR_SYMBOL_TAG_SMT2); node->name = btor_strdup (parser->mem, parser->token.start); btor_insert_symbol_smt2 (parser, node); } parser->last_node = node; return node->tag; } else return !btor_perr_smt2 (parser, "unexpected character code %d", ch); // should be dead code ... return !btor_perr_smt2 (parser, "internal token reading error"); } static int btor_read_token_smt2 (BtorSMT2Parser * parser) { int res = btor_read_token_aux_smt2 (parser); if (parser->verbosity >= 4) { printf ("[btorsmt2] line %08d token %08x %s\n", parser->lineno, res, res == EOF ? "" : res == BTOR_INVALID_TAG_SMT2 ? "" :parser->token.start); fflush (stdout); } return res; } static int btor_read_rpar_smt2 (BtorSMT2Parser * parser, const char * msg) { int tag = btor_read_token_smt2 (parser); if (tag == EOF) return !btor_perr_smt2 (parser, "expected ')'%s at end-of-file", msg ? msg : ""); if (tag == BTOR_INVALID_TAG_SMT2) { assert (parser->error); return 0; } if (tag != BTOR_RPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "expected ')'%s at '%s'", msg ? msg : "", parser->token.start); return 1; } static int btor_read_lpar_smt2 (BtorSMT2Parser * parser, const char * msg) { int tag = btor_read_token_smt2 (parser); if (tag == EOF) return !btor_perr_smt2 (parser, "expected '('%s at end-of-file", msg ? msg : ""); if (tag == BTOR_INVALID_TAG_SMT2) { assert (parser->error); return 0; } if (tag != BTOR_LPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "expected '('%s at '%s'", msg ? msg : "", parser->token.start); return 1; } static int btor_skip_sexprs (BtorSMT2Parser * parser, int initial) { int tag, open = initial; while (open > 0) { tag = btor_read_token_smt2 (parser); if (tag == EOF) { if (open > 0) return !btor_perr_smt2 (parser, "')' missing at end-of-file"); return 1; } if (tag == BTOR_INVALID_TAG_SMT2) { assert (parser->error); return 0; } else if (tag == BTOR_LPAR_TAG_SMT2) open++; else if (tag == BTOR_RPAR_TAG_SMT2) open--; } return 1; } static int btor_read_symbol (BtorSMT2Parser * parser, const char * errmsg, BtorSMT2Node ** resptr) { int tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "expected symbol%s but reached end-of-file", errmsg ? errmsg : ""); if (tag != BTOR_SYMBOL_TAG_SMT2) return !btor_perr_smt2 (parser, "expected symbol%s at '%s'", errmsg ? errmsg : "", parser->token.start); assert (parser->last_node->tag == BTOR_SYMBOL_TAG_SMT2); *resptr = parser->last_node; return 1; } static int btor_str2int32_smt2 (BtorSMT2Parser * parser, int posonly, const char * str, int * resptr) { int res, ch, digit; const char * p; res = 0; assert (sizeof (int) == 4); for (p = str; (ch = *p); p++) { if (res > INT_MAX/10) INVALID: return !btor_perr_smt2 (parser, "invalid 32-bit integer '%s'", str); assert ('0' <= ch && ch <= '9'); res *= 10; digit = ch - '0'; if (INT_MAX - digit < res) goto INVALID; res += digit; } if (posonly && !res) return !btor_perr_smt2 (parser, "expected positive non-zero 32-bit integer at '%s'", str); *resptr = res; return 1; } static BtorSMT2Item * btor_push_item_smt2 (BtorSMT2Parser * parser, BtorSMT2Tag tag) { BtorSMT2Item item; BTOR_CLR (&item); item.lineno = parser->lineno; item.tag = tag; BTOR_PUSH_STACK (parser->mem, parser->work, item); return &BTOR_TOP_STACK (parser->work); } static BtorSMT2Item * btor_last_lpar_smt2 (BtorSMT2Parser * parser) { BtorSMT2Item * p = parser->work.top; do { if (p-- == parser->work.start) return 0; } while (p->tag != BTOR_LPAR_TAG_SMT2); return p; } #define BTOR_TAG_CLASS_MASK_SMT2 \ (BTOR_RESERVED_TAG_CLASS_SMT2 | \ BTOR_COMMAND_TAG_CLASS_SMT2 | \ BTOR_KEYWORD_TAG_CLASS_SMT2 | \ BTOR_CORE_TAG_CLASS_SMT2 | \ BTOR_ARRAY_TAG_CLASS_SMT2 | \ BTOR_BITVEC_TAG_CLASS_SMT2 | \ BTOR_LOGIC_TAG_CLASS_SMT2 ) static int btor_item_with_node_smt2 (BtorSMT2Item * item) { if (item->tag == BTOR_SYMBOL_TAG_SMT2) return 1; if (item->tag == BTOR_ATTRIBUTE_TAG_SMT2) return 1; if (item->tag & BTOR_TAG_CLASS_MASK_SMT2) return 1; return 0; } static const char * btor_item2str_smt2 (BtorSMT2Item * item) { if (btor_item_with_node_smt2 (item)) { if (!item->node) return ""; assert (item->node->name); return item->node->name; } else if (item->tag & BTOR_CONSTANT_TAG_CLASS_SMT2) { assert (item->str); return item->str; } else return ""; } static int btor_bvconst_str_smt2 (const char * str) { const char * p; if (str[0] != 'b' || str[1] != 'v') return 0; if (!isdigit (str[2])) return 0; for (p = str + 3; *p; p++) if (!isdigit (*p)) return 0; return 1; } static int btor_prev_item_was_lpar_smt2 (BtorSMT2Parser * parser) { if (BTOR_COUNT_STACK (parser->work) >= 2 && parser->work.top[-2].tag == BTOR_LPAR_TAG_SMT2) return 1; return !btor_perr_smt2 (parser, "expected '(' before '%s'", parser->token.start); } static int btor_parse_int32_smt2 (BtorSMT2Parser * parser, int posonly, int * resptr) { int tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "expected decimal constant but reached end-of-file"); if (tag != BTOR_DECIMAL_CONSTANT_TAG_SMT2) return !btor_perr_smt2 (parser, "expected decimal constant at '%s'", parser->token.start); return btor_str2int32_smt2 (parser, posonly, parser->token.start, resptr); } static int btor_check_boolean_args_smt2 (BtorSMT2Parser * parser, BtorSMT2Item * p, int nargs) { int i, width; for (i = 1; i <= nargs; i++) { if (btor_is_array_exp (parser->btor, p[i].exp)) return !btor_perr_smt2 (parser, "argument %d of '%s' is an array term", i, p->node->name); if ((width = btor_get_exp_len (parser->btor, p[i].exp)) != 1) return !btor_perr_smt2 (parser, "argument %d of '%s' is a bit-vector of width %d", i, width, p->node->name); } return 1; } static int btor_check_arg_sorts_match_smt2 (BtorSMT2Parser * parser, BtorSMT2Item * p, int nargs) { int i, domain, width, len; assert (nargs >= 1); width = btor_get_exp_len (parser->btor, p[1].exp); if (btor_is_array_exp (parser->btor, p[1].exp)) { domain = btor_get_index_exp_len (parser->btor, p[1].exp); for (i = 2; i <= nargs; i++) { if (!btor_is_array_exp (parser->btor, p[i].exp)) return !btor_perr_smt2 (parser, "first argument of '%s' is an array but argument %d not", p->node->name, i); if ((len = btor_get_exp_len (parser->btor, p[i].exp)) != width) return !btor_perr_smt2 (parser, "first argument of '%s' is an array of bit-vectors of width %d " "but argument %d is an array of bit-vectors of width %d", p->node->name, width, i, len); if ((len = btor_get_index_exp_len (parser->btor, p[i].exp)) != domain) return !btor_perr_smt2 (parser, "first argument of '%s' is an array with index bit-vectors of width %d " "but argument %d is an array with index bit-vectors of width %d", p->node->name, domain, i, len); } } else { for (i = 1; i <= nargs; i++) { if (btor_is_array_exp (parser->btor, p[i].exp)) return !btor_perr_smt2 (parser, "argument %d of '%s' is an array but first argument not", i, p->node->name); if ((len = btor_get_exp_len (parser->btor, p[i].exp)) != width) return !btor_perr_smt2 (parser, "first argument of '%s' is bit-vector of width %d " "but argument %d is a bit-vector of width %d", p->node->name, width, i, len); } } return 1; } static int btor_check_ite_args_sorts_match_smt2 (BtorSMT2Parser * parser, BtorSMT2Item * p) { int domain, width, len; assert (p->tag == BTOR_ITE_TAG_SMT2); if (btor_is_array_exp (parser->btor, p[1].exp)) return !btor_perr_smt2 (parser, "first argument of 'ite' is an array"); if ((len = btor_get_exp_len (parser->btor, p[1].exp)) != 1) return !btor_perr_smt2 (parser, "first argument of 'ite' is non-boolean"); if (btor_is_array_exp (parser->btor, p[2].exp)) { if (!btor_is_array_exp (parser->btor, p[3].exp)) return !btor_perr_smt2 (parser, "second argument of 'ite' is an array but third not"); width = btor_get_exp_len (parser->btor, p[2].exp); len = btor_get_exp_len (parser->btor, p[3].exp); if (width != len) return !btor_perr_smt2 (parser, "second argument of 'ite' is array of bit-vectors of width %d and " "third argument is array of bit-vectors of width %d", width, len); domain = btor_get_index_exp_len (parser->btor, p[2].exp); len = btor_get_index_exp_len (parser->btor, p[3].exp); if (domain != len) return !btor_perr_smt2 (parser, "second argument of 'ite' is array with index bit-vectors of width %d and " "third argument is array with index bit-vectors of width %d", domain, len); } else { if (btor_is_array_exp (parser->btor, p[3].exp)) return !btor_perr_smt2 (parser, "third argument of 'ite' is an array but second not"); width = btor_get_exp_len (parser->btor, p[2].exp); len = btor_get_exp_len (parser->btor, p[3].exp); if (width != len) return !btor_perr_smt2 (parser, "second argument of 'ite' is bit-vector of width %d and " "third argument is bit-vector of width %d", width, len); } return 1; } static int btor_check_nargs_smt2 (BtorSMT2Parser * parser, const char * op, int actual, int required) { int diff = required - actual; if (diff == -1) return !btor_perr_smt2 (parser, "one argument to '%s' missing", op); if (diff < 0) return !btor_perr_smt2 (parser, "%d arguments to '%s' missing", -diff, op); if (diff == 1) return !btor_perr_smt2 (parser, "'%s' has one argument too much", op); if (diff > 0) return !btor_perr_smt2 (parser, "'%s' has %d arguments too much", op, diff); return 1; } static int btor_check_not_array_args_smt2 (BtorSMT2Parser * parser, BtorSMT2Item * p, int nargs) { int i; for (i = 1; i <= nargs; i++) if (btor_is_array_exp (parser->btor, p[i].exp)) return !btor_perr_smt2 (parser, "argument %d of '%s' is an array", i, p->node->name); return 1; } static BtorNode * btor_translate_shift_smt2 ( Btor * btor, BtorNode * a0, BtorNode * a1, BtorNode * (*f)(Btor*,BtorNode*,BtorNode*)) { BtorNode * c, * e, * t, * e0, * u, * l, * tmp, * res; int len, l0, l1, p0, p1; len = btor_get_exp_len (btor, a0); assert (len == btor_get_exp_len (btor, a1)); l1 = 0; for (l0 = 1; l0 < len; l0 *= 2) l1++; assert (l0 == (1 << l1)); if (len == 1) { assert (l0 == 1); assert (l1 == 0); if (f != btor_sra_exp) { tmp = btor_not_exp (btor, a1); res = btor_and_exp (btor, a0, tmp); btor_release_exp (btor, tmp); } else res = btor_copy_exp (btor, a0); } else { assert (len >= 1); p0 = l0 - len; p1 = len - l1; assert (p0 >= 0); assert (p1 > 0); u = btor_slice_exp (btor, a1, len - 1, len - p1); l = btor_slice_exp (btor, a1, l1 - 1, 0); assert (btor_get_exp_len (btor, u) == p1); assert (btor_get_exp_len (btor, l) == l1); if (p1 > 1) c = btor_redor_exp (btor, u); else c = btor_copy_exp (btor, u); btor_release_exp (btor, u); if (f == btor_sra_exp) { tmp = btor_slice_exp (btor, a0, len - 1, len - 1); t = btor_sext_exp (btor, tmp, len - 1); btor_release_exp (btor, tmp); } else t = btor_zero_exp (btor, len); if (!p0) e0 = btor_copy_exp (btor, a0); else if (f == btor_sra_exp) e0 = btor_sext_exp (btor, a0, p0); else e0 = btor_uext_exp (btor, a0, p0); assert (btor_get_exp_len (btor, e0) == l0); e = f (btor, e0, l); btor_release_exp (btor, e0); btor_release_exp (btor, l); if (p0 > 0) { tmp = btor_slice_exp (btor, e, len - 1, 0); btor_release_exp (btor, e); e = tmp; } res = btor_cond_exp (btor, c, t, e); btor_release_exp (btor, c); btor_release_exp (btor, t); btor_release_exp (btor, e); } return res; } static BtorNode * btor_shl_smt2 (Btor * btor, BtorNode * a, BtorNode * b) { return btor_translate_shift_smt2 (btor, a, b, btor_sll_exp); } static BtorNode * btor_ashr_smt2 (Btor * btor, BtorNode * a, BtorNode * b) { return btor_translate_shift_smt2 (btor, a, b, btor_sra_exp); } static BtorNode * btor_lshr_smt2 (Btor * btor, BtorNode * a, BtorNode * b) { return btor_translate_shift_smt2 (btor, a, b, btor_srl_exp); } static BtorNode * btor_translate_rotate_smt2 ( Btor * btor, BtorNode * exp, int shift, int left) { BtorNode * l, * r, * res; int len; assert (shift >= 0); len = btor_get_exp_len (btor, exp); assert (len > 0); shift %= len; if (shift) { if (left) shift = len - shift; assert (1 <= shift && shift < len); l = btor_slice_exp (btor, exp, shift - 1, 0); r = btor_slice_exp (btor, exp, len - 1, shift); res = btor_concat_exp (btor, l, r); btor_release_exp (btor, l); btor_release_exp (btor, r); } else res = btor_copy_exp (btor, exp); assert (btor_get_exp_len (btor, res) == len); return res; } static BtorNode * btor_rotate_left_smt2 (Btor * btor, BtorNode * exp, int shift) { return btor_translate_rotate_smt2 (btor, exp, shift, 1); } static BtorNode * btor_rotate_right_smt2 (Btor * btor, BtorNode * exp, int shift) { return btor_translate_rotate_smt2 (btor, exp, shift, 0); } static int btor_parse_term_smt2 (BtorSMT2Parser * parser, BtorNode ** resptr, int * linenoptr) { int tag, width, domain, len, nargs, i, j, open = 0; BtorNode * (*binfun)(Btor *,BtorNode*,BtorNode*); BtorNode * (*extfun)(Btor *, BtorNode *, int); BtorNode * (*unaryfun)(Btor *,BtorNode*); BtorNode * res, * exp, * tmp, * old; BtorSMT2Item * l, * p; unaryfun = 0; binfun = 0; assert (BTOR_EMPTY_STACK (parser->work)); do { tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) { l = btor_last_lpar_smt2 (parser); if (!l) return !btor_perr_smt2 (parser, "expected term but reached end-of-file"); return !btor_perr_smt2 (parser, "unexpected end-of-file since '(' at line %d still open", l->lineno); } if (tag == BTOR_RPAR_TAG_SMT2) { assert (open > 0); l = btor_last_lpar_smt2 (parser); assert (l); p = l + 1; if (p == parser->work.top) return !btor_perr_smt2 (parser, "unexpected '()'"); nargs = parser->work.top - p - 1; tag = p->tag; #ifndef NDEBUG if (tag != BTOR_LET_TAG_SMT2 && tag != BTOR_LETBIND_TAG_SMT2 && tag != BTOR_PARLETBINDING_TAG_SMT2) for (i = 1; i <= nargs; i++) assert (p[i].tag == BTOR_EXP_TAG_SMT2); #endif if (tag == BTOR_EXP_TAG_SMT2) { if (nargs) { parser->perrlineno = l->lineno; return !btor_perr_smt2 (parser, "list with %d expressions", nargs + 1); } p->lineno = l->lineno; *l = *p; parser->work.top--; assert (l + 1 == parser->work.top); } else if (tag == BTOR_NOT_TAG_SMT2) { if (nargs != 1) return !btor_perr_smt2 (parser, "'not' with %d arguments but expected exactly one", nargs); tmp = p[1].exp; if (btor_is_array_exp (parser->btor, tmp)) return !btor_perr_smt2 (parser, "unexpected array expression as argument to 'not'"); if ((width = btor_get_exp_len (parser->btor, tmp)) != 1) return !btor_perr_smt2 (parser, "unexpected bit-vector of width %d as argument to 'not'", width); parser->work.top = p; l->tag = BTOR_EXP_TAG_SMT2; l->exp = btor_not_exp (parser->btor, tmp); btor_release_exp (parser->btor, tmp); } else if (tag == BTOR_IMPLIES_TAG_SMT2) { if (!nargs) return !btor_perr_smt2 (parser, "argument to '%s' missing", p->node->name); if (!btor_check_boolean_args_smt2 (parser, p, nargs)) return 0; exp = 0; for (i = nargs; i >= 1; i--) { if (exp) { old = exp; exp = btor_implies_exp (parser->btor, p[i].exp, old); btor_release_exp (parser->btor, old); } else exp = btor_copy_exp (parser->btor, p[i].exp); } assert (exp); RELEASE_EXP_AND_OVERWRITE: for (i = 1; i <= nargs; i++) btor_release_exp (parser->btor, p[i].exp); parser->work.top = p; l->tag = BTOR_EXP_TAG_SMT2; l->exp = exp; } else if (tag == BTOR_AND_TAG_SMT2) { binfun = btor_and_exp; BIN_LEFT_ASSOCIATIVE_CORE: if (!nargs) return !btor_perr_smt2 (parser, "argument to '%s' missing", p->node->name); if (!btor_check_boolean_args_smt2 (parser, p, nargs)) return 0; exp = 0; for (i = 1; i <= nargs; i++) { if (exp) { old = exp; exp = binfun (parser->btor, old, p[i].exp); btor_release_exp (parser->btor, old); } else exp = btor_copy_exp (parser->btor, p[i].exp); } assert (exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_OR_TAG_SMT2) { binfun = btor_or_exp; goto BIN_LEFT_ASSOCIATIVE_CORE; } else if (tag == BTOR_XOR_TAG_SMT2) { binfun = btor_xor_exp; goto BIN_LEFT_ASSOCIATIVE_CORE; } else if (tag == BTOR_EQUAL_TAG_SMT2) { if (!nargs) return !btor_perr_smt2 (parser, "arguments to '=' missing"); if (nargs == 1) return !btor_perr_smt2 (parser, "only one argument to '='"); if (!btor_check_arg_sorts_match_smt2 (parser, p, nargs)) return 0; exp = btor_true_exp (parser->btor); for (i = 1; i < nargs; i++) { tmp = btor_eq_exp (parser->btor, p[i].exp, p[i+1].exp); old = exp; exp = btor_and_exp (parser->btor, old, tmp); btor_release_exp (parser->btor, old); btor_release_exp (parser->btor, tmp); } goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_DISTINCT_TAG_SMT2) { if (!nargs) return !btor_perr_smt2 (parser, "arguments to 'distinct' missing"); if (nargs == 1) return !btor_perr_smt2 (parser, "only one argument to 'distinct'"); if (!btor_check_arg_sorts_match_smt2 (parser, p, nargs)) return 0; exp = btor_true_exp (parser->btor); for (i = 1; i < nargs; i++) { for (j = i + 1; j <= nargs; j++) { tmp = btor_ne_exp (parser->btor, p[i].exp, p[j].exp); old = exp; exp = btor_and_exp (parser->btor, old, tmp); btor_release_exp (parser->btor, old); btor_release_exp (parser->btor, tmp); } } goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_ITE_TAG_SMT2) { if(!btor_check_nargs_smt2 (parser, "ite", nargs, 3)) return 0; if (!btor_check_ite_args_sorts_match_smt2 (parser, p)) return 0; exp = btor_cond_exp (parser->btor, p[1].exp, p[2].exp, p[3].exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_SELECT_TAG_SMT2) { if(!btor_check_nargs_smt2 (parser, "select", nargs, 2)) return 0; if (!btor_is_array_exp (parser->btor, p[1].exp)) return !btor_perr_smt2 (parser, "first argument of 'select' is not an array"); if (btor_is_array_exp (parser->btor, p[2].exp)) return !btor_perr_smt2 (parser, "second argument of 'select' is an array"); width = btor_get_exp_len (parser->btor, p[2].exp); domain = btor_get_index_exp_len (parser->btor, p[1].exp); if (width != domain) return !btor_perr_smt2 (parser, "array argument of 'select' has index bit-width %d " "but the index argument has bit-width %d", domain, width); exp = btor_read_exp (parser->btor, p[1].exp, p[2].exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_STORE_TAG_SMT2) { if(!btor_check_nargs_smt2 (parser, "store", nargs, 3)) return 0; if (!btor_is_array_exp (parser->btor, p[1].exp)) return !btor_perr_smt2 (parser, "first argument of 'store' is not an array"); if (btor_is_array_exp (parser->btor, p[2].exp)) return !btor_perr_smt2 (parser, "second argument of 'store' is an array"); if (btor_is_array_exp (parser->btor, p[3].exp)) return !btor_perr_smt2 (parser, "third argument of 'store' is an array"); width = btor_get_exp_len (parser->btor, p[2].exp); domain = btor_get_index_exp_len (parser->btor, p[1].exp); if (width != domain) return !btor_perr_smt2 (parser, "array argument of 'store' has index bit-width %d " "but the index argument has bit-width %d", domain, width); width = btor_get_exp_len (parser->btor, p[1].exp); len = btor_get_exp_len (parser->btor, p[3].exp); if (width != len) return !btor_perr_smt2 (parser, "array argument of 'store' has element bit-width %d " "but the stored bit-vector argument has bit-width %d", width, len); exp = btor_write_exp (parser->btor, p[1].exp, p[2].exp, p[3].exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_CONCAT_TAG_SMT2) { if (!btor_check_nargs_smt2 (parser, "concat", nargs, 2)) return 0; if (!btor_check_not_array_args_smt2 (parser, p, nargs)) return 0; exp = btor_concat_exp (parser->btor, p[1].exp, p[2].exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_EXTRACT_TAG_SMT2) { if (!btor_check_nargs_smt2 (parser, "extract", nargs, 1)) return 0; if (!btor_check_not_array_args_smt2 (parser, p, nargs)) return 0; width = btor_get_exp_len (parser->btor, p[1].exp); if (width <= p->hi) return !btor_perr_smt2 (parser, "first 'extract' parameter %d too large for bit-width %d of argument", p->hi, width); exp = btor_slice_exp (parser->btor, p[1].exp, p->hi, p->lo); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_BVNOT_TAG_SMT2) { unaryfun = btor_not_exp; UNARY_BV_FUN: if (!btor_check_nargs_smt2 (parser, p->node->name, nargs, 1)) return 0; if (!btor_check_not_array_args_smt2 (parser, p, nargs)) return 0; exp = unaryfun (parser->btor, p[1].exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_BVAND_TAG_SMT2) { binfun = btor_and_exp; BINARY_BV_FUN: if (!btor_check_nargs_smt2 (parser, p->node->name, nargs, 2)) return 0; if (!btor_check_not_array_args_smt2 (parser, p, nargs)) return 0; exp = binfun (parser->btor, p[1].exp, p[2].exp); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_BVOR_TAG_SMT2) { binfun = btor_or_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVNEG_TAG_SMT2) { unaryfun = btor_neg_exp; goto UNARY_BV_FUN; } else if (tag == BTOR_BVADD_TAG_SMT2) { binfun = btor_add_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVMUL_TAG_SMT2) { binfun = btor_mul_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVUDIV_TAG_SMT2) { binfun = btor_udiv_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVUREM_TAG_SMT2) { binfun = btor_urem_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSHL_TAG_SMT2) { binfun = btor_shl_smt2; goto BINARY_BV_FUN; } else if (tag == BTOR_BVLSHR_TAG_SMT2) { binfun = btor_lshr_smt2; goto BINARY_BV_FUN; } else if (tag == BTOR_BVULT_TAG_SMT2) { binfun = btor_ult_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVNAND_TAG_SMT2) { binfun = btor_nand_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVNOR_TAG_SMT2) { binfun = btor_nor_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVXOR_TAG_SMT2) { binfun = btor_xor_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVXNOR_TAG_SMT2) { binfun = btor_xnor_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVCOMP_TAG_SMT2) { binfun = btor_eq_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSUB_TAG_SMT2) { binfun = btor_sub_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSDIV_TAG_SMT2) { binfun = btor_sdiv_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSREM_TAG_SMT2) { binfun = btor_srem_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSMOD_TAG_SMT2) { binfun = btor_smod_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVASHR_TAG_SMT2) { binfun = btor_ashr_smt2; goto BINARY_BV_FUN; } else if (tag == BTOR_REPEAT_TAG_SMT2) { if (!btor_check_nargs_smt2 (parser, p->node->name, nargs, 1)) return 0; if (!btor_check_not_array_args_smt2 (parser, p, nargs)) return 0; width = btor_get_exp_len (parser->btor, p[1].exp); if (p->num && ((INT_MAX / p->num) < width)) { parser->perrlineno = p->lineno; return !btor_perr_smt2 (parser, "resulting bit-width of 'repeat' too large"); } exp = btor_copy_exp (parser->btor, p[1].exp); for (i = 1; i < p->num; i++) { old = exp; exp = btor_concat_exp (parser->btor, old, p[1].exp); btor_release_exp (parser->btor, old); } goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_ZERO_EXTEND_TAG_SMT2) { extfun = btor_uext_exp; EXTEND_BV_FUN: if (!btor_check_nargs_smt2 (parser, p->node->name, nargs, 1)) return 0; if (!btor_check_not_array_args_smt2 (parser, p, nargs)) return 0; width = btor_get_exp_len (parser->btor, p[1].exp); if (INT_MAX - p->num < width) { parser->perrlineno = p->lineno; return !btor_perr_smt2 (parser, "resulting bit-width of '%s' too large", p->node->name); } exp = extfun (parser->btor, p[1].exp, p->num); goto RELEASE_EXP_AND_OVERWRITE; } else if (tag == BTOR_SIGN_EXTEND_TAG_SMT2) { extfun = btor_sext_exp; goto EXTEND_BV_FUN; } else if (tag == BTOR_ROTATE_LEFT_TAG_SMT2) { extfun = btor_rotate_left_smt2; goto EXTEND_BV_FUN; } else if (tag == BTOR_ROTATE_RIGHT_TAG_SMT2) { extfun = btor_rotate_right_smt2; goto EXTEND_BV_FUN; } else if (tag == BTOR_BVULE_TAG_SMT2) { binfun = btor_ulte_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVUGT_TAG_SMT2) { binfun = btor_ugt_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVUGE_TAG_SMT2) { binfun = btor_ugte_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSLT_TAG_SMT2) { binfun = btor_slt_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSLE_TAG_SMT2) { binfun = btor_slte_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSGT_TAG_SMT2) { binfun = btor_sgt_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_BVSGE_TAG_SMT2) { binfun = btor_sgte_exp; goto BINARY_BV_FUN; } else if (tag == BTOR_LET_TAG_SMT2) { BtorSMT2Node * s; assert (nargs >= 2); assert (p[nargs].tag == BTOR_EXP_TAG_SMT2); l[0].tag = BTOR_EXP_TAG_SMT2; l[0].exp= p[nargs].exp; for (i = 1; i < nargs; i++) { assert (p[i].tag == BTOR_SYMBOL_TAG_SMT2); s = p[i].node; assert (s); assert (s->lineno); assert (s->tag == BTOR_SYMBOL_TAG_SMT2); btor_remove_symbol_smt2 (parser, s); } parser->work.top = p; } else if (tag == BTOR_LETBIND_TAG_SMT2) { assert (nargs >= 2); assert (p[1].tag == BTOR_SYMBOL_TAG_SMT2); if (nargs == 1) { return !btor_perr_smt2 (parser, "term to be bound to '%s' missing", p[1].node->name); } if (nargs > 2) { return !btor_perr_smt2 (parser, "more than one term to be bound to '%s'", p[1].node->name); } l[0] = p[1]; assert (!l[0].node->exp); assert (p[2].tag == BTOR_EXP_TAG_SMT2); l[0].node->exp = p[2].exp; assert (!l[0].node->bound); l[0].node->bound = 1; parser->work.top = p; assert (!parser->binding); parser->binding = 1; } else if (tag == BTOR_PARLETBINDING_TAG_SMT2) { if (!nargs) return !btor_perr_smt2 (parser, "empty 'let' binding"); assert (parser->binding); parser->binding = 0; #ifndef NDEBUG for (i = 1; i <= nargs; i++) assert (p[i].tag == BTOR_SYMBOL_TAG_SMT2); #endif for (i = 0; i < nargs; i++) l[i] = p[i + 1]; parser->work.top = l + nargs; } else return !btor_perr_smt2 (parser, "internal parse error: can not close yet unsupported '%s'", btor_item2str_smt2 (p)); assert (open > 0); open--; } else { p = btor_push_item_smt2 (parser, tag); if (tag == BTOR_LPAR_TAG_SMT2) { if (parser->binding) { BtorSMT2Node * s; BtorSMT2Item * q; btor_push_item_smt2 (parser, BTOR_LETBIND_TAG_SMT2); parser->binding = 0; tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "expected symbol to be bound after '(' but reached end-of-file"); if (tag != BTOR_SYMBOL_TAG_SMT2) return !btor_perr_smt2 (parser, "expected symbol to be bound after '(' at '%s'", parser->token.start); s = parser->last_node; assert (s); if (s->lineno) return !btor_perr_smt2 (parser, "symbol '%s' to be bound already %s at line %d", s->name, s->bound ? "bound with 'let'" : "declared as function", s->lineno); s->lineno = parser->lineno; q = btor_push_item_smt2 (parser, BTOR_SYMBOL_TAG_SMT2); q->node = s; } open++; } else if (parser->binding) { return !btor_perr_smt2 (parser, "expected binding at '%s'", parser->token.start); } else if (btor_item_with_node_smt2 (p)) { p->node = parser->last_node; if (tag & BTOR_COMMAND_TAG_CLASS_SMT2) return !btor_perr_smt2 (parser, "unexpected command '%s'", p->node->name); if (tag & BTOR_KEYWORD_TAG_CLASS_SMT2) return !btor_perr_smt2 (parser, "unexpected keyword '%s'", p->node->name); if (tag & BTOR_LOGIC_TAG_CLASS_SMT2) return !btor_perr_smt2 (parser, "unexpected logic '%s'", p->node->name); if (tag & BTOR_RESERVED_TAG_CLASS_SMT2) { if (tag == BTOR_LET_TAG_SMT2) { if (!btor_read_lpar_smt2 (parser, " after 'let'")) return 0; btor_push_item_smt2 (parser, BTOR_LPAR_TAG_SMT2); open++, assert (open > 0); btor_push_item_smt2 (parser, BTOR_PARLETBINDING_TAG_SMT2); assert (!parser->binding); parser->binding = 1; } else if (tag == BTOR_UNDERSCORE_TAG_SMT2) { const char * read_rpar_msg = 0; BtorSMT2Node * node = 0; if (!btor_prev_item_was_lpar_smt2 (parser)) return 0; tag = btor_read_token_smt2 (parser); node = parser->last_node; if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '_'"); if (tag == BTOR_REPEAT_TAG_SMT2) { assert (node && tag == (int) node->tag); read_rpar_msg = " to close '(repeat'"; ONE_FIXED_NUM_PARAMETRIC: if (BTOR_COUNT_STACK (parser->work) < 3 || parser->work.top[-3].tag != BTOR_LPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "expected two '(' before '_ %s'", node->name); l = p - 1; if (!btor_parse_int32_smt2 (parser, 0, &l->num)) return 0; l->tag = tag; l->node = node; parser->work.top = p; if (!btor_read_rpar_smt2 (parser, read_rpar_msg)) return 0; assert (open > 0); open--; } else if (tag == BTOR_ZERO_EXTEND_TAG_SMT2) { read_rpar_msg = " to close 'zero_extend'"; goto ONE_FIXED_NUM_PARAMETRIC; } else if (tag == BTOR_SIGN_EXTEND_TAG_SMT2) { read_rpar_msg = " to close 'sign_extend'"; goto ONE_FIXED_NUM_PARAMETRIC; } else if (tag == BTOR_ROTATE_LEFT_TAG_SMT2) { read_rpar_msg = " to close 'rotate_left'"; goto ONE_FIXED_NUM_PARAMETRIC; } else if (tag == BTOR_ROTATE_RIGHT_TAG_SMT2) { read_rpar_msg = " to close 'rotate_right'"; goto ONE_FIXED_NUM_PARAMETRIC; } else if (tag == BTOR_EXTRACT_TAG_SMT2) { assert (node && tag == (int) node->tag); if (BTOR_COUNT_STACK (parser->work) < 3 || parser->work.top[-3].tag != BTOR_LPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "expected two '(' before '_ extract'"); l = p - 1; if (!btor_parse_int32_smt2 (parser, 0, &l->hi)) return 0; if (!btor_parse_int32_smt2 (parser, 0, &l->lo)) return 0; if (l->hi < l->lo) return !btor_perr_smt2 (parser, "first 'extract' parameter %d smaller than second %d", l->hi, l->lo); l->tag = tag; l->node = node; parser->work.top = p; if (!btor_read_rpar_smt2 (parser, " to close 'extract'")) return 0; assert (open > 0); open--; } else if (tag == BTOR_SYMBOL_TAG_SMT2 && btor_bvconst_str_smt2 (parser->token.start)) { char * constr; int len; exp = 0; constr = btor_decimal_to_const (parser->mem, parser->token.start + 2); if (!btor_parse_int32_smt2 (parser, 1, &width)) goto UNDERSCORE_DONE; len = (int) strlen (constr); if (len > width) { (void) btor_perr_smt2 (parser, "decimal constant '%s' needs %d bits which exceeds width %d", parser->token.start, len, width); } else if (len == width) exp = btor_const_exp (parser->btor, constr); else if (!len) exp = btor_zero_exp (parser->btor, width); else { char * uconstr = btor_uext_const (parser->mem, constr, width - len); exp = btor_const_exp (parser->btor, uconstr); btor_freestr (parser->mem, uconstr); } UNDERSCORE_DONE: btor_delete_const (parser->mem, constr); if (!exp) return 0; assert (btor_get_exp_len (parser->btor, exp) == width); assert (p > parser->work.start); p--, parser->work.top--; assert (p->tag == BTOR_LPAR_TAG_SMT2); assert (open > 0); open--; p->tag = BTOR_EXP_TAG_SMT2; p->exp = exp; if (!btor_read_rpar_smt2 (parser, "to close '(_'")) return 0; } else return !btor_perr_smt2 (parser, "invalid parametric term '_ %s'", parser->token.start); } else { assert (p->node->name); return !btor_perr_smt2 (parser, "unsupported reserved word '%s'", p->node->name); } } else if (tag == BTOR_SYMBOL_TAG_SMT2) { assert (p->node); if (!p->node->exp) return !btor_perr_smt2 (parser, "undefined symbol '%s'", p->node->name); p->tag = BTOR_EXP_TAG_SMT2; p->exp = btor_copy_exp (parser->btor, p->node->exp); } else if (tag == BTOR_TRUE_TAG_SMT2) { p->tag = BTOR_EXP_TAG_SMT2; p->exp = btor_true_exp (parser->btor); } else if (tag == BTOR_FALSE_TAG_SMT2) { p->tag = BTOR_EXP_TAG_SMT2; p->exp = btor_false_exp (parser->btor); } else if (tag == BTOR_ATTRIBUTE_TAG_SMT2) { return !btor_perr_smt2 (parser, "unexpected attribute '%s'", parser->token.start); } else if (tag & BTOR_CORE_TAG_CLASS_SMT2) { if (tag == BTOR_BOOL_TAG_SMT2) return !btor_perr_smt2 (parser, "unexpected 'Bool'"); } else if (tag & BTOR_ARRAY_TAG_CLASS_SMT2) { if (tag == BTOR_ARRAY_TAG_SMT2) return !btor_perr_smt2 (parser, "unexpected 'Array'"); } else if (tag & BTOR_BITVEC_TAG_CLASS_SMT2) { if (tag == BTOR_BITVEC_TAG_SMT2) return !btor_perr_smt2 (parser, "unexpected 'BitVec'"); } else return !btor_perr_smt2 (parser, "unexpected token '%s'", btor_item2str_smt2 (p)); } else if (tag == BTOR_BINARY_CONSTANT_TAG_SMT2) { p->tag = BTOR_EXP_TAG_SMT2; p->exp = btor_const_exp (parser->btor, parser->token.start + 2); } else if (tag == BTOR_HEXADECIMAL_CONSTANT_TAG_SMT2) { char * constr = btor_hex_to_const (parser->mem, parser->token.start + 2); int len = strlen (constr), width = strlen (parser->token.start+2)*4; char * uconstr; assert (len <= width); if (len == width) uconstr = constr; else uconstr = btor_uext_const (parser->mem, constr, width - len); p->tag = BTOR_EXP_TAG_SMT2; p->exp = btor_const_exp (parser->btor, uconstr); if (uconstr != constr) btor_delete_const (parser->mem, uconstr); btor_delete_const (parser->mem, constr); } else return !btor_perr_smt2 (parser, "unexpected token '%s'", parser->token.start); } } while (open); if (BTOR_COUNT_STACK (parser->work) != 1) { parser->perrlineno = p->lineno; // This should not occur, but we keep it as a bad style of // defensive programming for future extensions of the parser. return !btor_perr_smt2 (parser, "internal parse error: worker stack of size %d", BTOR_COUNT_STACK (parser->work)); } p = parser->work.start; if (p->tag != BTOR_EXP_TAG_SMT2) { parser->perrlineno = p->lineno; // Dito, same comment wrt defensive programming an future use. return !btor_perr_smt2 (parser, "internal parse error: failed to translate parsed term at '%s'", btor_item2str_smt2 (p)); } res = btor_copy_exp (parser->btor, p->exp); *linenoptr = p->lineno; btor_release_work_smt2 (parser); *resptr = res; return 1; } static int btor_parse_bitvec_sort_smt2 (BtorSMT2Parser * parser, int skiplu, int * resptr) { int tag, res; if (!skiplu) { if (!btor_read_lpar_smt2 (parser, 0)) return 0; tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "expected '_' but reached end-of-file"); if (tag != BTOR_UNDERSCORE_TAG_SMT2) return !btor_perr_smt2 (parser, "expected '_' at '%s'", parser->token.start); } tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "expected 'BitVec' but reached end-of-file"); if (tag != BTOR_BITVEC_TAG_SMT2) return !btor_perr_smt2 (parser, "expected 'BitVec' at '%s'", parser->token.start); tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "expected bit-width but reached end-of-file"); if (tag != BTOR_DECIMAL_CONSTANT_TAG_SMT2) return !btor_perr_smt2 (parser, "expected bit-width at '%s'", parser->token.start); assert (parser->token.start[0] != '-'); if (parser->token.start[0] == '0') { assert (!parser->token.start[1]); return !btor_perr_smt2 (parser, "invalid zero bit-width"); } if (strchr (parser->token.start, '.')) return !btor_perr_smt2 (parser, "invalid floating point bit-width '%s'", parser->token.start); res = 0; if (!btor_str2int32_smt2 (parser, 1, parser->token.start, &res)) return 0; *resptr = res; btor_msg_smt2 (parser, 3, "parsed bit-vector sort of width %d", res); return btor_read_rpar_smt2 (parser, " to close bit-vector sort"); } static int btor_declare_fun_smt2 (BtorSMT2Parser * parser) { int tag, domain, width; BtorSMT2Node * fun; fun = 0; width = domain = 0; if (!btor_read_symbol (parser, " after 'declare-fun'", &fun)) return 0; assert (fun && fun->tag == BTOR_SYMBOL_TAG_SMT2); if (fun->lineno) return !btor_perr_smt2 (parser, "symbol '%s' already defined at line %d", fun->name, fun->lineno); fun->lineno = parser->lineno; if (!btor_read_lpar_smt2 (parser, " after function name")) return 0; if (!btor_read_rpar_smt2 (parser, " after '('")) return 0; tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "reached end-of-file expecting '(' or 'Bool'"); if (tag == BTOR_BOOL_TAG_SMT2) { width = 1; goto BITVEC; } else if (tag != BTOR_LPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "expected '(' or 'Bool' at '%s'", parser->token.start); tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "reached end-of-file expecting '_' or 'Array'"); if (tag == BTOR_UNDERSCORE_TAG_SMT2) { if (!btor_parse_bitvec_sort_smt2 (parser, 1, &width)) return 0; BITVEC: fun->exp = btor_var_exp (parser->btor, width, fun->name); btor_msg_smt2 (parser, 2, "declared '%s' as bit-vector of width %d at line %d", fun->name, width, fun->lineno); } else if (tag == BTOR_ARRAY_TAG_SMT2) { if (parser->commands.set_logic && parser->res->logic == BTOR_LOGIC_QF_BV) return !btor_perr_smt2 (parser, "'Array' invalid for logic 'QF_BV'"); if (!btor_parse_bitvec_sort_smt2 (parser, 0, &domain)) return 0; if (!btor_parse_bitvec_sort_smt2 (parser, 0, &width)) return 0; if (!btor_read_rpar_smt2 (parser, " after element sort")) return 0; fun->exp = btor_array_exp (parser->btor, width, domain, fun->name); btor_msg_smt2 (parser, 2, "declared bit-vector array '%s' index element width %d %d at line %d", fun->name, domain, width, fun->lineno); parser->need_arrays = 1; } else return !btor_perr_smt2 (parser, "expected '_' or 'Array' at '%s'", parser->token.start); (void) btor_copy_exp (parser->btor, fun->exp); BTOR_PUSH_STACK (parser->mem, parser->inputs, fun->exp); return btor_read_rpar_smt2 (parser, " for closing declaration"); } static int btor_set_info_smt2 (BtorSMT2Parser * parser) { int tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after 'set-info'"); if (tag == BTOR_RPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "keyword after 'set-info' missing"); if (tag == BTOR_STATUS_TAG_SMT2) { tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after ':status'"); if (tag == BTOR_RPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "value after ':status' missing"); if (tag != BTOR_SYMBOL_TAG_SMT2) INVALID_STATUS_VALUE: return !btor_perr_smt2 (parser, "invalid value '%s' after ':status'", parser->token.start); if (!strcmp (parser->token.start, "sat")) parser->res->status = BTOR_PARSE_SAT_STATUS_SAT; else if (!strcmp (parser->token.start, "unsat")) parser->res->status = BTOR_PARSE_SAT_STATUS_UNSAT; else if (!strcmp (parser->token.start, "unknown")) parser->res->status = BTOR_PARSE_SAT_STATUS_UNKNOWN; else goto INVALID_STATUS_VALUE; btor_msg_smt2 (parser, 2, "parsed status '%s'", parser->token.start); return btor_read_rpar_smt2 (parser, " after 'set-logic'"); } return btor_skip_sexprs (parser, 1); } static int btor_read_command_smt2 (BtorSMT2Parser * parser) { int tag, lineno = 0; BtorNode * exp = 0; tag = btor_read_token_smt2 (parser); if (tag == EOF || tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag != BTOR_LPAR_TAG_SMT2) return !btor_perr_smt2 (parser, "expected '(' at '%s'", parser->token.start); tag = btor_read_token_smt2 (parser); if (tag == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after '('"); if (tag == BTOR_INVALID_TAG_SMT2) { assert (parser->error); return 0; } if (!(tag & BTOR_COMMAND_TAG_CLASS_SMT2)) return !btor_perr_smt2 (parser, "expected command at '%s'", parser->token.start); switch (tag) { case BTOR_SET_LOGIC_TAG_SMT2: if (parser->commands.all) btor_msg_smt2 (parser, 0, "WARNING 'set-logic' not first command in '%s'", parser->name); tag = btor_read_token_smt2 (parser); if (tag == EOF) return !btor_perr_smt2 (parser, "unexpected end-of-file after 'set-logic'"); if (tag == BTOR_INVALID_TAG_SMT2) { assert (parser->error); return 0; } if (!(tag & BTOR_LOGIC_TAG_CLASS_SMT2)) return !btor_perr_smt2 (parser, "unsupported logic '%s'", parser->token.start); if (tag == BTOR_QF_BV_TAG_SMT2) parser->res->logic = BTOR_LOGIC_QF_BV; else { assert (tag == BTOR_QF_AUFBV_TAG_SMT2 || tag == BTOR_QF_UFBV_TAG_SMT2 || tag == BTOR_QF_ABV_TAG_SMT2); parser->res->logic = BTOR_LOGIC_QF_AUFBV; } btor_msg_smt2 (parser, 2, "logic %s", parser->token.start); if (!btor_read_rpar_smt2 (parser, " after logic")) return 0; if (parser->commands.set_logic++) btor_msg_smt2 (parser, 0, "WARNING additional 'set-logic' command"); break; case BTOR_CHECK_SAT_TAG_SMT2: if (!btor_read_rpar_smt2 (parser, " after 'check-sat'")) return 0; if (parser->commands.check_sat++) btor_msg_smt2 (parser, 0, "WARNING additional 'check-sat' command"); break; case BTOR_DECLARE_FUN_TAG_SMT2: if (!btor_declare_fun_smt2 (parser)) return 0; break; case BTOR_ASSERT_TAG_SMT2: if (!btor_parse_term_smt2 (parser, &exp, &lineno)) return 0; BTOR_PUSH_STACK (parser->mem, parser->outputs, exp); if (btor_is_array_exp (parser->btor, exp)) { parser->perrlineno = lineno; return !btor_perr_smt2 (parser, "assert argument is an array and not a formula"); } if (btor_get_exp_len (parser->btor, exp) != 1) { parser->perrlineno = lineno; return !btor_perr_smt2 (parser, "assert argument is a bit-vector of length %d", btor_get_exp_len (parser->btor, exp)); } if (!btor_read_rpar_smt2 (parser, " after assert term")) return 0; assert (!parser->error); parser->commands.asserts++; break; case BTOR_EXIT_TAG_SMT2: if (!btor_read_rpar_smt2 (parser, " after 'exit'")) return 0; assert (!parser->commands.exits); parser->commands.exits++; tag = btor_read_token_smt2 (parser); if (tag == BTOR_INVALID_TAG_SMT2) return 0; if (tag != EOF) return !btor_perr_smt2 (parser, "expected end-of-file after 'exit' command at '%s'", parser->token.start); goto DONE; break; case BTOR_SET_INFO_TAG_SMT2: if (!btor_set_info_smt2 (parser)) return 0; break; default: return !btor_perr_smt2 (parser, "unsupported command '%s'", parser->token.start); break; } DONE: parser->commands.all++; return 1; } static const char * btor_parse_smt2_parser (BtorSMT2Parser * parser, BtorCharStack * prefix, FILE * file, const char * name, BtorParseResult * res) { double start = btor_time_stamp (), delta; parser->name = btor_strdup (parser->mem, name); parser->nprefix = 0; parser->prefix = prefix; parser->lineno = 1; parser->file = file; parser->saved = 0; BTOR_CLR (res); parser->res = res; while (btor_read_command_smt2 (parser)) ; if (parser->error) return parser->error; if (!parser->commands.all) btor_msg_smt2 (parser, 0, "WARNING no commands in in '%s'", parser->name); else { if (!parser->commands.set_logic) btor_msg_smt2 (parser, 0, "WARNING 'set-logic' command missing in '%s'", parser->name); if (!parser->commands.asserts) btor_msg_smt2 (parser, 0, "WARNING no 'assert' command in '%s'", parser->name); if (!parser->commands.check_sat) btor_msg_smt2 (parser, 0, "WARNING 'check-sat' command missing in '%s'", parser->name); if (!parser->commands.exits) btor_msg_smt2 (parser, 0, "WARNING no 'exit' command at end of '%s'", parser->name); } parser->res->inputs = parser->inputs.start; parser->res->outputs = parser->outputs.start; parser->res->ninputs = BTOR_COUNT_STACK (parser->inputs); parser->res->noutputs = BTOR_COUNT_STACK (parser->outputs); delta = btor_time_stamp () - start; if (delta < 0) delta = 0; btor_msg_smt2 (parser, 1, "parsed %d commands in %.2f seconds", parser->commands.all, delta); if (parser->commands.set_logic) { assert (!parser->need_arrays || parser->res->logic == BTOR_LOGIC_QF_AUFBV); if (!parser->need_arrays && parser->res->logic == BTOR_LOGIC_QF_AUFBV) { btor_msg_smt2 (parser, 1, "no arrays found thus restricting logic to 'QF_BV'"); parser->res->logic = BTOR_LOGIC_QF_BV; } } else if (parser->need_arrays) { btor_msg_smt2 (parser, 1, "found arrays thus using 'QF_AUFBV' logic"); assert (parser->res->logic == BTOR_LOGIC_QF_BV); parser->res->logic = BTOR_LOGIC_QF_AUFBV; } return 0; } static BtorParserAPI static_btor_smt2_parser_api = { (BtorInitParser) btor_new_smt2_parser, (BtorResetParser) btor_delete_smt2_parser, (BtorParse) btor_parse_smt2_parser }; const BtorParserAPI * btor_smt2_parser_api () { return &static_btor_smt2_parser_api; } boolector-1.5.118-6b56be4-121013/btorlogic.h0000664000175000017500000000070611761140525016561 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTORLOGIC_H_INCLUDED #define BTORLOGIC_H_INCLUDED enum BtorLogic { BTOR_LOGIC_QF_BV = 0, BTOR_LOGIC_QF_AUFBV, }; typedef enum BtorLogic BtorLogic; #endif boolector-1.5.118-6b56be4-121013/makefile.in0000664000175000017500000000223012036253615016524 0ustar bierebiere.SUFFIXES: .o .c .cc .c.o: $(CC) $(CFLAGS) -c $< .cc.o: $(CC) $(CFLAGS) -c $< MAKEFLAGS=-j $(if $(CORES),$(CORES),1) CC=@CC@ INCS=@INCS@ CFLAGS=@CFLAGS@ OBJS=@OBJS@ LIBS=@LIBS@ LDEPS=@LDEPS@ VERSION=$(shell cat VERSION) LIBOBJ= $(addsuffix .o,$(basename $(wildcard btor*.c))) boolector.o $(OBJS) SRC=$(shell ls *.c *.h *.cc) all: libboolector.a boolector synthebtor deltabtor -include dependencies analyze: clang --analyze $(CFLAGS) $(SRC) dependencies: btorconfig.h $(SRC) makefile rm -f $@; $(CC) $(CFLAGS) -MM *.c|sed -e 's,:,: makefile,'>$@ boolector: boolectormain.o libboolector.a $(LDEPS) $(CC) $(CFLAGS) -o $@ boolectormain.o -L. -lboolector $(LIBS) synthebtor: synthebtor.o libboolector.a $(LDEPS) $(CC) $(CFLAGS) -o $@ synthebtor.o -L. -lboolector $(LIBS) deltabtor: deltabtor.c makefile $(LDEPS) $(CC) $(CFLAGS) -o $@ deltabtor.c libboolector.a: $(LIBOBJ) rm -f $@ ar rc $@ $(LIBOBJ) ranlib $@ btorconfig.h: makefile VERSION mkconfig rm -f $@; ./mkconfig > $@ clean: rm -f boolector deltabtor synthebtor rm -f dependencies makefile btorconfig.h rm -f *.gcda *.gcno *.gcov *.gch *.plist rm -f log/*.log *.tmp rm -f *.o *.a .PHONY: all analyze clean boolector-1.5.118-6b56be4-121013/btormem.h0000664000175000017500000000442111761140525016240 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTORMEM_H_INCLUDED #define BTORMEM_H_INCLUDED #include #include #include /*------------------------------------------------------------------------*/ #define BTOR_NEWN(mm,ptr,nelems) \ do { (ptr) = btor_malloc ((mm), (nelems) * sizeof *(ptr)); } while (0) #define BTOR_CNEWN(mm,ptr,nelems) \ do { (ptr) = btor_calloc ((mm), (nelems), sizeof *(ptr)); } while (0) #define BTOR_CLRN(ptr,nelems) \ do { memset ((ptr), 0, (nelems) * sizeof *(ptr)); } while (0) #define BTOR_DELETEN(mm,ptr,nelems) \ do { btor_free ((mm), (ptr), (nelems) * sizeof *(ptr)); } while (0) #define BTOR_REALLOC(mm,p,o,n) \ do { \ (p) = btor_realloc ((mm),(p),((o)*sizeof*(p)),((n)*sizeof*(p))); \ } while (0) #define BTOR_NEW(mm,ptr) BTOR_NEWN((mm),(ptr),1) #define BTOR_CNEW(mm,ptr) BTOR_CNEWN((mm),(ptr),1) #define BTOR_CLR(ptr) BTOR_CLRN((ptr),1) #define BTOR_DELETE(mm,ptr) BTOR_DELETEN((mm),(ptr),1) #define BTOR_ENLARGE(mm,p,o,n) \ do { \ int internaln = (o) ? 2 * (o) : 1; \ BTOR_REALLOC ((mm),(p),(o),internaln); \ (n) = internaln; \ } while (0) /*------------------------------------------------------------------------*/ struct BtorMemMgr { size_t allocated; size_t maxallocated; }; typedef struct BtorMemMgr BtorMemMgr; /*------------------------------------------------------------------------*/ BtorMemMgr *btor_new_mem_mgr (void); void *btor_malloc (BtorMemMgr * mm, size_t size); void *btor_realloc (BtorMemMgr * mm, void *, size_t oldsz, size_t newsz); void *btor_calloc (BtorMemMgr * mm, size_t nobj, size_t size); void btor_free (BtorMemMgr * mm, void *p, size_t freed); char *btor_strdup (BtorMemMgr * mm, const char *str); void btor_freestr (BtorMemMgr * mm, char *str); void btor_delete_mem_mgr (BtorMemMgr * mm); size_t btor_parse_error_message_length (const char * name, const char * fmt, va_list ap); char * btor_parse_error_message (BtorMemMgr *, const char * name, int lineno, const char * fmt, va_list, size_t bytes); #endif boolector-1.5.118-6b56be4-121013/btorutil.c0000664000175000017500000000360611761140525016436 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btorutil.h" #include #include /*------------------------------------------------------------------------*/ int btor_is_power_of_2_util (int x) { assert (x > 0); return (x & (x - 1)) == 0; } int btor_log_2_util (int x) { int result = 0; assert (x > 0); assert (btor_is_power_of_2_util (x)); while (x > 1) { x >>= 1; result++; } assert (result >= 0); return result; } int btor_pow_2_util (int x) { int result = 1; assert (x >= 0); while (x > 0) { assert (result <= INT_MAX / 2); result <<= 1; x--; } assert (result > 0); return result; } int btor_next_power_of_2_util (int x) { int i; assert (x > 0); x--; for (i = 1; i < (int) sizeof(int) * 8; i *= 2) x = x | (x >> i); return x + 1; } int btor_num_digits_util (int x) { int result; assert (x >= 0); result = 0; do { x /= 10; result++; } while (x > 0); return result; } #ifdef BTOR_HAVE_GETRUSAGE #include #include #include double btor_time_stamp (void) { double res = -1; struct rusage u; res = 0; if (!getrusage (RUSAGE_SELF, &u)) { res += u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec; res += u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec; } return res; } #endif #define BTOR_HAVE_STAT #ifdef BTOR_HAVE_STAT #include #include #include int btor_file_exists (const char * path) { struct stat buf; return !stat (path, &buf); } #else int btor_file_exists (const char * path) { (void) path; return -1; } #endif boolector-1.5.118-6b56be4-121013/btorrewrite.c0000664000175000017500000032715412024635403017146 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btorrewrite.h" #include "btorconst.h" #include "btormem.h" #include "btorutil.h" #include /*------------------------------------------------------------------------*/ /* recursive rewriting bound */ #define BTOR_REC_RW_BOUND (1<<12) /* iterative rewriting bounds */ #define BTOR_WRITE_CHAIN_NODE_RW_BOUND (1<<5) #define BTOR_READ_OVER_WRITE_DOWN_PROPAGATION_LIMIT (1<<11) /* other rewriting bounds */ #define BTOR_FIND_AND_NODE_CONTRADICTION_LIMIT (1<<4) #define BTOR_INC_REC_RW_CALL(btor) \ do { \ (btor)->rec_rw_calls++; \ if ((btor)->rec_rw_calls > (btor)->stats.max_rec_rw_calls) \ (btor)->stats.max_rec_rw_calls = (btor)->rec_rw_calls; \ } while (0) #define BTOR_DEC_REC_RW_CALL(btor) \ do { \ assert ((btor)->rec_rw_calls > 0); \ (btor)->rec_rw_calls--; \ } while (0) /*------------------------------------------------------------------------*/ static int is_const_one_exp (Btor * btor, BtorNode * exp) { int result; BtorNode *real_exp; assert (btor); assert (exp); exp = btor_pointer_chase_simplified_exp (btor, exp); if (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (exp))) return 0; real_exp = BTOR_REAL_ADDR_NODE (exp); if (BTOR_IS_INVERTED_NODE (exp)) btor_invert_const (btor->mm, real_exp->bits); result = btor_is_special_const (real_exp->bits) == BTOR_SPECIAL_CONST_ONE; if (BTOR_IS_INVERTED_NODE (exp)) btor_invert_const (btor->mm, real_exp->bits); return result; } static int is_const_zero_exp (Btor * btor, BtorNode * exp) { int result; BtorNode *real_exp; assert (btor); assert (exp); exp = btor_pointer_chase_simplified_exp (btor, exp); if (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (exp))) return 0; if (BTOR_IS_INVERTED_NODE (exp)) { real_exp = BTOR_REAL_ADDR_NODE (exp); result = btor_is_ones_const (real_exp->bits); } else result = btor_is_zero_const (exp->bits); return result; } static int is_const_ones_exp (Btor * btor, BtorNode * exp) { int result; BtorNode *real_exp; assert (btor); assert (exp); exp = btor_pointer_chase_simplified_exp (btor, exp); if (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (exp))) return 0; if (BTOR_IS_INVERTED_NODE (exp)) { real_exp = BTOR_REAL_ADDR_NODE (exp); result = btor_is_zero_const (real_exp->bits); } else result = btor_is_ones_const (exp->bits); return result; } static int is_xor_exp (Btor * btor, BtorNode *exp) { BtorNode *e0, *e1, *e0_0, *e0_1, *e1_0, *e1_1; assert (btor); assert (exp); exp = btor_pointer_chase_simplified_exp (btor, exp); (void) btor; if (BTOR_REAL_ADDR_NODE (exp)->kind != BTOR_AND_NODE) return 0; e0 = BTOR_REAL_ADDR_NODE (exp)->e[0]; if (!(BTOR_IS_INVERTED_NODE (e0) && BTOR_REAL_ADDR_NODE (e0)->kind == BTOR_AND_NODE)) return 0; e1 = BTOR_REAL_ADDR_NODE (exp)->e[1]; if (!(BTOR_IS_INVERTED_NODE (e1) && BTOR_REAL_ADDR_NODE (e1)->kind == BTOR_AND_NODE)) return 0; e0_0 = BTOR_REAL_ADDR_NODE (e0)->e[0]; e0_1 = BTOR_REAL_ADDR_NODE (e0)->e[1]; e1_0 = BTOR_REAL_ADDR_NODE (e1)->e[0]; e1_1 = BTOR_REAL_ADDR_NODE (e1)->e[1]; /* we assume that the children of commutative operators are sorted by id */ /* are children of e0 the same children as of e1 (ignoring sign) ? */ /* if not we terminate with false */ if (BTOR_REAL_ADDR_NODE (e0_0) != BTOR_REAL_ADDR_NODE (e1_0)) return 0; if (BTOR_REAL_ADDR_NODE (e0_1) != BTOR_REAL_ADDR_NODE (e1_1)) return 0; /* we check for two cases */ /* first case: !(!a && !b) && !(a && b) */ if (!BTOR_IS_INVERTED_NODE (exp)) { if (BTOR_IS_INVERTED_NODE (e0_0) == BTOR_IS_INVERTED_NODE (e0_1) && BTOR_IS_INVERTED_NODE (e1_0) == BTOR_IS_INVERTED_NODE (e1_1) && BTOR_IS_INVERTED_NODE (e0_0) != BTOR_IS_INVERTED_NODE (e1_0)) return 1; } /* second case: !((!a && b) && !(a && !b)) */ else { if (BTOR_IS_INVERTED_NODE (e0_0) != BTOR_IS_INVERTED_NODE (e1_0) && BTOR_IS_INVERTED_NODE (e0_1) != BTOR_IS_INVERTED_NODE (e1_1) && BTOR_IS_INVERTED_NODE (e0_0) != BTOR_IS_INVERTED_NODE (e0_1)) return 1; } return 0; } static int is_xnor_exp (Btor * btor, BtorNode *exp) { assert (btor); assert (exp); exp = btor_pointer_chase_simplified_exp (btor, exp); return is_xor_exp (btor, BTOR_INVERT_NODE (exp)); } static int btor_slice_simplifiable (BtorNode * exp) { BtorNode * real_exp = BTOR_REAL_ADDR_NODE (exp); switch (real_exp->kind) { case BTOR_BV_VAR_NODE: case BTOR_BV_CONST_NODE: case BTOR_SLICE_NODE: return 1; } return 0; } BtorNode * btor_rewrite_slice_exp (Btor * btor, BtorNode * exp, int upper, int lower) { BtorNode *result, *tmp, *real_exp, * left, * right, * t, * e; BtorMemMgr *mm; char *bits = 0; int len; exp = btor_pointer_chase_simplified_exp (btor, exp); assert (btor_precond_slice_exp_dbg (btor, exp, upper, lower)); assert (btor->rewrite_level > 0); mm = btor->mm; result = 0; real_exp = BTOR_REAL_ADDR_NODE (exp); len = real_exp->len; if (len == upper - lower + 1) /* handles result->len == 1 */ result = btor_copy_exp (btor, exp); else if (BTOR_IS_BV_CONST_NODE (real_exp)) { bits = btor_slice_const (mm, real_exp->bits, upper, lower); result = btor_const_exp (btor, bits); result = BTOR_COND_INVERT_NODE (exp, result); btor_delete_const (mm, bits); } else if (real_exp->kind == BTOR_SLICE_NODE) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_SLICE_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_slice_exp (btor, BTOR_COND_INVERT_NODE (exp, real_exp->e[0]), real_exp->lower + upper, real_exp->lower + lower); BTOR_DEC_REC_RW_CALL (btor); } /* check if slice and child of concat matches */ else if (real_exp->kind == BTOR_CONCAT_NODE) { if (lower == 0 && BTOR_REAL_ADDR_NODE (real_exp->e[1])->len == upper - lower + 1) { if (BTOR_IS_INVERTED_NODE (exp)) result = BTOR_INVERT_NODE (btor_copy_exp (btor, real_exp->e[1])); else result = btor_copy_exp (btor, real_exp->e[1]); } else if (btor->rewrite_level < 3) { /* we look just one level down */ if (upper == len - 1 && BTOR_REAL_ADDR_NODE (real_exp->e[0])->len == upper - lower + 1) { if (BTOR_IS_INVERTED_NODE (exp)) result = BTOR_INVERT_NODE (btor_copy_exp (btor, real_exp->e[0])); else result = btor_copy_exp (btor, real_exp->e[0]); } } else { assert (btor->rewrite_level >= 3); /* concats are normalized at rewrite level 3 */ /* we recursively check if slice and child of concat matches */ len = BTOR_REAL_ADDR_NODE (real_exp->e[1])->len; if (lower >= len) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_SLICE_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_slice_exp (btor, BTOR_COND_INVERT_NODE (exp, real_exp->e[0]), upper - len, lower - len); BTOR_DEC_REC_RW_CALL (btor); } else if (upper < len) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_SLICE_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_slice_exp (btor, BTOR_COND_INVERT_NODE (exp, real_exp->e[1]), upper, lower); BTOR_DEC_REC_RW_CALL (btor); } else if (lower == 0) { assert (upper >= len); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_SLICE_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp = btor_rewrite_slice_exp (btor, BTOR_COND_INVERT_NODE (exp, real_exp->e[0]), upper - len, 0); result = btor_rewrite_concat_exp (btor, tmp, BTOR_COND_INVERT_NODE (exp, real_exp->e[1])); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp); } } } else if (btor->rewrite_level >= 3 && real_exp->kind == BTOR_AND_NODE && (btor_slice_simplifiable (real_exp->e[0]) || btor_slice_simplifiable (real_exp->e[1]))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_SLICE_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_slice_exp (btor, real_exp->e[0], upper, lower); right = btor_slice_exp (btor, real_exp->e[1], upper, lower); result = btor_and_exp (btor, left, right); btor_release_exp (btor, right); btor_release_exp (btor, left); if (BTOR_IS_INVERTED_NODE (exp)) result = BTOR_INVERT_NODE (result); BTOR_DEC_REC_RW_CALL (btor); } else if (btor->rewrite_level >= 3 && real_exp->kind == BTOR_BCOND_NODE && (btor_slice_simplifiable (real_exp->e[1]) || btor_slice_simplifiable (real_exp->e[2]))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_SLICE_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); t = btor_slice_exp (btor, real_exp->e[1], upper, lower); e = btor_slice_exp (btor, real_exp->e[2], upper, lower); result = btor_cond_exp (btor, real_exp->e[0], t, e); btor_release_exp (btor, e); btor_release_exp (btor, t); if (BTOR_IS_INVERTED_NODE (exp)) result = BTOR_INVERT_NODE (result); BTOR_DEC_REC_RW_CALL (btor); } if (!result) { BTOR_REWRITE_SLICE_NODE_NO_REWRITE: result = btor_slice_exp_node (btor, exp, upper, lower); } return result; } static BtorNode * rewrite_binary_exp (Btor * btor, BtorNodeKind kind, BtorNode * e0, BtorNode * e1) { BtorMemMgr *mm; BtorNode *result, *real_e0, *real_e1, *tmp1, *tmp2, *tmp3; BtorNode *tmp4, *eq, *left, *right; BtorNode *(*fptr) (Btor *, BtorNode *, BtorNode *); char *b0, *b1, *bresult; int same_children_mem; int invert_b0 = 0; int invert_b1 = 0; BtorSpecialConst sc; BtorNodePtrStack stack; char *bv_const; char tmpString[2] = { '\0', '\0'}; int pos, len; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor); assert (btor->rewrite_level > 0); assert (BTOR_IS_BINARY_NODE_KIND (kind)); assert (e0); assert (e1); mm = btor->mm; result = 0; real_e0 = BTOR_REAL_ADDR_NODE (e0); real_e1 = BTOR_REAL_ADDR_NODE (e1); if (!real_e0 || !real_e1) abort (); // make static anlayzer happy if (BTOR_IS_BV_CONST_NODE (real_e0) && BTOR_IS_BV_CONST_NODE (real_e1)) { same_children_mem = real_e0 == real_e1; if (same_children_mem) { b0 = BTOR_BITS_NODE (mm, e0); b1 = BTOR_BITS_NODE (mm, e1); } else { invert_b0 = BTOR_IS_INVERTED_NODE (e0); b0 = real_e0->bits; if (invert_b0) btor_invert_const (mm, b0); invert_b1 = BTOR_IS_INVERTED_NODE (e1); b1 = real_e1->bits; if (invert_b1) btor_invert_const (mm, b1); } switch (kind) { case BTOR_AND_NODE: bresult = btor_and_const (mm, b0, b1); break; case BTOR_BEQ_NODE: bresult = btor_eq_const (mm, b0, b1); break; case BTOR_ADD_NODE: bresult = btor_add_const (mm, b0, b1); break; case BTOR_MUL_NODE: bresult = btor_mul_const (mm, b0, b1); break; case BTOR_ULT_NODE: bresult = btor_ult_const (mm, b0, b1); break; case BTOR_UDIV_NODE: bresult = btor_udiv_const (mm, b0, b1); break; case BTOR_UREM_NODE: bresult = btor_urem_const (mm, b0, b1); break; case BTOR_SLL_NODE: bresult = btor_sll_const (mm, b0, b1); break; case BTOR_SRL_NODE: bresult = btor_srl_const (mm, b0, b1); break; default: assert (kind == BTOR_CONCAT_NODE); bresult = btor_concat_const (mm, b0, b1); break; } if (same_children_mem) { btor_delete_const (mm, b1); btor_delete_const (mm, b0); } else { /* invert back if necessary */ if (invert_b0) btor_invert_const (mm, b0); if (invert_b1) btor_invert_const (mm, b1); } result = btor_const_exp (btor, bresult); btor_delete_const (mm, bresult); } else if (BTOR_IS_BV_CONST_NODE (real_e0) && !BTOR_IS_BV_CONST_NODE (real_e1)) { invert_b0 = BTOR_IS_INVERTED_NODE (e0); b0 = real_e0->bits; if (invert_b0) btor_invert_const (mm, b0); sc = btor_is_special_const (b0); /* invert back if necessary */ if (invert_b0) btor_invert_const (mm, b0); switch (sc) { case BTOR_SPECIAL_CONST_ZERO: switch (kind) { case BTOR_BEQ_NODE: if (real_e0->len == 1) result = btor_not_exp (btor, e1); else if (is_xor_exp (btor, e1)) /* 0 == (a ^ b) --> a = b */ { if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e1)->e[0])->e[0]), BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e1)->e[0])->e[1])); BTOR_DEC_REC_RW_CALL (btor); } } else if (BTOR_IS_INVERTED_NODE (e1) && real_e1->kind == BTOR_AND_NODE) { /* 0 == a | b --> a == 0 && b == 0 */ if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e1->e[0]), e0); right = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e1->e[1]), e0); result = btor_rewrite_and_exp (btor, left, right); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); btor_release_exp (btor, right); } } break; case BTOR_ULT_NODE: /* 0 < a --> a != 0 */ result = BTOR_INVERT_NODE (btor_rewrite_eq_exp (btor, e0, e1)); break; case BTOR_ADD_NODE: result = btor_copy_exp (btor, e1); break; case BTOR_MUL_NODE: case BTOR_SLL_NODE: case BTOR_SRL_NODE: case BTOR_UREM_NODE: case BTOR_AND_NODE: result = btor_zero_exp (btor, real_e0->len); break; case BTOR_UDIV_NODE: tmp2 = btor_zero_exp (btor, real_e0->len); tmp4 = btor_ones_exp (btor, real_e0->len); eq = btor_rewrite_eq_exp (btor, e1, tmp2); result = btor_rewrite_cond_exp (btor, eq, tmp4, tmp2); btor_release_exp (btor, tmp2); btor_release_exp (btor, eq); btor_release_exp (btor, tmp4); break; default: break; } break; case BTOR_SPECIAL_CONST_ONE_ONES: assert (real_e0->len == 1); if (kind == BTOR_AND_NODE || kind == BTOR_BEQ_NODE || kind == BTOR_MUL_NODE) result = btor_copy_exp (btor, e1); else if (kind == BTOR_ULT_NODE) result = btor_false_exp (btor); break; case BTOR_SPECIAL_CONST_ONE: if (kind == BTOR_MUL_NODE) result = btor_copy_exp (btor, e1); break; case BTOR_SPECIAL_CONST_ONES: if (kind == BTOR_BEQ_NODE) { if (is_xnor_exp (btor, e1)) /* 1+ == (a XNOR b) --> a = b */ { if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e1)->e[0])->e[0]), BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e1)->e[0])->e[1])); BTOR_DEC_REC_RW_CALL (btor); } } else if (!BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_AND_NODE) { /* 1+ == a & b --> a == 1+ && b == 1+ */ if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_eq_exp (btor, e1->e[0], e0); right = btor_rewrite_eq_exp (btor, e1->e[1], e0); result = btor_rewrite_and_exp (btor, left, right); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); btor_release_exp (btor, right); } } } else if (kind == BTOR_AND_NODE) result = btor_copy_exp (btor, e1); else if (kind == BTOR_ULT_NODE) /* UNSIGNED_MAX < x */ result = btor_false_exp (btor); break; default: assert (sc == BTOR_SPECIAL_CONST_NONE); if (kind == BTOR_BEQ_NODE && real_e1->kind == BTOR_AND_NODE && btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); BTOR_INIT_STACK (stack); if (BTOR_IS_INVERTED_NODE (e0)) bv_const = btor_not_const (btor->mm, real_e0->bits); else bv_const = btor_copy_const (btor->mm, real_e0->bits); pos = 0; /* const == a | b */ if (BTOR_IS_INVERTED_NODE (e1)) { while (pos < real_e0->len) { tmpString[0] = bv_const[pos]; len = (int) strspn (bv_const + pos, tmpString); tmp1 = btor_rewrite_slice_exp (btor, BTOR_INVERT_NODE (real_e1->e[0]), real_e0->len - 1 - pos, real_e0->len - pos - len); tmp2 = btor_rewrite_slice_exp (btor, BTOR_INVERT_NODE (real_e1->e[1]), real_e0->len - 1 - pos, real_e0->len - pos - len); if (tmpString[0] == '0') { tmp3 = btor_zero_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp1, tmp3)); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp2, tmp3)); btor_release_exp (btor, tmp3); } else { assert (tmpString[0] == '1'); tmp3 = btor_or_exp (btor, tmp1, tmp2); tmp4 = btor_ones_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp3, tmp4)); btor_release_exp (btor, tmp3); btor_release_exp (btor, tmp4); } btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp2); pos += len; } } else { assert (!BTOR_IS_INVERTED_NODE (e1)); /* const == a & b */ while (pos < real_e0->len) { tmpString[0] = bv_const[pos]; len = (int) strspn (bv_const + pos, tmpString); tmp1 = btor_rewrite_slice_exp (btor, e1->e[0], real_e0->len - 1 - pos, real_e0->len - pos - len); tmp2 = btor_rewrite_slice_exp (btor, e1->e[1], real_e0->len - 1 - pos, real_e0->len - pos - len); if (tmpString[0] == '1') { tmp3 = btor_ones_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp1, tmp3)); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp2, tmp3)); btor_release_exp (btor, tmp3); } else { assert (tmpString[0] == '0'); tmp3 = btor_rewrite_and_exp (btor, tmp1, tmp2); tmp4 = btor_zero_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp3, tmp4)); btor_release_exp (btor, tmp3); btor_release_exp (btor, tmp4); } btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp2); pos += len; } } result = btor_true_exp (btor); assert (!BTOR_EMPTY_STACK(stack)); do { tmp1 = BTOR_POP_STACK (stack); tmp2 = btor_rewrite_and_exp (btor, result, tmp1); btor_release_exp (btor, result); result = tmp2; btor_release_exp (btor, tmp1); } while (!BTOR_EMPTY_STACK (stack)); btor_delete_const (btor->mm, bv_const); BTOR_RELEASE_STACK (btor->mm, stack); BTOR_DEC_REC_RW_CALL (btor); } break; } } else if (!BTOR_IS_BV_CONST_NODE (real_e0) && BTOR_IS_BV_CONST_NODE (real_e1)) { invert_b1 = BTOR_IS_INVERTED_NODE (e1); b1 = real_e1->bits; if (invert_b1) btor_invert_const (mm, b1); sc = btor_is_special_const (b1); /* invert back if necessary */ if (invert_b1) btor_invert_const (mm, b1); switch (sc) { case BTOR_SPECIAL_CONST_ZERO: switch (kind) { case BTOR_BEQ_NODE: if (real_e0->len == 1) result = btor_not_exp (btor, e0); else if (is_xor_exp (btor, e0)) /* (a ^ b) == 0 --> a = b */ { if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e0)->e[0])->e[0]), BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e0)->e[0])->e[1])); BTOR_DEC_REC_RW_CALL (btor); } } else if (BTOR_IS_INVERTED_NODE (e0) && real_e0->kind == BTOR_AND_NODE) { /* a | b == 0 --> a == 0 && b == 0 */ if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e0->e[0]), e1); right = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e0->e[1]), e1); result = btor_rewrite_and_exp (btor, left, right); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); btor_release_exp (btor, right); } } break; case BTOR_SLL_NODE: case BTOR_SRL_NODE: case BTOR_UREM_NODE: case BTOR_ADD_NODE: result = btor_copy_exp (btor, e0); break; case BTOR_MUL_NODE: case BTOR_AND_NODE: result = btor_zero_exp (btor, real_e0->len); break; case BTOR_ULT_NODE: /* x < 0 */ result = btor_false_exp (btor); break; case BTOR_UDIV_NODE: result = btor_ones_exp (btor, real_e0->len); break; default: break; } break; case BTOR_SPECIAL_CONST_ONE_ONES: assert (real_e1->len == 1); if (kind == BTOR_AND_NODE || kind == BTOR_BEQ_NODE || kind == BTOR_MUL_NODE || kind == BTOR_UDIV_NODE) result = btor_copy_exp (btor, e0); break; case BTOR_SPECIAL_CONST_ONE: if (kind == BTOR_MUL_NODE || kind == BTOR_UDIV_NODE) result = btor_copy_exp (btor, e0); else if (kind == BTOR_UREM_NODE) result = btor_zero_exp (btor, real_e0->len); else if (kind == BTOR_ULT_NODE) { tmp1 = btor_zero_exp (btor, real_e0->len); result = btor_rewrite_eq_exp (btor, e0, tmp1); btor_release_exp (btor, tmp1); } break; case BTOR_SPECIAL_CONST_ONES: if (kind == BTOR_BEQ_NODE) { if (is_xnor_exp (btor, e0)) /* (a XNOR b) == 1 --> a = b */ { if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e0)->e[0])->e[0]), BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE ( BTOR_REAL_ADDR_NODE (e0)->e[0])->e[1])); BTOR_DEC_REC_RW_CALL (btor); } } else if (!BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_AND_NODE) { /* a & b == 1+ --> a == 1+ && b == 1+ */ if (btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_eq_exp (btor, e0->e[0], e1); right = btor_rewrite_eq_exp (btor, e0->e[1], e1); result = btor_rewrite_and_exp (btor, left, right); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); btor_release_exp (btor, right); } } } else if (kind == BTOR_AND_NODE) result = btor_copy_exp (btor, e0); else if (kind == BTOR_ULT_NODE) result = BTOR_INVERT_NODE (btor_rewrite_eq_exp (btor, e0, e1)); break; default: assert (sc == BTOR_SPECIAL_CONST_NONE); if (kind == BTOR_BEQ_NODE && real_e0->kind == BTOR_AND_NODE && btor->rec_rw_calls < BTOR_REC_RW_BOUND) { BTOR_INC_REC_RW_CALL (btor); BTOR_INIT_STACK (stack); if (BTOR_IS_INVERTED_NODE (e1)) bv_const = btor_not_const (btor->mm, real_e1->bits); else bv_const = btor_copy_const (btor->mm, real_e1->bits); pos = 0; /* a | b == const */ if (BTOR_IS_INVERTED_NODE (e0)) { while (pos < real_e1->len) { tmpString[0] = bv_const[pos]; len = (int) strspn (bv_const + pos, tmpString); tmp1 = btor_rewrite_slice_exp (btor, BTOR_INVERT_NODE (real_e0->e[0]), real_e1->len - 1 - pos, real_e1->len - pos - len); tmp2 = btor_rewrite_slice_exp (btor, BTOR_INVERT_NODE (real_e0->e[1]), real_e1->len - 1 - pos, real_e1->len - pos - len); if (tmpString[0] == '0') { tmp3 = btor_zero_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp1, tmp3)); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp2, tmp3)); btor_release_exp (btor, tmp3); } else { assert (tmpString[0] == '1'); tmp3 = btor_or_exp (btor, tmp1, tmp2); tmp4 = btor_ones_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp3, tmp4)); btor_release_exp (btor, tmp3); btor_release_exp (btor, tmp4); } btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp2); pos += len; } } else { assert (!BTOR_IS_INVERTED_NODE (e0)); /* a & b == const */ while (pos < real_e1->len) { tmpString[0] = bv_const[pos]; len = (int) strspn (bv_const + pos, tmpString); tmp1 = btor_rewrite_slice_exp (btor, e0->e[0], real_e1->len - 1 - pos, real_e1->len - pos - len); tmp2 = btor_rewrite_slice_exp (btor, e0->e[1], real_e1->len - 1 - pos, real_e1->len - pos - len); if (tmpString[0] == '1') { tmp3 = btor_ones_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp1, tmp3)); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp2, tmp3)); btor_release_exp (btor, tmp3); } else { assert (tmpString[0] == '0'); tmp3 = btor_rewrite_and_exp (btor, tmp1, tmp2); tmp4 = btor_zero_exp (btor, len); BTOR_PUSH_STACK (btor->mm, stack, btor_rewrite_eq_exp (btor, tmp3, tmp4)); btor_release_exp (btor, tmp3); btor_release_exp (btor, tmp4); } btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp2); pos += len; } } result = btor_true_exp (btor); assert (!BTOR_EMPTY_STACK(stack)); do { tmp1 = BTOR_POP_STACK (stack); tmp2 = btor_rewrite_and_exp (btor, result, tmp1); btor_release_exp (btor, result); result = tmp2; btor_release_exp (btor, tmp1); } while (!BTOR_EMPTY_STACK (stack)); btor_delete_const (btor->mm, bv_const); BTOR_RELEASE_STACK (btor->mm, stack); BTOR_DEC_REC_RW_CALL (btor); } break; } } else if (real_e0 == real_e1 && (kind == BTOR_BEQ_NODE || kind == BTOR_AEQ_NODE || kind == BTOR_ADD_NODE)) { if (kind == BTOR_BEQ_NODE) { if (e0 == e1) result = btor_true_exp (btor); /* x == x */ else result = btor_false_exp (btor); /* x == ~x */ } else if (kind == BTOR_AEQ_NODE) { /* arrays must not be negated */ assert (e0 == e1); result = btor_true_exp (btor); /* x == x */ } else { assert (kind == BTOR_ADD_NODE); /* replace x + x by x * 2 */ if (e0 == e1) { if (real_e0->len >= 2) { tmp1 = btor_int_to_exp (btor, 2, real_e0->len); result = btor_rewrite_mul_exp (btor, e0, tmp1); btor_release_exp (btor, tmp1); } } else /* replace x + ~x by -1 */ result = btor_ones_exp (btor, real_e0->len); } } else if (e0 == e1 && (kind == BTOR_ULT_NODE || kind == BTOR_UREM_NODE || kind == BTOR_UDIV_NODE)) { switch (kind) { case BTOR_ULT_NODE: result = btor_false_exp (btor); break; /* v / v is 1 if v != 0 and UINT_MAX otherwise */ case BTOR_UDIV_NODE: tmp2 = btor_zero_exp (btor, real_e0->len); tmp3 = btor_one_exp (btor, real_e0->len); tmp4 = btor_ones_exp (btor, real_e0->len); eq = btor_rewrite_eq_exp (btor, e0, tmp2); result = btor_rewrite_cond_exp (btor, eq, tmp4, tmp3); btor_release_exp (btor, tmp2); btor_release_exp (btor, eq); btor_release_exp (btor, tmp4); btor_release_exp (btor, tmp3); break; default: assert (kind == BTOR_UREM_NODE); result = btor_zero_exp (btor, real_e0->len); break; } } else if (BTOR_IS_ARRAY_OR_BV_COND_NODE (real_e0) && BTOR_IS_ARRAY_OR_BV_COND_NODE (real_e1) && BTOR_IS_INVERTED_NODE (e0) == BTOR_IS_INVERTED_NODE (e1) && real_e0->e[0] == real_e1->e[0] && (real_e0->e[1] == real_e1->e[1] || real_e0->e[2] == real_e1->e[2]) && (kind == BTOR_ULT_NODE || kind == BTOR_BEQ_NODE || kind == BTOR_AEQ_NODE || kind == BTOR_ADD_NODE || kind == BTOR_UDIV_NODE)) { switch (kind) { case BTOR_ULT_NODE: fptr = btor_rewrite_ult_exp; break; case BTOR_BEQ_NODE: case BTOR_AEQ_NODE: fptr = btor_rewrite_eq_exp; break; case BTOR_ADD_NODE: fptr = btor_rewrite_add_exp; break; default: assert (kind == BTOR_UDIV_NODE); fptr = btor_rewrite_udiv_exp; break; } left = fptr (btor, BTOR_COND_INVERT_NODE (e0, real_e0->e[1]), BTOR_COND_INVERT_NODE (e0, real_e1->e[1])); right = fptr (btor, BTOR_COND_INVERT_NODE (e0, real_e0->e[2]), BTOR_COND_INVERT_NODE (e0, real_e1->e[2])); result = btor_rewrite_cond_exp (btor, real_e0->e[0], left, right); btor_release_exp (btor, left); btor_release_exp (btor, right); } else if (kind == BTOR_AND_NODE && !BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == BTOR_CONCAT_NODE && e1->kind == BTOR_CONCAT_NODE && BTOR_REAL_ADDR_NODE (e0->e[0])->len == BTOR_REAL_ADDR_NODE (e1->e[0])->len && is_const_ones_exp (btor, e0->e[1]) && is_const_ones_exp (btor, e1->e[0])) { result = btor_concat_exp (btor, real_e0->e[0], real_e1->e[1]); } else if (kind == BTOR_AND_NODE && !BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == BTOR_CONCAT_NODE && e1->kind == BTOR_CONCAT_NODE && BTOR_REAL_ADDR_NODE (e0->e[0])->len == BTOR_REAL_ADDR_NODE (e1->e[0])->len && is_const_zero_exp (btor, e0->e[0]) && is_const_zero_exp (btor, e1->e[1])) { result = btor_concat_exp (btor, e1->e[0], e0->e[1]); } else if (kind == BTOR_AND_NODE && BTOR_IS_INVERTED_NODE (e0) && BTOR_IS_INVERTED_NODE (e1) && real_e0->kind == BTOR_CONCAT_NODE && real_e1->kind == BTOR_CONCAT_NODE && BTOR_REAL_ADDR_NODE (real_e0->e[0])->len == BTOR_REAL_ADDR_NODE (real_e1->e[0])->len && is_const_zero_exp (btor, real_e0->e[1]) && is_const_zero_exp (btor, real_e1->e[0])) { result = btor_concat_exp (btor, real_e0->e[0], real_e1->e[1]); result = BTOR_INVERT_NODE (result); } else if (kind == BTOR_AND_NODE && BTOR_IS_INVERTED_NODE (e0) && BTOR_IS_INVERTED_NODE (e1) && real_e0->kind == BTOR_CONCAT_NODE && real_e1->kind == BTOR_CONCAT_NODE && BTOR_REAL_ADDR_NODE (real_e0->e[0])->len == BTOR_REAL_ADDR_NODE (real_e1->e[0])->len && is_const_zero_exp (btor, real_e0->e[0]) && is_const_zero_exp (btor, real_e1->e[1])) { result = btor_concat_exp (btor, real_e1->e[0], real_e0->e[1]); result = BTOR_INVERT_NODE (result); } /* TODO: lots of word level simplifications: * a[7:4] == b[7:4] && a[3:0] == b[3:0] <=> a == b * {a,b} == {c,d} with |a|=|c| <=> a == c && b == d * ... */ /* TODO a + 2 * a <=> 3 * a <=> and see below */ /* TODO strength reduction: a * 2 == a << 1 (really ?) */ /* TODO strength reduction: a * 3 == (a << 1) + a (really ?) */ /* TODO strength reduction: a / 2 == (a >> 1) (yes!) */ /* TODO strength reduction: a / 3 => higher bits zero (check!) */ /* TODO MAX-1 < a <=> a == MAX */ /* TODO (x < ~x) <=> !msb(x) */ /* TODO (~x < x) <=> msb(x) */ /* TODO to support GAUSS bubble up odd terms: * (2 * a + 3 * y) + 4 * x => 3 * y + (2 * a + 4 * x) * or alternatively normalize arithmetic terms/polynomials * or simply always replace by equation. */ /* TODO simplify (c * x + 2 * y) + x == 5 at GAUSS application * by first (c + 1) * x + 2 * y == 5 and then check whether 'c' * is even. */ /* TODO Howto handle 2 * x == 4 && 4 * x + 8 * y == 0 ? * Maybe: x[30:0] == 2 && 4 * {x[31],2[30:0]} + 8 * y == 0? * Then: x[30:0] == 2 && 8[31:0] + 8 *y == 0? * Then: x[30:0] = 2 && 8 * y = -8 * Finally: x[30:0] = 2 && y[29:0] = -1 * etc. */ return result; } static int is_always_unequal (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *real_e0, *real_e1; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor); assert (e0); assert (e1); /* we need this so that a + 0 is rewritten to a, * and constants are normalized (all inverted constants are odd) */ assert (btor->rewrite_level > 0); real_e0 = BTOR_REAL_ADDR_NODE (e0); real_e1 = BTOR_REAL_ADDR_NODE (e1); if (!real_e0 || !real_e1) return 0; if (BTOR_IS_ARRAY_NODE (real_e0)) { assert (BTOR_IS_ARRAY_NODE (real_e1)); return 0; } assert (!BTOR_IS_ARRAY_NODE (real_e1)); if (e0 == BTOR_INVERT_NODE (e1)) return 1; if (BTOR_IS_BV_CONST_NODE (real_e0) && BTOR_IS_BV_CONST_NODE (real_e1) && e0 != e1) return 1; if (real_e0->kind == BTOR_ADD_NODE) { if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (real_e0->e[0])) && !is_const_zero_exp (btor, real_e0->e[0]) && BTOR_COND_INVERT_NODE (e0, real_e0->e[1]) == e1) return 1; if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (real_e0->e[1])) && !is_const_zero_exp (btor, real_e0->e[1]) && BTOR_COND_INVERT_NODE (e0, real_e0->e[0]) == e1) return 1; } if (real_e1->kind == BTOR_ADD_NODE) { if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (real_e1->e[0])) && !is_const_zero_exp (btor, real_e1->e[0]) && BTOR_COND_INVERT_NODE (e1, real_e1->e[1]) == e0) return 1; if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (real_e1->e[1])) && !is_const_zero_exp (btor, real_e1->e[1]) && BTOR_COND_INVERT_NODE (e1, real_e1->e[0]) == e0) return 1; } return 0; } static void normalize_binary_comm_ass_exp (Btor * btor, BtorNode * e0, BtorNode * e1, BtorNode ** e0_norm, BtorNode ** e1_norm, BtorNode * (*fptr) (Btor *, BtorNode *, BtorNode *), BtorNodeKind kind) { BtorNode *cur, *result, *temp, *common; BtorNodePtrStack stack; BtorMemMgr *mm; int i; BtorPtrHashTable *left, *right, *comm; BtorPtrHashBucket *b; assert (btor); assert (e0); assert (e1); assert (!BTOR_REAL_ADDR_NODE (e0)->simplified); assert (!BTOR_REAL_ADDR_NODE (e1)->simplified); assert (e0_norm); assert (e1_norm); assert (fptr); assert (BTOR_IS_BINARY_NODE_KIND (kind)); assert (!BTOR_IS_INVERTED_NODE (e0)); assert (!BTOR_IS_INVERTED_NODE (e1)); assert (e0->kind == kind); assert (e1->kind == kind); assert (btor->rewrite_level > 2); mm = btor->mm; left = btor_new_ptr_hash_table (mm, (BtorHashPtr) btor_hash_exp_by_id, (BtorCmpPtr) btor_compare_exp_by_id); right = btor_new_ptr_hash_table (mm, (BtorHashPtr) btor_hash_exp_by_id, (BtorCmpPtr) btor_compare_exp_by_id); comm = btor_new_ptr_hash_table (mm, (BtorHashPtr) btor_hash_exp_by_id, (BtorCmpPtr) btor_compare_exp_by_id); BTOR_INIT_STACK (stack); BTOR_PUSH_STACK (mm, stack, e0); do { cur = BTOR_POP_STACK (stack); if (!BTOR_IS_INVERTED_NODE (cur) && cur->kind == kind) { BTOR_PUSH_STACK (mm, stack, cur->e[1]); BTOR_PUSH_STACK (mm, stack, cur->e[0]); } else { b = btor_find_in_ptr_hash_table (left, cur); if (!b) btor_insert_in_ptr_hash_table (left, cur)->data.asInt = 1; else b->data.asInt++; } } while (!BTOR_EMPTY_STACK (stack)); BTOR_PUSH_STACK (mm, stack, e1); do { cur = BTOR_POP_STACK (stack); if (!BTOR_IS_INVERTED_NODE (cur) && cur->kind == kind) { BTOR_PUSH_STACK (mm, stack, cur->e[1]); BTOR_PUSH_STACK (mm, stack, cur->e[0]); } else { b = btor_find_in_ptr_hash_table (left, cur); if (b) { /* we found one common operand */ /* remove operand from left */ if (b->data.asInt > 1) b->data.asInt--; else { assert (b->data.asInt == 1); btor_remove_from_ptr_hash_table (left, cur, 0, 0); } /* insert into common table */ b = btor_find_in_ptr_hash_table (comm, cur); if (!b) btor_insert_in_ptr_hash_table (comm, cur)->data.asInt = 1; else b->data.asInt++; } else { /* operand is not common */ b = btor_find_in_ptr_hash_table (right, cur); if (!b) btor_insert_in_ptr_hash_table (right, cur)->data.asInt = 1; else b->data.asInt++; } } } while (!BTOR_EMPTY_STACK (stack)); BTOR_RELEASE_STACK (mm, stack); /* no operand or only one operand in common? leave everything as it is */ if (comm->count < 2u) { /* clean up */ btor_delete_ptr_hash_table (left); btor_delete_ptr_hash_table (right); btor_delete_ptr_hash_table (comm); *e0_norm = btor_copy_exp (btor, e0); *e1_norm = btor_copy_exp (btor, e1); return; } if (kind == BTOR_ADD_NODE) btor->stats.adds_normalized++; else { assert (kind == BTOR_MUL_NODE); btor->stats.muls_normalized++; } assert (comm->count >= 2u); b = comm->first; common = btor_copy_exp (btor, (BtorNode *) b->key); if (b->data.asInt > 0) b->data.asInt--; else b = b->next; while (b) { cur = b->key; for (i = 0; i < b->data.asInt; i++) { temp = fptr (btor, common, cur); btor_release_exp (btor, common); common = temp; } b = b->next; } /* normalize left side */ result = btor_copy_exp (btor, common); for (b = left->first; b; b = b->next) { cur = b->key; for (i = 0; i < b->data.asInt; i++) { temp = fptr (btor, result, cur); btor_release_exp (btor, result); result = temp; } } *e0_norm = result; /* normalize right side */ result = btor_copy_exp (btor, common); for (b = right->first; b; b = b->next) { cur = b->key; for (i = 0; i < b->data.asInt; i++) { temp = fptr (btor, result, cur); btor_release_exp (btor, result); result = temp; } } *e1_norm = result; /* clean up */ btor_release_exp (btor, common); btor_delete_ptr_hash_table (left); btor_delete_ptr_hash_table (right); btor_delete_ptr_hash_table (comm); } static void normalize_adds_exp (Btor * btor, BtorNode * e0, BtorNode * e1, BtorNode ** e0_norm, BtorNode ** e1_norm) { assert (btor); assert (e0); assert (e1); assert (!BTOR_REAL_ADDR_NODE (e0)->simplified); assert (!BTOR_REAL_ADDR_NODE (e1)->simplified); assert (e0_norm); assert (e1_norm); assert (!BTOR_IS_INVERTED_NODE (e0)); assert (!BTOR_IS_INVERTED_NODE (e1)); assert (e0->kind == BTOR_ADD_NODE); assert (e1->kind == BTOR_ADD_NODE); normalize_binary_comm_ass_exp (btor, e0, e1, e0_norm, e1_norm, btor_rewrite_add_exp, BTOR_ADD_NODE); } static void normalize_muls_exp (Btor * btor, BtorNode * e0, BtorNode * e1, BtorNode ** e0_norm, BtorNode ** e1_norm) { assert (btor); assert (e0); assert (e1); assert (!BTOR_REAL_ADDR_NODE (e0)->simplified); assert (!BTOR_REAL_ADDR_NODE (e1)->simplified); assert (e0_norm); assert (e1_norm); assert (!BTOR_IS_INVERTED_NODE (e0)); assert (!BTOR_IS_INVERTED_NODE (e1)); assert (e0->kind == BTOR_MUL_NODE); assert (e1->kind == BTOR_MUL_NODE); normalize_binary_comm_ass_exp (btor, e0, e1, e0_norm, e1_norm, btor_rewrite_mul_exp, BTOR_MUL_NODE); } static int find_and_contradiction_exp (Btor * btor, BtorNode *exp, BtorNode *e0, BtorNode *e1, int *calls) { assert (btor); assert (exp); assert (e0); assert (e1); assert (calls); assert (*calls >= 0); (void) btor; if (*calls >= BTOR_FIND_AND_NODE_CONTRADICTION_LIMIT) return 0; if (!BTOR_IS_INVERTED_NODE (exp) && exp->kind == BTOR_AND_NODE) { if (exp->e[0] == BTOR_INVERT_NODE (e0) || exp->e[0] == BTOR_INVERT_NODE (e1) || exp->e[1] == BTOR_INVERT_NODE (e0) || exp->e[1] == BTOR_INVERT_NODE (e1)) return 1; *calls += 1; return find_and_contradiction_exp (btor, exp->e[0], e0, e1, calls) || find_and_contradiction_exp (btor, exp->e[1], e0, e1, calls); } return 0; } BtorNode * btor_rewrite_and_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *real_e0, *real_e1, *result, *e0_norm, *e1_norm, *temp; int normalized, calls; normalized = 0; calls = 0; BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN: /* two level optimization [MEMICS] for BTOR_AND_NODE */ assert (!normalized); e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_regular_binary_bv_exp_dbg (btor, e0, e1)); real_e0 = BTOR_REAL_ADDR_NODE (e0); real_e1 = BTOR_REAL_ADDR_NODE (e1); if (e0 == e1) /* x & x == x */ { return btor_copy_exp (btor, e0); } if (BTOR_INVERT_NODE (e0) == e1) /* x & ~x == 0 */ { return btor_zero_exp (btor, real_e0->len); } if (real_e0->kind == BTOR_AND_NODE && real_e1->kind == BTOR_AND_NODE) { if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1)) { /* second rule of contradiction */ if (real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[0]) || real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[1]) || real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[0]) || real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[1])) { return btor_zero_exp (btor, real_e0->len); } /* symmetric rule of idempotency */ if (real_e0->e[0] == real_e1->e[0] || real_e0->e[1] == real_e1->e[0]) { e1 = real_e1->e[1]; goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } /* use commutativity */ if (real_e0->e[0] == real_e1->e[1] || real_e0->e[1] == real_e1->e[1]) { e1 = real_e1->e[0]; goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } } else if (!BTOR_IS_INVERTED_NODE (e0) && BTOR_IS_INVERTED_NODE (e1)) { /* second rule of subsumption */ if (real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[0]) || real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[1]) || real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[0]) || real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[1])) { return btor_copy_exp (btor, e0); } /* symmetric rule of substitution */ if ((real_e1->e[0] == real_e0->e[1]) || (real_e1->e[0] == real_e0->e[0])) { e1 = BTOR_INVERT_NODE (real_e1->e[1]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } /* symmetric rule of substitution */ if ((real_e1->e[1] == real_e0->e[1]) || (real_e1->e[1] == real_e0->e[0])) { e1 = BTOR_INVERT_NODE (real_e1->e[0]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } } else if (BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1)) { /* second rule of subsumption */ if (real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[0]) || real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[1]) || real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[0]) || real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[1])) { return btor_copy_exp (btor, e1); } /* symmetric rule of substitution */ if ((real_e0->e[1] == real_e1->e[0]) || (real_e0->e[1] == real_e1->e[1])) { e0 = BTOR_INVERT_NODE (real_e0->e[0]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } /* symmetric rule of substitution */ if ((real_e0->e[0] == real_e1->e[0]) || (real_e0->e[0] == real_e1->e[1])) { e0 = BTOR_INVERT_NODE (real_e0->e[1]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } } else { assert (BTOR_IS_INVERTED_NODE (e0)); assert (BTOR_IS_INVERTED_NODE (e1)); /* a XNOR b simplifies to a == b for the boolean case */ if (real_e0->len == 1 && BTOR_IS_INVERTED_NODE (real_e0->e[0]) != BTOR_IS_INVERTED_NODE (real_e0->e[1]) && BTOR_IS_INVERTED_NODE (real_e1->e[0]) != BTOR_IS_INVERTED_NODE (real_e1->e[1]) && ((real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[0]) && real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[1])) || (real_e0->e[0] == BTOR_INVERT_NODE (real_e1->e[1]) && real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[0])))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_AND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, BTOR_REAL_ADDR_NODE (real_e0->e[0]), BTOR_REAL_ADDR_NODE (real_e0->e[1])); BTOR_DEC_REC_RW_CALL (btor); return result; } /* rule of resolution */ if ((real_e0->e[0] == real_e1->e[0] && real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[1])) || (real_e0->e[0] == real_e1->e[1] && real_e0->e[1] == BTOR_INVERT_NODE (real_e1->e[0]))) { return BTOR_INVERT_NODE (btor_copy_exp (btor, real_e0->e[0])); } /* rule of resolution */ if ((real_e1->e[1] == real_e0->e[1] && real_e1->e[0] == BTOR_INVERT_NODE (real_e0->e[0])) || (real_e1->e[1] == real_e0->e[0] && real_e1->e[0] == BTOR_INVERT_NODE (real_e0->e[1]))) { return BTOR_INVERT_NODE (btor_copy_exp (btor, real_e1->e[1])); } } } if (real_e0->kind == BTOR_AND_NODE) { if (BTOR_IS_INVERTED_NODE (e0)) { /* first rule of subsumption */ if (real_e0->e[0] == BTOR_INVERT_NODE (e1) || real_e0->e[1] == BTOR_INVERT_NODE (e1)) { return btor_copy_exp (btor, e1); } /* asymmetric rule of substitution */ if (real_e0->e[1] == e1) { e0 = BTOR_INVERT_NODE (real_e0->e[0]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } /* asymmetric rule of substitution */ if (real_e0->e[0] == e1) { e0 = BTOR_INVERT_NODE (real_e0->e[1]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } } else { assert (!BTOR_IS_INVERTED_NODE (e0)); /* first rule of contradiction */ if (e0->e[0] == BTOR_INVERT_NODE (e1) || e0->e[1] == BTOR_INVERT_NODE (e1)) { return btor_zero_exp (btor, e0->len); } /* asymmetric rule of idempotency */ if (e0->e[0] == e1 || e0->e[1] == e1) { return btor_copy_exp (btor, e0); } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1))) { if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_AND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_and_exp (btor, e1, e0->e[0]); result = btor_rewrite_and_exp (btor, temp, e0->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_AND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_and_exp (btor, e1, e0->e[1]); result = btor_rewrite_and_exp (btor, temp, e0->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } } } } if (real_e1->kind == BTOR_AND_NODE) { if (BTOR_IS_INVERTED_NODE (e1)) { /* first rule of subsumption */ if (real_e1->e[0] == BTOR_INVERT_NODE (e0) || real_e1->e[1] == BTOR_INVERT_NODE (e0)) { return btor_copy_exp (btor, e0); } /* asymmetric rule of substitution */ if (real_e1->e[0] == e0) { e1 = BTOR_INVERT_NODE (real_e1->e[1]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } /* asymmetric rule of substitution */ if (real_e1->e[1] == e0) { e1 = BTOR_INVERT_NODE (real_e1->e[0]); goto BTOR_NODE_TWO_LEVEL_OPT_TRY_AGAIN; } } else { assert (!BTOR_IS_INVERTED_NODE (e1)); /* first rule of contradiction */ if (e1->e[0] == BTOR_INVERT_NODE (e0) || e1->e[1] == BTOR_INVERT_NODE (e0)) { return btor_zero_exp (btor, real_e0->len); } /* asymmetric rule of idempotency */ if (e1->e[0] == e0 || e1->e[1] == e0) { return btor_copy_exp (btor, e1); } if (BTOR_IS_BV_CONST_NODE (real_e0)) { /* recursion is no problem here, as one call leads to * folding of constants, and the other call can not * trigger the same kind of recursion anymore */ if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_AND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_and_exp (btor, e0, e1->e[0]); result = btor_rewrite_and_exp (btor, temp, e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_AND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_and_exp (btor, e0, e1->e[1]); result = btor_rewrite_and_exp (btor, temp, e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } } } } if (real_e0->kind == BTOR_ULT_NODE && real_e1->kind == BTOR_ULT_NODE) { /* a < b && b < a simplifies to FALSE */ if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->e[0] == e1->e[1] && e0->e[1] == e1->e[0]) { return btor_false_exp (btor); } /* NOT (a < b) && NOT (b < a) simplifies to a == b */ if (BTOR_IS_INVERTED_NODE (e0) && BTOR_IS_INVERTED_NODE (e1) && real_e0->e[0] == real_e1->e[1] && real_e0->e[1] == real_e1->e[0]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_AND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, real_e0->e[0], real_e0->e[1]); BTOR_DEC_REC_RW_CALL (btor); return result; } } if (find_and_contradiction_exp (btor, e0, e0, e1, &calls) || find_and_contradiction_exp (btor, e1, e0, e1, &calls)) return btor_zero_exp (btor, real_e0->len); if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == e1->kind) { if (e0->kind == BTOR_ADD_NODE) { assert (e1->kind == BTOR_ADD_NODE); normalize_adds_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } else if (e0->kind == BTOR_MUL_NODE) { assert (e1->kind == BTOR_MUL_NODE); normalize_muls_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } } result = rewrite_binary_exp (btor, BTOR_AND_NODE, e0, e1); if (!result) { BTOR_REWRITE_AND_NODE_NO_REWRITE: result = btor_and_exp_node (btor, e0, e1); } if (normalized) { btor_release_exp (btor, e0_norm); btor_release_exp (btor, e1_norm); } return result; } /* This function tries to rewrite a * b + a * c into a * (b + c) * it returns 0 when it has not succeeded */ static BtorNode * try_rewrite_add_mul_distrib (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *add, *mul; assert (btor); assert (e0); assert (e1); assert (btor->rewrite_level > 2); result = 0; add = 0; mul = 0; if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == BTOR_MUL_NODE && e1->kind == BTOR_MUL_NODE) { if (e0->e[0] == e1->e[0]) { add = btor_rewrite_add_exp (btor, e0->e[1], e1->e[1]); mul = e0->e[0]; } else if (e0->e[0] == e1->e[1]) { add = btor_rewrite_add_exp (btor, e0->e[1], e1->e[0]); mul = e0->e[0]; } else if (e0->e[1] == e1->e[0]) { add = btor_rewrite_add_exp (btor, e0->e[0], e1->e[1]); mul = e0->e[1]; } else if (e0->e[1] == e1->e[1]) { add = btor_rewrite_add_exp (btor, e0->e[0], e1->e[0]); mul = e0->e[1]; } if (add) { assert (mul); result = btor_rewrite_mul_exp (btor, mul, add); btor_release_exp (btor, add); /* mul owns no reference */ } } return result; } static BtorNode * normalize_negated_add (Btor * btor, BtorNode * exp) { BtorNode * tmp, *res, *one; BtorNode * real_exp; if (!BTOR_IS_INVERTED_NODE (exp)) return btor_copy_exp (btor, exp); real_exp = BTOR_REAL_ADDR_NODE (exp); if (real_exp->kind != BTOR_ADD_NODE) return btor_copy_exp (btor, exp); tmp = btor_add_exp (btor, BTOR_INVERT_NODE (real_exp->e[0]), BTOR_INVERT_NODE (real_exp->e[1])); one = btor_one_exp (btor, real_exp->len); res = btor_add_exp (btor, tmp, one); btor_release_exp (btor, one); btor_release_exp (btor, tmp); return res; } #if 0 static void normalize_eq_adds_exp (Btor * btor, BtorNode * e0, BtorNode * e1, BtorNode ** res0ptr, BtorNode ** res1ptr) { BtorNode * cur, * leftconst, * tmp, * res0, * res1, * one; int len = BTOR_REAL_ADDR_NODE (e0)->len; BtorMemMgr *mm = btor->mm; BtorNodePtrStack stack; res0 = btor_zero_exp (btor, len); res1 = btor_copy_exp (btor, res0); leftconst = btor_copy_exp (btor, res0); one = btor_one_exp (btor, len); BTOR_INIT_STACK (stack); BTOR_PUSH_STACK (mm, stack, e0); do { cur = BTOR_POP_STACK (stack); if (!BTOR_IS_INVERTED_NODE (cur) && cur->kind == BTOR_ADD_NODE) { BTOR_PUSH_STACK (mm, stack, cur->e[1]); BTOR_PUSH_STACK (mm, stack, cur->e[0]); } else if (BTOR_REAL_ADDR_NODE (cur)->kind == BTOR_BV_CONST_NODE) { tmp = btor_add_exp (btor, leftconst, cur); btor_release_exp (btor, leftconst); leftconst = tmp; } else if (BTOR_IS_INVERTED_NODE (cur)) { tmp = btor_add_exp (btor, res1, BTOR_INVERT_NODE (cur)); btor_release_exp (btor, res1); res1 = tmp; tmp = btor_sub_exp (btor, leftconst, one); btor_release_exp (btor, leftconst); leftconst = tmp; } else { tmp = btor_add_exp (btor, res0, cur); btor_release_exp (btor, res0); res0 = tmp; } } while (!BTOR_EMPTY_STACK (stack)); BTOR_PUSH_STACK (mm, stack, e1); do { cur = BTOR_POP_STACK (stack); if (!BTOR_IS_INVERTED_NODE (cur) && cur->kind == BTOR_ADD_NODE) { BTOR_PUSH_STACK (mm, stack, cur->e[1]); BTOR_PUSH_STACK (mm, stack, cur->e[0]); } else if (BTOR_REAL_ADDR_NODE (cur)->kind == BTOR_BV_CONST_NODE) { tmp = btor_sub_exp (btor, leftconst, cur); btor_release_exp (btor, leftconst); leftconst = tmp; } else if (BTOR_IS_INVERTED_NODE (cur)) { tmp = btor_add_exp (btor, res0, BTOR_INVERT_NODE (cur)); btor_release_exp (btor, res0); res0 = tmp; tmp = btor_add_exp (btor, leftconst, one); btor_release_exp (btor, leftconst); leftconst = tmp; } else { tmp = btor_add_exp (btor, res1, cur); btor_release_exp (btor, res1); res1 = tmp; } } while (!BTOR_EMPTY_STACK (stack)); assert (BTOR_REAL_ADDR_NODE (leftconst)->kind == BTOR_BV_CONST_NODE); if (is_const_zero_exp (btor, leftconst)) { /* nothing to be done */ } else if (is_const_zero_exp (btor, res0)) { btor_release_exp (btor, res0); res0 = btor_copy_exp (btor, leftconst); } else if (is_const_zero_exp (btor, res1)) { btor_release_exp (btor, res1); res1 = btor_neg_exp (btor, leftconst); } else { tmp = btor_add_exp (btor, res0, leftconst); btor_release_exp (btor, res0); res0 = tmp; } btor_release_exp (btor, leftconst); btor_release_exp (btor, one); BTOR_RELEASE_STACK (mm, stack); *res0ptr = res0; *res1ptr = res1; } #else static void normalize_eq_adds_exp (Btor * btor, BtorNode * e0, BtorNode * e1, BtorNode ** res0ptr, BtorNode ** res1ptr) { BtorNode * res0 = 0, * res1 = 0; if (BTOR_REAL_ADDR_NODE (e0)->kind == BTOR_BV_CONST_NODE && !BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_ADD_NODE) { if (BTOR_REAL_ADDR_NODE (e1->e[0])->kind == BTOR_BV_CONST_NODE) { res0 = btor_sub_exp (btor, e0, e1->e[0]); res1 = btor_copy_exp (btor, e1->e[1]); } else if (BTOR_REAL_ADDR_NODE (e1->e[1])->kind == BTOR_BV_CONST_NODE) { res0 = btor_sub_exp (btor, e0, e1->e[1]); res1 = btor_copy_exp (btor, e1->e[0]); } } else if (BTOR_REAL_ADDR_NODE (e1)->kind == BTOR_BV_CONST_NODE && !BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_ADD_NODE) { if (BTOR_REAL_ADDR_NODE (e0->e[0])->kind == BTOR_BV_CONST_NODE) { res0 = btor_copy_exp (btor, e0->e[1]); res1 = btor_sub_exp (btor, e1, e0->e[0]); } else if (BTOR_REAL_ADDR_NODE (e0->e[1])->kind == BTOR_BV_CONST_NODE) { res0 = btor_copy_exp (btor, e0->e[0]); res1 = btor_sub_exp (btor, e1, e0->e[1]); } } if (res0) { assert (res1); *res0ptr = res0; *res1ptr = res1; } else { assert (!res1); *res0ptr = btor_copy_exp (btor, e0); *res1ptr = btor_copy_exp (btor, e1); } } #endif BtorNode * btor_rewrite_eq_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *tmp1, *tmp2, *tmp3, *tmp4, *result; BtorNode *real_e0, *real_e1; BtorNodeKind kind; int upper, lower; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_eq_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); if (BTOR_IS_ARRAY_NODE (BTOR_REAL_ADDR_NODE (e0))) kind = BTOR_AEQ_NODE; else kind = BTOR_BEQ_NODE; /* write (a, i, e1) = write (a, i, e2) ----> e1 = e2 */ if (kind == BTOR_AEQ_NODE && BTOR_IS_WRITE_NODE (e0) && BTOR_IS_WRITE_NODE (e1) && e0->e[0] == e1->e[0] && e0->e[1] == e1->e[1]) { e0 = e0->e[2]; e1 = e1->e[2]; kind = BTOR_BEQ_NODE; } e0 = normalize_negated_add (btor, e0); e1 = normalize_negated_add (btor, e1); /* ~e0 == ~e1 is the same as e0 == e1 */ if (BTOR_IS_INVERTED_NODE (e0) && BTOR_IS_INVERTED_NODE (e1)) { e0 = BTOR_REAL_ADDR_NODE (e0); e1 = BTOR_REAL_ADDR_NODE (e1); } real_e0 = BTOR_REAL_ADDR_NODE (e0); real_e1 = BTOR_REAL_ADDR_NODE (e1); /* We do not rewrite eq in the boolean case, as we cannot extract the resulting * XNOR on top level again and would therefore loose substitutions. * * Additionally, we do not rewrite eq in the boolean case, as we rewrite a != b * to a = ~b and substitute. */ if (e0 == e1) { result = btor_true_exp (btor); goto DONE; } if (is_always_unequal (btor, e0, e1)) { result = btor_false_exp (btor); goto DONE; } if (btor->rewrite_level > 2) { if (!BTOR_IS_INVERTED_NODE (e0)) { /* a + b = a ----> b = 0, * This rule does not lead to less substitutions. 'a' cannot * be substituted as the occurrence check would fail */ if (e0->kind == BTOR_ADD_NODE) { if (e0->e[0] == e1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; tmp1 = btor_zero_exp (btor, e0->len); BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, tmp1, e0->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } if (e0->e[1] == e1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; tmp1 = btor_zero_exp (btor, e0->len); BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, tmp1, e0->e[0]); btor_release_exp (btor, tmp1); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } } /* b ? a : t = d ---a != d--> !b AND d = t */ if (e0->kind == BTOR_BCOND_NODE) { if (is_always_unequal (btor, e0->e[1], e1)) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_eq_exp (btor, e0->e[2], e1); result = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (e0->e[0]), tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } if (is_always_unequal (btor, e0->e[2], e1)) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_eq_exp (btor, e0->e[1], e1); result = btor_rewrite_and_exp (btor, e0->e[0], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } } } if (!BTOR_IS_INVERTED_NODE (e1)) { /* a = a + b ----> b = 0, * This rule does not lead to less substitutions. 'a' cannot * be substituted as the occurrence check would fail. */ if (e1->kind == BTOR_ADD_NODE) { if (e1->e[0] == e0) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; tmp1 = btor_zero_exp (btor, e1->len); BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, tmp1, e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } if (e1->e[1] == e0) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; tmp1 = btor_zero_exp (btor, e1->len); BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, tmp1, e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } } /* d = b ? a : t ---a != d--> !b AND d = t */ if (e1->kind == BTOR_BCOND_NODE) { if (is_always_unequal (btor, e1->e[1], e0)) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_eq_exp (btor, e1->e[2], e0); result = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (e1->e[0]), tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } if (is_always_unequal (btor, e1->e[2], e0)) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_eq_exp (btor, e1->e[1], e0); result = btor_rewrite_and_exp (btor, e1->e[0], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } } } if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1)) { /* a + b = a + c ---> b = c */ if (e0->kind == BTOR_ADD_NODE && e1->kind == BTOR_ADD_NODE) { if (e0->e[0] == e1->e[0]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[1], e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } if (e0->e[0] == e1->e[1]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[1], e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } if (e0->e[1] == e1->e[0]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[0], e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } if (e0->e[1] == e1->e[1]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[0], e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } } /* Commutative operators are normalized ignoring signs, so we do not * have to check cases like a & b == ~b & a as they are represented as * a & b == a & ~b */ if (e0->kind == BTOR_AND_NODE && e1->kind == BTOR_AND_NODE) { if (e0->e[0] == BTOR_INVERT_NODE (e1->e[0]) && e0->e[1] == BTOR_INVERT_NODE (e1->e[1])) { /* a & b == ~a & ~b --> a == ~b */ if (BTOR_IS_INVERTED_NODE (e0->e[0]) == BTOR_IS_INVERTED_NODE (e0->e[1])) { assert (BTOR_IS_INVERTED_NODE (e1->e[0]) == BTOR_IS_INVERTED_NODE (e1->e[1])); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[0], BTOR_INVERT_NODE (e0->e[1])); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } /* a~ & b == a & ~b --> a == b */ if (BTOR_IS_INVERTED_NODE (e0->e[0]) != BTOR_IS_INVERTED_NODE (e0->e[1])) { assert (BTOR_IS_INVERTED_NODE (e1->e[0]) != BTOR_IS_INVERTED_NODE (e1->e[1])); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, BTOR_REAL_ADDR_NODE (e0->e[0]), BTOR_REAL_ADDR_NODE (e0->e[1])); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } } /* a & b == a & ~b ---> a == 0 */ if (e0->e[0] == e1->e[0] && e0->e[1] == BTOR_INVERT_NODE (e1->e[1])) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; tmp1 = btor_zero_exp (btor, e0->len); BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[0], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } /* a & b == ~a & b ---> b == 0 */ if (e0->e[1] == e1->e[1] && e0->e[0] == BTOR_INVERT_NODE (e1->e[0])) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; tmp1 = btor_zero_exp (btor, e0->len); BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_eq_exp (btor, e0->e[1], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); goto DONE; } } } /* a = b ? a : c is rewritten to b OR a = c * a = ~(b ? a : c) is rewritten to !b AND a = ~c */ if (BTOR_IS_ARRAY_OR_BV_COND_NODE (real_e0)) { if (real_e0->e[1] == e1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); if (BTOR_IS_INVERTED_NODE (e0)) { tmp1 = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e0->e[2]), e1); result = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (real_e0->e[0]), tmp1); } else { tmp1 = btor_rewrite_eq_exp (btor, real_e0->e[2], e1); result = btor_or_exp (btor, real_e0->e[0], tmp1); } btor_release_exp (btor, tmp1); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } if (real_e0->e[2] == e1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); if (BTOR_IS_INVERTED_NODE (e0)) { tmp1 = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e0->e[1]), e1); result = btor_rewrite_and_exp (btor, real_e0->e[0], tmp1); } else { tmp1 = btor_rewrite_eq_exp (btor, real_e0->e[1], e1); result = btor_or_exp (btor, BTOR_INVERT_NODE (real_e0->e[0]), tmp1); } btor_release_exp (btor, tmp1); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } } if (BTOR_IS_ARRAY_OR_BV_COND_NODE (real_e1)) { if (real_e1->e[1] == e0) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); if (BTOR_IS_INVERTED_NODE (e1)) { tmp1 = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e1->e[2]), e0); result = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (real_e1->e[0]), tmp1); } else { tmp1 = btor_rewrite_eq_exp (btor, real_e1->e[2], e0); result = btor_or_exp (btor, real_e1->e[0], tmp1); } btor_release_exp (btor, tmp1); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } if (real_e1->e[2] == e0) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); if (BTOR_IS_INVERTED_NODE (e1)) { tmp1 = btor_rewrite_eq_exp (btor, BTOR_INVERT_NODE (real_e1->e[1]), e0); result = btor_rewrite_and_exp (btor, real_e1->e[0], tmp1); } else { tmp1 = btor_rewrite_eq_exp (btor, real_e1->e[1], e0); result = btor_or_exp (btor, BTOR_INVERT_NODE (real_e1->e[0]), tmp1); } btor_release_exp (btor, tmp1); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } } /* normalize adds and muls on demand */ if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && (((e0->kind == BTOR_ADD_NODE || e0->kind == BTOR_MUL_NODE) && e0->kind == e1->kind) || (e0->kind == BTOR_ADD_NODE && e1->kind == BTOR_MUL_NODE) || (e1->kind == BTOR_ADD_NODE && e0->kind == BTOR_MUL_NODE))) { if ((e0->kind == BTOR_ADD_NODE || e0->kind == BTOR_MUL_NODE) && e0->kind == e1->kind) { if (e0->kind == BTOR_ADD_NODE) { assert (e1->kind == BTOR_ADD_NODE); normalize_adds_exp (btor, e0, e1, &tmp1, &tmp2); } else { assert (e0->kind == BTOR_MUL_NODE); assert (e1->kind == BTOR_MUL_NODE); normalize_muls_exp (btor, e0, e1, &tmp1, &tmp2); } btor_release_exp (btor, e0); btor_release_exp (btor, e1); e0 = tmp1; e1 = tmp2; real_e0 = BTOR_REAL_ADDR_NODE (e0); real_e1 = BTOR_REAL_ADDR_NODE (e1); } /* find out distributivity from mul and add */ else if (e0->kind == BTOR_MUL_NODE && e1->kind == BTOR_ADD_NODE) { tmp1 = try_rewrite_add_mul_distrib (btor, e1->e[0], e1->e[1]); if (tmp1) { if (tmp1 == e0) { btor_release_exp (btor, tmp1); result = btor_true_exp (btor); goto DONE; } btor_release_exp (btor, tmp1); } } else if (e1->kind == BTOR_MUL_NODE && e0->kind == BTOR_ADD_NODE) { tmp1 = try_rewrite_add_mul_distrib (btor, e0->e[0], e0->e[1]); if (tmp1) { if (tmp1 == e1) { btor_release_exp (btor, tmp1); result = btor_true_exp (btor); goto DONE; } btor_release_exp (btor, tmp1); } } } else if (kind == BTOR_BEQ_NODE) { /* push eq down over concats */ if (real_e0->kind == BTOR_CONCAT_NODE || real_e1->kind == BTOR_CONCAT_NODE) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_EQ_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); upper = real_e0->len - 1; if (real_e0->kind == BTOR_CONCAT_NODE) lower = upper - BTOR_REAL_ADDR_NODE (real_e0->e[0])->len + 1; else lower = upper - BTOR_REAL_ADDR_NODE (real_e1->e[0])->len + 1; tmp1 = btor_rewrite_slice_exp (btor, e0, upper, lower); tmp3 = btor_rewrite_slice_exp (btor, e1, upper, lower); tmp2 = btor_rewrite_eq_exp (btor, tmp1, tmp3); btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp3); lower--; tmp1 = btor_rewrite_slice_exp (btor, e0, lower, 0); tmp3 = btor_rewrite_slice_exp (btor, e1, lower, 0); tmp4 = btor_rewrite_eq_exp (btor, tmp1, tmp3); result = btor_rewrite_and_exp (btor, tmp2, tmp4); btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp2); btor_release_exp (btor, tmp3); btor_release_exp (btor, tmp4); BTOR_DEC_REC_RW_CALL (btor); goto DONE; } } if ((!BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_ADD_NODE) || (!BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_ADD_NODE)) { normalize_eq_adds_exp (btor, e0, e1, &tmp1, &tmp2); btor_release_exp (btor, e0); btor_release_exp (btor, e1); e0 = tmp1; e1 = tmp2; real_e0 = BTOR_REAL_ADDR_NODE (e0); real_e1 = BTOR_REAL_ADDR_NODE (e1); } } result = rewrite_binary_exp (btor, kind, e0, e1); if (!result) { BTOR_REWRITE_EQ_NODE_NO_REWRITE: result = btor_eq_exp_node (btor, e0, e1); } DONE: btor_release_exp (btor, e0); btor_release_exp (btor, e1); return result; } BtorNode * btor_rewrite_add_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *e0_norm, *e1_norm, *temp; int normalized; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_regular_binary_bv_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); normalized = 0; /* boolean case */ if (BTOR_REAL_ADDR_NODE (e0)->len == 1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ADD_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_xor_exp (btor, e0, e1); BTOR_DEC_REC_RW_CALL (btor); return result; } /* a - a == 0 */ if (!BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_ADD_NODE && e0 == BTOR_INVERT_NODE (e1->e[0]) && is_const_one_exp (btor, e1->e[1])) { return btor_zero_exp (btor, e1->len); } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0)) && !BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_ADD_NODE) { /* recursion is no problem here, as one call leads to * folding of constants, and the other call can not * trigger the same kind of recursion anymore */ if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ADD_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_add_exp (btor, e0, e1->e[0]); result = btor_rewrite_add_exp (btor, temp, e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ADD_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_add_exp (btor, e0, e1->e[1]); result = btor_rewrite_add_exp (btor, temp, e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } } else if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1)) && !BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_ADD_NODE) { /* recursion is no problem here, as one call leads to * folding of constants, and the other call can not * trigger the same kind of recursion anymore */ if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ADD_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_add_exp (btor, e1, e0->e[0]); result = btor_rewrite_add_exp (btor, temp, e0->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ADD_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); temp = btor_rewrite_add_exp (btor, e1, e0->e[1]); result = btor_rewrite_add_exp (btor, temp, e0->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); return result; } } if (btor->rewrite_level > 2 && BTOR_IS_INVERTED_NODE (e0) && btor->rec_rw_calls >= BTOR_REC_RW_BOUND && (temp = BTOR_REAL_ADDR_NODE (e0))->kind == BTOR_ADD_NODE) { BtorNode * e00 = temp->e[0]; BtorNode * e01 = temp->e[1]; BtorNode * one; BTOR_INC_REC_RW_CALL (btor); one = btor_one_exp (btor, temp->len); temp = btor_add_exp (btor, BTOR_INVERT_NODE (e00), BTOR_INVERT_NODE (e01)); result = btor_add_exp (btor, temp, one); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); btor_release_exp (btor, one); return result; } if (btor->rewrite_level > 2 && BTOR_IS_INVERTED_NODE (e1) && btor->rec_rw_calls >= BTOR_REC_RW_BOUND && (temp = BTOR_REAL_ADDR_NODE (e1))->kind == BTOR_ADD_NODE) { BtorNode * e10 = temp->e[0]; BtorNode * e11 = temp->e[1]; BtorNode * one; BTOR_INC_REC_RW_CALL (btor); one = btor_one_exp (btor, temp->len); temp = btor_add_exp (btor, BTOR_INVERT_NODE (e10), BTOR_INVERT_NODE (e11)); result = btor_add_exp (btor, temp, one); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, temp); btor_release_exp (btor, one); return result; } if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == BTOR_MUL_NODE && e1->kind == BTOR_MUL_NODE) { /* normalize muls on demand */ normalize_muls_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } result = rewrite_binary_exp (btor, BTOR_ADD_NODE, e0, e1); if (!result) { BTOR_REWRITE_ADD_NODE_NO_REWRITE: result = btor_add_exp_node (btor, e0, e1); } if (normalized) { btor_release_exp (btor, e0_norm); btor_release_exp (btor, e1_norm); } return result; } BtorNode * btor_rewrite_mul_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *left, *right; int normalized; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_regular_binary_bv_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); normalized = 0; /* we do not need the optimization for term * power_of_2_constant as * the AIG level does this optimization already */ /* boolean case */ if (BTOR_REAL_ADDR_NODE (e0)->len == 1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_and_exp (btor, e0, e1); BTOR_DEC_REC_RW_CALL (btor); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0)) && !BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_MUL_NODE) { if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_mul_exp (btor, e0, e1->e[0]); result = btor_rewrite_mul_exp (btor, left, e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_mul_exp (btor, e0, e1->e[1]); result = btor_rewrite_mul_exp (btor, left, e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); return result; } } else if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1)) && !BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_MUL_NODE) { if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_mul_exp (btor, e1, e0->e[0]); result = btor_rewrite_mul_exp (btor, left, e0->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1]))) { assert (!BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0]))); if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_mul_exp (btor, e1, e0->e[1]); result = btor_rewrite_mul_exp (btor, left, e0->e[0]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); return result; } } /* const * (t + const) =recursively= const * t + const * const */ if (btor->rewrite_level > 2) { if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0)) && BTOR_IS_REGULAR_NODE (e1) && e1->kind == BTOR_ADD_NODE && (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[0])) || BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1->e[1])))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_mul_exp (btor, e0, e1->e[0]); right = btor_rewrite_mul_exp (btor, e0, e1->e[1]); result = btor_rewrite_add_exp (btor, left, right); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); btor_release_exp (btor, right); return result; } if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1)) && BTOR_IS_REGULAR_NODE (e0) && e0->kind == BTOR_ADD_NODE && (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[0])) || BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e0->e[1])))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_MUL_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); left = btor_rewrite_mul_exp (btor, e1, e0->e[0]); right = btor_rewrite_mul_exp (btor, e1, e0->e[1]); result = btor_rewrite_add_exp (btor, left, right); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, left); btor_release_exp (btor, right); return result; } if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == BTOR_ADD_NODE && e1->kind == BTOR_ADD_NODE) { /* normalize adds on demand */ normalize_adds_exp (btor, e0, e1, &left, &right); normalized = 1; e0 = left; e1 = right; } } result = rewrite_binary_exp (btor, BTOR_MUL_NODE, e0, e1); if (!result) { BTOR_REWRITE_MUL_NODE_NO_REWRITE: result = btor_mul_exp_node (btor, e0, e1); } if (normalized) { btor_release_exp (btor, left); btor_release_exp (btor, right); } return result; } BtorNode * btor_rewrite_ult_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *e0_norm, *e1_norm, *temp; int normalized; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_regular_binary_bv_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); normalized = 0; if (BTOR_IS_INVERTED_NODE (e0) && BTOR_IS_INVERTED_NODE (e1)) { /* ~a < ~b is the same as b < a */ temp = BTOR_REAL_ADDR_NODE (e1); e1 = BTOR_REAL_ADDR_NODE (e0); e0 = temp; } /* boolean case */ if (BTOR_REAL_ADDR_NODE (e0)->len == 1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ULT_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (e0), e1); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2) { if (!BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == e1->kind) { switch (e0->kind) { case BTOR_CONCAT_NODE: assert (e1->kind == BTOR_CONCAT_NODE); if (e0->e[0] == e1->e[0]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ULT_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_ult_exp (btor, e0->e[1], e1->e[1]); BTOR_DEC_REC_RW_CALL (btor); return result; } else if (e0->e[1] == e1->e[1]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_ULT_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_ult_exp (btor, e0->e[0], e1->e[0]); BTOR_DEC_REC_RW_CALL (btor); return result; } break; case BTOR_ADD_NODE: assert (e1->kind == BTOR_ADD_NODE); normalize_adds_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; break; case BTOR_MUL_NODE: assert (e1->kind == BTOR_MUL_NODE); normalize_muls_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; break; default: break; } } } result = rewrite_binary_exp (btor, BTOR_ULT_NODE, e0, e1); if (!result) { BTOR_REWRITE_ULT_NODE_NO_REWRITE: result = btor_ult_exp_node (btor, e0, e1); } if (normalized) { btor_release_exp (btor, e0_norm); btor_release_exp (btor, e1_norm); } return result; } BtorNode * btor_rewrite_sll_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_shift_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); result = rewrite_binary_exp (btor, BTOR_SLL_NODE, e0, e1); if (!result) result = btor_sll_exp_node (btor, e0, e1); return result; } BtorNode * btor_rewrite_srl_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_shift_exp_dbg (btor, e0, e1)); result = rewrite_binary_exp (btor, BTOR_SRL_NODE, e0, e1); if (!result) result = btor_srl_exp_node (btor, e0, e1); return result; } BtorNode * btor_rewrite_udiv_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *e0_norm, *e1_norm; int normalized; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_regular_binary_bv_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); normalized = 0; /* we do not need the optimization for term / power_of_2_constant as * the AIG level does this optimization already */ /* boolean case */ if (BTOR_REAL_ADDR_NODE (e0)->len == 1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_UDIV_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = BTOR_INVERT_NODE ( btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (e0), e1)); BTOR_DEC_REC_RW_CALL (btor); return result; } /* normalize adds and muls on demand */ if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == e1->kind) { if (e0->kind == BTOR_ADD_NODE) { assert (e1->kind == BTOR_ADD_NODE); normalize_adds_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } else if (e0->kind == BTOR_MUL_NODE) { assert (e1->kind == BTOR_MUL_NODE); normalize_muls_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } } result = rewrite_binary_exp (btor, BTOR_UDIV_NODE, e0, e1); if (!result) { BTOR_REWRITE_UDIV_NODE_NO_REWRITE: result = btor_udiv_exp_node (btor, e0, e1); } if (normalized) { btor_release_exp (btor, e0_norm); btor_release_exp (btor, e1_norm); } return result; } BtorNode * btor_rewrite_urem_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *e0_norm, *e1_norm; int normalized; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_regular_binary_bv_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); normalized = 0; /* we do not need the optimization for term % power_of_2_constant as * the AIG level does this optimization already */ /* boolean case */ if (BTOR_REAL_ADDR_NODE (e0)->len == 1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_UREM_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_and_exp (btor, e0, BTOR_INVERT_NODE (e1)); BTOR_DEC_REC_RW_CALL (btor); return result; } /* normalize adds and muls on demand */ if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e0) && !BTOR_IS_INVERTED_NODE (e1) && e0->kind == e1->kind) { if (e0->kind == BTOR_ADD_NODE) { assert (e1->kind == BTOR_ADD_NODE); normalize_adds_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } else if (e0->kind == BTOR_MUL_NODE) { assert (e1->kind == BTOR_MUL_NODE); normalize_muls_exp (btor, e0, e1, &e0_norm, &e1_norm); normalized = 1; e0 = e0_norm; e1 = e1_norm; } } result = rewrite_binary_exp (btor, BTOR_UREM_NODE, e0, e1); if (!result) { BTOR_REWRITE_UREM_NODE_NO_REWRITE: result = btor_urem_exp_node (btor, e0, e1); } if (normalized) { btor_release_exp (btor, e0_norm); btor_release_exp (btor, e1_norm); } return result; } static int btor_concat_simplifiable (BtorNode * exp) { BtorNode * real_exp = BTOR_REAL_ADDR_NODE (exp); switch (real_exp->kind) { case BTOR_BV_VAR_NODE: case BTOR_BV_CONST_NODE: return 1; } return 0; } BtorNode * btor_rewrite_concat_exp (Btor * btor, BtorNode * e0, BtorNode * e1) { BtorNode *result, *temp, *cur, * left, * right, * real_e0, * real_e1; BtorNodePtrStack stack, po_stack; BtorNode *t, *e; BtorMemMgr *mm; int i; e0 = btor_pointer_chase_simplified_exp (btor, e0); e1 = btor_pointer_chase_simplified_exp (btor, e1); assert (btor_precond_concat_exp_dbg (btor, e0, e1)); assert (btor->rewrite_level > 0); mm = btor->mm; if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (e1)) && BTOR_REAL_ADDR_NODE (e0)->kind == BTOR_CONCAT_NODE && BTOR_IS_BV_CONST_NODE ( BTOR_REAL_ADDR_NODE (BTOR_REAL_ADDR_NODE (e0)->e[1]))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_CONCAT_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); if (!BTOR_IS_INVERTED_NODE (e0)) { temp = btor_rewrite_concat_exp (btor, e0->e[1], e1); result = btor_rewrite_concat_exp (btor, e0->e[0], temp); btor_release_exp (btor, temp); } else { temp = btor_rewrite_concat_exp (btor, BTOR_INVERT_NODE (BTOR_REAL_ADDR_NODE (e0)->e[1]), e1); result = btor_rewrite_concat_exp (btor, BTOR_INVERT_NODE (BTOR_REAL_ADDR_NODE (e0)->e[0]), temp); btor_release_exp (btor, temp); } BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 0 && (BTOR_IS_INVERTED_NODE (e0) == BTOR_IS_INVERTED_NODE (e1)) && (real_e0 = BTOR_REAL_ADDR_NODE (e0))->kind == BTOR_SLICE_NODE && (real_e1 = BTOR_REAL_ADDR_NODE (e1))->kind == BTOR_SLICE_NODE && real_e0->e[0] == real_e1->e[0] && real_e0->lower == real_e1->upper + 1) { BTOR_INC_REC_RW_CALL (btor); result = btor_slice_exp (btor, real_e0->e[0], real_e0->upper, real_e1->lower); BTOR_DEC_REC_RW_CALL (btor); if (BTOR_IS_INVERTED_NODE (e0)) result = BTOR_INVERT_NODE (result); return result; } /* normalize concats --> left-associative */ if (btor->rewrite_level > 2 && BTOR_REAL_ADDR_NODE (e1)->kind == BTOR_CONCAT_NODE) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_CONCAT_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); BTOR_INIT_STACK (po_stack); BTOR_PUSH_STACK (mm, po_stack, e0); BTOR_INIT_STACK (stack); BTOR_PUSH_STACK (mm, stack, e1); do { cur = BTOR_POP_STACK (stack); if (BTOR_REAL_ADDR_NODE (cur)->kind == BTOR_CONCAT_NODE) { BTOR_PUSH_STACK (mm, stack, BTOR_COND_INVERT_NODE (cur, BTOR_REAL_ADDR_NODE (cur)->e[1])); BTOR_PUSH_STACK (mm, stack, BTOR_COND_INVERT_NODE (cur, BTOR_REAL_ADDR_NODE (cur)->e[0])); } else BTOR_PUSH_STACK (mm, po_stack, cur); } while (!BTOR_EMPTY_STACK (stack)); assert (BTOR_COUNT_STACK (po_stack) >= 3); result = btor_rewrite_concat_exp (btor, po_stack.start[0], po_stack.start[1]); for (i = 2; i < BTOR_COUNT_STACK (po_stack); i++) { cur = po_stack.start[i]; assert (BTOR_REAL_ADDR_NODE (cur)->kind != BTOR_CONCAT_NODE); temp = btor_rewrite_concat_exp (btor, result, cur); btor_release_exp (btor, result); result = temp; } BTOR_RELEASE_STACK (mm, stack); BTOR_RELEASE_STACK (mm, po_stack); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_CONCAT_NODE_NO_REWRITE; if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_AND_NODE && (btor_concat_simplifiable (e0->e[0]) || btor_concat_simplifiable (e0->e[1]))) { BTOR_INC_REC_RW_CALL (btor); left = btor_concat_exp (btor, e0->e[0], e1); right = btor_concat_exp (btor, e0->e[1], e1); result = btor_and_exp (btor, left, right); btor_release_exp (btor, right); btor_release_exp (btor, left); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e0) && e0->kind == BTOR_BCOND_NODE && (btor_concat_simplifiable (e0->e[1]) || btor_concat_simplifiable (e0->e[2]))) { BTOR_INC_REC_RW_CALL (btor); t = btor_concat_exp (btor, e0->e[1], e1); e = btor_concat_exp (btor, e0->e[2], e1); result = btor_cond_exp (btor, e0->e[0], t, e); btor_release_exp (btor, e); btor_release_exp (btor, t); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && BTOR_IS_INVERTED_NODE (e0) && (real_e0 = BTOR_REAL_ADDR_NODE (e0))->kind == BTOR_AND_NODE && (btor_concat_simplifiable (real_e0->e[0]) || btor_concat_simplifiable (real_e0->e[1]))) { BTOR_INC_REC_RW_CALL (btor); left = btor_concat_exp (btor, real_e0->e[0], BTOR_INVERT_NODE (e1)); right = btor_concat_exp (btor, real_e0->e[1], BTOR_INVERT_NODE (e1)); result = btor_and_exp (btor, left, right); result = BTOR_INVERT_NODE (result); btor_release_exp (btor, right); btor_release_exp (btor, left); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && BTOR_IS_INVERTED_NODE (e0) && (real_e0 = BTOR_REAL_ADDR_NODE (e0))->kind == BTOR_BCOND_NODE && (btor_concat_simplifiable (real_e0->e[1]) || btor_concat_simplifiable (real_e0->e[2]))) { BTOR_INC_REC_RW_CALL (btor); t = btor_concat_exp (btor, BTOR_INVERT_NODE (real_e0->e[1]), e1); e = btor_concat_exp (btor, BTOR_INVERT_NODE (real_e0->e[2]), e1); result = btor_cond_exp (btor, real_e0->e[0], t, e); btor_release_exp (btor, e); btor_release_exp (btor, t); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_AND_NODE && (btor_concat_simplifiable (e1->e[0]) || btor_concat_simplifiable (e1->e[1]))) { BTOR_INC_REC_RW_CALL (btor); left = btor_concat_exp (btor, e0, e1->e[0]); right = btor_concat_exp (btor, e0, e1->e[1]); result = btor_and_exp (btor, left, right); btor_release_exp (btor, right); btor_release_exp (btor, left); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e1) && e1->kind == BTOR_BCOND_NODE && (btor_concat_simplifiable (e1->e[1]) || btor_concat_simplifiable (e1->e[2]))) { BTOR_INC_REC_RW_CALL (btor); t = btor_concat_exp (btor, e0, e1->e[1]); e = btor_concat_exp (btor, e0, e1->e[2]); result = btor_cond_exp (btor, e1->e[0], t, e); btor_release_exp (btor, e); btor_release_exp (btor, t); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && BTOR_IS_INVERTED_NODE (e1) && (real_e1 = BTOR_REAL_ADDR_NODE (e1))->kind == BTOR_AND_NODE && (btor_concat_simplifiable (real_e1->e[0]) || btor_concat_simplifiable (real_e1->e[1]))) { BTOR_INC_REC_RW_CALL (btor); left = btor_concat_exp (btor, BTOR_INVERT_NODE (e0), real_e1->e[0]); right = btor_concat_exp (btor, BTOR_INVERT_NODE (e0), real_e1->e[1]); result = btor_and_exp (btor, left, right); result = BTOR_INVERT_NODE (result); btor_release_exp (btor, right); btor_release_exp (btor, left); BTOR_DEC_REC_RW_CALL (btor); return result; } if (btor->rewrite_level > 2 && BTOR_IS_INVERTED_NODE (e1) && (real_e1 = BTOR_REAL_ADDR_NODE (e1))->kind == BTOR_BCOND_NODE && (btor_concat_simplifiable (real_e1->e[1]) || btor_concat_simplifiable (real_e1->e[2]))) { BTOR_INC_REC_RW_CALL (btor); t = btor_concat_exp (btor, e0, BTOR_INVERT_NODE (real_e1->e[1])); e = btor_concat_exp (btor, e0, BTOR_INVERT_NODE (real_e1->e[2])); result = btor_cond_exp (btor, real_e1->e[0], t, e); btor_release_exp (btor, e); btor_release_exp (btor, t); BTOR_DEC_REC_RW_CALL (btor); return result; } result = rewrite_binary_exp (btor, BTOR_CONCAT_NODE, e0, e1); if (!result) { BTOR_REWRITE_CONCAT_NODE_NO_REWRITE: result = btor_concat_exp_node (btor, e0, e1); } return result; } BtorNode * btor_rewrite_read_exp (Btor * btor, BtorNode * e_array, BtorNode * e_index) { BtorNode *result, *cur_array, *write_index; int propagations; /* no recurisve rewrite calls here, so we do not need to check bounds */ e_array = btor_pointer_chase_simplified_exp (btor, e_array); e_index = btor_pointer_chase_simplified_exp (btor, e_index); assert (btor_precond_read_exp_dbg (btor, e_array, e_index)); assert (btor->rewrite_level > 0); if (BTOR_IS_WRITE_NODE (e_array)) { write_index = e_array->e[1]; /* if read index is equal write index, then return write value */ if (e_index == write_index) return btor_copy_exp (btor, e_array->e[2]); cur_array = e_array; assert (BTOR_IS_REGULAR_NODE (cur_array)); assert (BTOR_IS_ARRAY_NODE (cur_array)); propagations = 0; do { assert (BTOR_IS_WRITE_NODE (cur_array)); write_index = cur_array->e[1]; if (e_index == write_index) return btor_copy_exp (btor, cur_array->e[2]); if (is_always_unequal (btor, e_index, write_index)) { cur_array = cur_array->e[0]; assert (BTOR_IS_REGULAR_NODE (cur_array)); assert (BTOR_IS_ARRAY_NODE (cur_array)); propagations++; btor->stats.read_props_construct++; } else break; } while (BTOR_IS_WRITE_NODE (cur_array) && propagations < BTOR_READ_OVER_WRITE_DOWN_PROPAGATION_LIMIT); result = btor_read_exp_node (btor, cur_array, e_index); } else result = btor_read_exp_node (btor, e_array, e_index); assert (result); return result; } BtorNode * btor_rewrite_write_exp (Btor * btor, BtorNode * e_array, BtorNode * e_index, BtorNode * e_value) { BtorNode *cur, *cur_write, *temp, *result; BtorNode *chain[BTOR_WRITE_CHAIN_NODE_RW_BOUND]; int depth; /* no recurisve rewrite calls here, so we do not need to check bounds */ e_array = btor_pointer_chase_simplified_exp (btor, e_array); e_index = btor_pointer_chase_simplified_exp (btor, e_index); e_value = btor_pointer_chase_simplified_exp (btor, e_value); assert (btor_precond_write_exp_dbg (btor, e_array, e_index, e_value)); assert (btor->rewrite_level > 0); result = 0; if (btor->rewrite_level > 2 && BTOR_IS_WRITE_NODE (e_array)) { depth = 0; cur = e_array; assert (BTOR_IS_REGULAR_NODE (cur)); assert (BTOR_IS_WRITE_NODE (cur)); while (BTOR_IS_WRITE_NODE (cur) && cur->e[1] != e_index && depth < BTOR_WRITE_CHAIN_NODE_RW_BOUND) { assert (BTOR_IS_REGULAR_NODE (cur)); assert (BTOR_IS_WRITE_NODE (cur)); chain[depth++] = cur; cur = cur->e[0]; assert (BTOR_IS_REGULAR_NODE (cur)); assert (BTOR_IS_ARRAY_NODE (cur)); } if (depth < BTOR_WRITE_CHAIN_NODE_RW_BOUND && BTOR_IS_WRITE_NODE (cur)) { assert (cur->e[1] == e_index); /* we overwrite this position anyhow, so we can skip * this intermediate write */ cur = btor_copy_exp (btor, cur->e[0]); depth--; while (depth >= 0) { cur_write = chain[depth--]; assert (BTOR_IS_REGULAR_NODE (cur_write)); assert (BTOR_IS_WRITE_NODE (cur_write)); temp = btor_write_exp_node (btor, cur, cur_write->e[1], cur_write->e[2]); btor_release_exp (btor, cur); cur = temp; } result = btor_write_exp_node (btor, cur, e_index, e_value); btor_release_exp (btor, cur); } } if (!result) result = btor_write_exp_node (btor, e_array, e_index, e_value); return result; } BtorNode * btor_rewrite_cond_exp (Btor * btor, BtorNode * e_cond, BtorNode * e_if, BtorNode * e_else) { BtorNode *(*fptr) (Btor *, BtorNode *, BtorNode *); BtorNode *result, *tmp1, *tmp2, *tmp3, *tmp4; BtorNodeKind kind; e_cond = btor_pointer_chase_simplified_exp (btor, e_cond); e_if = btor_pointer_chase_simplified_exp (btor, e_if); e_else = btor_pointer_chase_simplified_exp (btor, e_else); assert (btor_precond_cond_exp_dbg (btor, e_cond, e_if, e_else)); assert (btor->rewrite_level > 0); result = 0; kind = BTOR_BCOND_NODE; /* normalization: ~e0 ? e1 : e2 is the same as e0 ? e2: e1 */ if (BTOR_IS_INVERTED_NODE (e_cond)) { e_cond = BTOR_INVERT_NODE (e_cond); tmp1 = e_if; e_if = e_else; e_else = tmp1; } assert (!BTOR_IS_INVERTED_NODE (e_cond)); if (BTOR_IS_ARRAY_NODE (BTOR_REAL_ADDR_NODE (e_if))) kind = BTOR_ACOND_NODE; if (e_if == e_else) { result = btor_copy_exp (btor, e_if); return result; } if (BTOR_IS_BV_CONST_NODE (e_cond)) { if (e_cond->bits[0] == '1') result = btor_copy_exp (btor, e_if); else result = btor_copy_exp (btor, e_else); return result; } if (BTOR_IS_ARRAY_OR_BV_COND_NODE (BTOR_REAL_ADDR_NODE (e_if))) { if (BTOR_REAL_ADDR_NODE (e_if)->e[0] == e_cond) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_cond_exp (btor, e_cond, BTOR_COND_INVERT_NODE (e_if, BTOR_REAL_ADDR_NODE (e_if)->e[1]), e_else); BTOR_DEC_REC_RW_CALL (btor); return result; } tmp1 = BTOR_REAL_ADDR_NODE (e_if)->e[0]; if (BTOR_IS_INVERTED_NODE (e_if)) { tmp2 = BTOR_INVERT_NODE (BTOR_REAL_ADDR_NODE (e_if)->e[1]); tmp3 = BTOR_INVERT_NODE (BTOR_REAL_ADDR_NODE (e_if)->e[2]); } else { tmp2 = e_if->e[1]; tmp3 = e_if->e[2]; } if (tmp2 == e_else) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp4 = btor_rewrite_and_exp (btor, e_cond, BTOR_INVERT_NODE (tmp1)); result = btor_rewrite_cond_exp (btor, tmp4, tmp3, e_else); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp4); return result; } if (tmp3 == e_else) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp4 = btor_rewrite_and_exp (btor, e_cond, tmp1); result = btor_rewrite_cond_exp (btor, tmp4, tmp2, e_else); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp4); return result; } } if (BTOR_IS_ARRAY_OR_BV_COND_NODE (BTOR_REAL_ADDR_NODE (e_else))) { if (BTOR_REAL_ADDR_NODE (e_else)->e[0] == e_cond) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); result = btor_rewrite_cond_exp (btor, e_cond, e_if, BTOR_COND_INVERT_NODE (e_else, BTOR_REAL_ADDR_NODE (e_else)->e[2])); BTOR_DEC_REC_RW_CALL (btor); return result; } tmp1 = BTOR_REAL_ADDR_NODE (e_else)->e[0]; if (BTOR_IS_INVERTED_NODE (e_else)) { tmp2 = BTOR_INVERT_NODE (BTOR_REAL_ADDR_NODE (e_else)->e[1]); tmp3 = BTOR_INVERT_NODE (BTOR_REAL_ADDR_NODE (e_else)->e[2]); } else { tmp2 = e_else->e[1]; tmp3 = e_else->e[2]; } if (tmp2 == e_if) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp4 = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (e_cond), BTOR_INVERT_NODE (tmp1)); result = btor_rewrite_cond_exp (btor, tmp4, tmp3, e_if); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp4); return result; } else if (tmp3 == e_if) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp4 = btor_rewrite_and_exp (btor, BTOR_INVERT_NODE (e_cond), tmp1); result = btor_rewrite_cond_exp (btor, tmp4, tmp2, e_if); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp4); return result; } } if (kind == BTOR_BCOND_NODE) { if (BTOR_REAL_ADDR_NODE (e_if)->len == 1) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_or_exp (btor, BTOR_INVERT_NODE (e_cond), e_if); tmp2 = btor_or_exp (btor, e_cond, e_else); result = btor_rewrite_and_exp (btor, tmp1, tmp2); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); btor_release_exp (btor, tmp2); } else if (!BTOR_IS_INVERTED_NODE (e_if) && e_if->kind == BTOR_ADD_NODE && ((e_if->e[0] == e_else && is_const_one_exp (btor, e_if->e[1])) || (e_if->e[1] == e_else && is_const_one_exp (btor, e_if->e[0])))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_uext_exp (btor, e_cond, BTOR_REAL_ADDR_NODE (e_if)->len - 1); result = btor_rewrite_add_exp (btor, e_else, tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); } else if (!BTOR_IS_INVERTED_NODE (e_else) && e_else->kind == BTOR_ADD_NODE && ((e_else->e[0] == e_if && is_const_one_exp (btor, e_else->e[1])) || (e_else->e[1] == e_if && is_const_one_exp (btor, e_else->e[0])))) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_uext_exp (btor, BTOR_INVERT_NODE (e_cond), BTOR_REAL_ADDR_NODE (e_if)->len - 1); result = btor_rewrite_add_exp (btor, e_if, tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); } else if (btor->rewrite_level > 2 && !BTOR_IS_INVERTED_NODE (e_if) && !BTOR_IS_INVERTED_NODE (e_else) && e_if->kind == e_else->kind) { fptr = 0; switch (e_if->kind) { case BTOR_ADD_NODE: fptr = btor_rewrite_add_exp; break; case BTOR_AND_NODE: fptr = btor_rewrite_and_exp; break; case BTOR_MUL_NODE: fptr = btor_rewrite_mul_exp; break; case BTOR_UDIV_NODE: fptr = btor_rewrite_udiv_exp; break; case BTOR_UREM_NODE: fptr = btor_rewrite_urem_exp; break; default: break; } if (fptr) { if (e_if->e[0] == e_else->e[0]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_cond_exp (btor, e_cond, e_if->e[1], e_else->e[1]); result = fptr (btor, e_if->e[0], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); } else if (e_if->e[1] == e_else->e[1]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_cond_exp (btor, e_cond, e_if->e[0], e_else->e[0]); result = fptr (btor, tmp1, e_if->e[1]); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); } else if (fptr != btor_rewrite_udiv_exp && fptr != btor_rewrite_urem_exp) { /* works only for commutative operators: */ if (e_if->e[0] == e_else->e[1]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_cond_exp (btor, e_cond, e_if->e[1], e_else->e[0]); result = fptr (btor, e_if->e[0], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); } else if (e_if->e[1] == e_else->e[0]) { if (btor->rec_rw_calls >= BTOR_REC_RW_BOUND) goto BTOR_REWRITE_COND_NODE_NO_REWRITE; BTOR_INC_REC_RW_CALL (btor); tmp1 = btor_rewrite_cond_exp (btor, e_cond, e_if->e[0], e_else->e[1]); result = fptr (btor, e_if->e[1], tmp1); BTOR_DEC_REC_RW_CALL (btor); btor_release_exp (btor, tmp1); } } } } } if (!result) { BTOR_REWRITE_COND_NODE_NO_REWRITE: result = btor_cond_exp_node (btor, e_cond, e_if, e_else); } return result; } boolector-1.5.118-6b56be4-121013/synthebtor.c0000664000175000017500000001242312031307056016763 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "stdio.h" #include "btorbtor.h" #include "btoraig.h" #include "btoraigvec.h" #include "btorhash.h" #include #include #define BTOR_HAVE_ISATTY #ifdef BTOR_HAVE_ISATTY #include #endif static void die (int prefix, const char * fmt, ...) { va_list ap; if (prefix) fputs ("*** synthebtor: ", stdout); va_start (ap, fmt); vfprintf (stdout, fmt, ap); va_end (ap); fputc ('\n', stdout); exit (1); } int main (int argc, char ** argv) { int i, j, verbosity, close_input, close_output, binary, merge, rwl; FILE * input_file, * output_file, * file; BtorAIG * aig, * tmp, * merged, ** p; BtorPtrHashTable * back_annotation; const char * input_name; const char * parse_error; BtorPtrHashBucket *b; BtorParseResult model; BtorAIGVecMgr * avmgr; BtorAIGPtrStack regs; BtorAIGPtrStack nexts; BtorAIGPtrStack aigs; BtorParseOpt parse_opt; BtorParser * parser; BtorAIGMgr * amgr; BtorMemMgr * mem; BtorAIGVec * av; Btor * btor; verbosity = 0; close_input = 0; close_output = 0; binary = 0; merge = 0; input_name = ""; input_file = stdin; output_file = stdout; rwl = 3; for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-h")) { printf ( "usage: synthebor [-h][-v][-m][-rwl[0123]][[]]\n"); exit (0); } else if (!strcmp (argv[i], "-v")) verbosity++; else if (!strcmp (argv[i], "-m")) merge = 1; else if (!strcmp (argv[i], "-rwl0")) rwl = 0; else if (!strcmp (argv[i], "-rwl1")) rwl = 1; else if (!strcmp (argv[i], "-rwl2")) rwl = 2; else if (!strcmp (argv[i], "-rwl3")) rwl = 3; else if (argv[i][0] == '-') die (1, "invalid command line option '%s'", argv[i]); else if (close_output) die (1, "too many files"); else if (close_input) { if (!strcmp (argv[i], input_name)) die (1, "input and output are the same"); if (!(file = fopen (argv[i], "w"))) die (1, "can not write '%s'", argv[i]); output_file = file; close_output = 1; } else if (!(file = fopen (argv[i], "r"))) die (1, "can not read '%s'", argv[i]); else { input_file = file; input_name = argv[i]; close_input = 1; } } btor = btor_new_btor (); btor_set_verbosity_btor (btor, verbosity); btor_set_rewrite_level_btor (btor, rwl); BTOR_CLR (&parse_opt); parser = btor_btor_parser_api ()->init (btor, &parse_opt); parse_error = btor_btor_parser_api()->parse (parser, 0, input_file, input_name, &model); if (parse_error) die (0, parse_error); if (!model.noutputs) die (1, "no roots in '%s'", input_name); if (model.nregs && merge) die (1, "can not merge registers"); mem = btor->mm; avmgr = btor->avmgr; amgr = btor_get_aig_mgr_aigvec_mgr (avmgr); back_annotation = btor_new_ptr_hash_table (mem, 0, 0); BTOR_INIT_STACK (regs); BTOR_INIT_STACK (nexts); for (i = 0; i < model.nregs; i++) { if (btor_is_array_exp (btor, model.regs[i])) die (1, "can not synthesize memories (yet)"); av = btor_exp_to_aigvec (btor, model.regs[i], back_annotation); for (j = 0; j < av->len; j++) { aig = btor_copy_aig (amgr, av->aigs[j]); BTOR_PUSH_STACK (mem, regs, aig); } btor_release_delete_aigvec (avmgr, av); av = btor_exp_to_aigvec (btor, model.nexts[i], back_annotation); for (j = 0; j < av->len; j++) { aig = btor_copy_aig (amgr, av->aigs[j]); BTOR_PUSH_STACK (mem, nexts, aig); } btor_release_delete_aigvec (avmgr, av); } BTOR_INIT_STACK (aigs); merged = BTOR_AIG_TRUE; for (i = 0; i < model.noutputs; i++) { av = btor_exp_to_aigvec (btor, model.outputs[i], back_annotation); for (j = 0; j < av->len; j++) { aig = av->aigs[j]; if (merge) { tmp = btor_and_aig (amgr, merged, aig); btor_release_aig (amgr, merged); merged = tmp; } else { aig = btor_copy_aig (amgr, aig); BTOR_PUSH_STACK (mem, aigs, aig); } } btor_release_delete_aigvec (avmgr, av); } if (merge) BTOR_PUSH_STACK (mem, aigs, merged); #ifdef BTOR_HAVE_ISATTY if (close_output || !isatty (1)) binary = 1; #endif assert (BTOR_COUNT_STACK (regs) == BTOR_COUNT_STACK (nexts)); btor_dump_aiger (amgr, binary, output_file, BTOR_COUNT_STACK (aigs), aigs.start, BTOR_COUNT_STACK (regs), regs.start, nexts.start, back_annotation); for (p = aigs.start; p < aigs.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, aigs); for (p = regs.start; p < regs.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, regs); for (p = nexts.start; p < nexts.top; p++) btor_release_aig (amgr, *p); BTOR_RELEASE_STACK (mem, nexts); for (b = back_annotation->first; b; b = b->next) btor_freestr (mem, b->data.asStr); btor_delete_ptr_hash_table (back_annotation); btor_btor_parser_api()->reset (parser); btor_delete_btor (btor); if (close_input) fclose (input_file); if (close_output) fclose (output_file); return 0; } boolector-1.5.118-6b56be4-121013/btorsat.c0000664000175000017500000004747112036252347016262 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifdef BTOR_USE_PICOSAT #include "../picosat/picosat.h" #endif #ifdef BTOR_USE_LINGELING #include "../lingeling/lglib.h" #endif #ifdef BTOR_USE_MINISAT #include "btorminisat.h" #endif #include "btorsat.h" #include "btorexit.h" #include "btorutil.h" #include #include #include #include #include /*------------------------------------------------------------------------*/ #define BTOR_ABORT_SAT(cond,msg) \ do { \ if (cond) \ { \ printf ("[btorsat] %s: %s\n", __func__, msg); \ fflush (stdout); \ exit (BTOR_ERR_EXIT); \ } \ } while (0) /*------------------------------------------------------------------------*/ void btor_msg_sat (BtorSATMgr * smgr, int level, const char *fmt, ...) { va_list ap; if (smgr->verbosity < level) return; assert (fmt != NULL); fprintf (stdout, "[btorsat] "); va_start (ap, fmt); vfprintf (stdout, fmt, ap); va_end (ap); putc ('\n', stdout); fflush (stdout); } /*------------------------------------------------------------------------*/ #if defined(BTOR_USE_LINGELING) int btor_enable_lingeling_sat (BtorSATMgr *, const char * optstr, int nofork); #define btor_enable_default_sat(SMGR) \ do { btor_enable_lingeling_sat ((SMGR), 0, 0); } while (0) #elif defined(BTOR_USE_PICOSAT) void btor_enable_picosat_sat (BtorSATMgr *); #define btor_enable_default_sat btor_enable_picosat_sat #elif defined(BTOR_USE_MINISAT) void btor_enable_minisat_sat (BtorSATMgr *); #define btor_enable_default_sat btor_enable_minisat_sat #else #error "no usable SAT solver configured" #endif /*------------------------------------------------------------------------*/ BtorSATMgr * btor_new_sat_mgr (BtorMemMgr * mm) { BtorSATMgr *smgr; assert (mm != NULL); BTOR_NEW (mm, smgr); smgr->verbosity = 0; smgr->mm = mm; smgr->satcalls = 0; smgr->initialized = 0; smgr->clauses = smgr->maxvar = 0; smgr->output = stdout; btor_enable_default_sat (smgr); return smgr; } void btor_set_verbosity_sat_mgr (BtorSATMgr * smgr, int verbosity) { assert (verbosity >= -1 && verbosity <= 3); smgr->verbosity = verbosity; } int btor_is_initialized_sat (BtorSATMgr * smgr) { assert (smgr != NULL); return smgr->initialized; } int btor_next_cnf_id_sat_mgr (BtorSATMgr * smgr) { int result; assert (smgr); assert (smgr->initialized); result = smgr->api.inc_max_var (smgr); if (abs (result) > smgr->maxvar) smgr->maxvar = abs (result); BTOR_ABORT_SAT (result <= 0, "CNF id overflow"); if (smgr->verbosity > 2 && !(result % 100000)) btor_msg_sat (smgr, 2, "reached CNF id %d", result); return result; } void btor_release_cnf_id_sat_mgr (BtorSATMgr * smgr, int lit) { assert (smgr); if (!smgr->initialized) return; assert (abs (lit) <= smgr->maxvar); if (abs (lit) == smgr->true_lit) return; if (smgr->api.melt) smgr->api.melt (smgr, lit); } int btor_get_last_cnf_id_sat_mgr (BtorSATMgr * smgr) { assert (smgr != NULL); assert (smgr->initialized); (void) smgr; return smgr->api.variables (smgr); } void btor_delete_sat_mgr (BtorSATMgr * smgr) { assert (smgr != NULL); /* if SAT is still initialized, then * reset_sat has not been called */ if (smgr->initialized) btor_reset_sat (smgr); BTOR_DELETE (smgr->mm, smgr); } /*------------------------------------------------------------------------*/ void btor_init_sat (BtorSATMgr * smgr) { assert (smgr != NULL); assert (!smgr->initialized); smgr->solver = smgr->api.init (smgr); smgr->initialized = 1; smgr->inc_required = 1; smgr->sat_time = 0; smgr->used_that_inc_was_not_required = 0; smgr->true_lit = btor_next_cnf_id_sat_mgr (smgr); btor_add_sat (smgr, smgr->true_lit); btor_add_sat (smgr, 0); } void btor_set_output_sat (BtorSATMgr * smgr, FILE * output) { char * prefix, * q; const char * p; assert (smgr != NULL); assert (smgr->initialized); assert (output != NULL); (void) smgr; smgr->api.set_output (smgr, output); smgr->output = output; prefix = btor_malloc (smgr->mm, strlen (smgr->name) + 4); sprintf (prefix, "[%s] ", smgr->name); q = prefix + 1; for (p = smgr->name; *p; p++) *q++ = tolower (*p); smgr->api.set_prefix (smgr, prefix); btor_free (smgr->mm, prefix, strlen (smgr->name) + 4); } void btor_enable_verbosity_sat (BtorSATMgr * smgr) { assert (smgr != NULL); assert (smgr->initialized); (void) smgr; smgr->api.enable_verbosity (smgr); } void btor_print_stats_sat (BtorSATMgr * smgr) { assert (smgr != NULL); if (!smgr->initialized) return; smgr->api.stats (smgr); btor_msg_sat (smgr, 0, "%d SAT calls in %.1f seconds", smgr->satcalls, smgr->sat_time); } void btor_add_sat (BtorSATMgr * smgr, int lit) { assert (smgr != NULL); assert (smgr->initialized); assert (abs (lit) <= smgr->maxvar); assert (!smgr->satcalls || smgr->inc_required); if (!lit) smgr->clauses++; (void) smgr->api.add (smgr, lit); } int btor_sat_sat (BtorSATMgr * smgr, int limit) { double start = btor_time_stamp (); int res; assert (smgr != NULL); assert (smgr->initialized); btor_msg_sat (smgr, 2, "calling SAT solver %s", smgr->name); assert (!smgr->satcalls || smgr->inc_required); smgr->satcalls++; res = smgr->api.sat (smgr, limit); smgr->sat_time += btor_time_stamp () - start; return res; } int btor_deref_sat (BtorSATMgr * smgr, int lit) { (void) smgr; assert (smgr != NULL); assert (smgr->initialized); assert (abs (lit) <= smgr->maxvar); return smgr->api.deref (smgr, lit); } int btor_repr_sat (BtorSATMgr * smgr, int lit) { (void) smgr; assert (smgr != NULL); assert (smgr->initialized); assert (abs (lit) <= smgr->maxvar); return smgr->api.repr (smgr, lit); } void btor_reset_sat (BtorSATMgr * smgr) { assert (smgr != NULL); assert (smgr->initialized); btor_msg_sat (smgr, 2, "resetting %s", smgr->name); smgr->api.reset (smgr); smgr->solver = 0; smgr->initialized = 0; } int btor_fixed_sat (BtorSATMgr * smgr, int lit) { int res; assert (smgr != NULL); assert (smgr->initialized); assert (abs (lit) <= smgr->maxvar); res = smgr->api.fixed (smgr, lit); return res; } /*------------------------------------------------------------------------*/ void btor_assume_sat (BtorSATMgr * smgr, int lit) { assert (smgr != NULL); assert (smgr->initialized); assert (abs (lit) <= smgr->maxvar); assert (!smgr->satcalls || smgr->inc_required); smgr->api.assume (smgr, lit); } int btor_failed_sat (BtorSATMgr * smgr, int lit) { (void) smgr; assert (smgr != NULL); assert (smgr->initialized); assert (abs (lit) <= smgr->maxvar); return smgr->api.failed (smgr, lit); } int btor_inconsistent_sat (BtorSATMgr * smgr) { (void) smgr; assert (smgr != NULL); assert (smgr->initialized); return smgr->api.inconsistent (smgr); } int btor_changed_sat (BtorSATMgr * smgr) { (void) smgr; assert (smgr != NULL); assert (smgr->initialized); return smgr->api.changed (smgr); } /*------------------------------------------------------------------------*/ #ifdef BTOR_USE_PICOSAT static void * btor_picosat_init (BtorSATMgr * smgr) { PicoSAT * res; btor_msg_sat (smgr, 1, "PicoSAT Version %s", picosat_version ()); res = picosat_minit (smgr->mm, (picosat_malloc) btor_malloc, (picosat_realloc) btor_realloc, (picosat_free) btor_free); picosat_set_global_default_phase (res, 0); return res; } static void btor_picosat_add (BtorSATMgr * smgr, int lit) { (void) picosat_add (smgr->solver, lit); } static int btor_picosat_sat (BtorSATMgr *smgr, int limit) { return picosat_sat (smgr->solver, limit); } static int btor_picosat_changed (BtorSATMgr * smgr) { return picosat_changed (smgr->solver); } static int btor_picosat_deref (BtorSATMgr * smgr, int lit) { return picosat_deref (smgr->solver, lit); } static int btor_picosat_repr (BtorSATMgr * smgr, int lit) { (void) smgr; return lit; } static void btor_picosat_reset (BtorSATMgr * smgr) { picosat_reset (smgr->solver); smgr->solver = 0; } static void btor_picosat_set_output (BtorSATMgr * smgr, FILE * output) { picosat_set_output (smgr->solver, output); } static void btor_picosat_set_prefix (BtorSATMgr * smgr, const char * prefix) { picosat_set_prefix (smgr->solver, prefix); } static void btor_picosat_enable_verbosity (BtorSATMgr * smgr) { picosat_set_verbosity (smgr->solver, 1); } static int btor_picosat_inc_max_var (BtorSATMgr * smgr) { return picosat_inc_max_var (smgr->solver); } static int btor_picosat_variables (BtorSATMgr * smgr) { return picosat_variables (smgr->solver); } static void btor_picosat_stats (BtorSATMgr *smgr) { picosat_stats (smgr->solver); } static int btor_picosat_fixed (BtorSATMgr * smgr, int lit) { int res; res = picosat_deref_toplevel (smgr->solver, lit); return res; } /*------------------------------------------------------------------------*/ static void btor_picosat_assume (BtorSATMgr * smgr, int lit) { (void) picosat_assume (smgr->solver, lit); } static int btor_picosat_failed (BtorSATMgr * smgr, int lit) { return picosat_failed_assumption (smgr->solver, lit); } static int btor_picosat_inconsistent (BtorSATMgr * smgr) { return picosat_inconsistent (smgr->solver); } /*------------------------------------------------------------------------*/ void btor_enable_picosat_sat (BtorSATMgr * smgr) { assert (smgr != NULL); BTOR_ABORT_SAT (smgr->initialized, "'btor_init_sat' called before 'btor_enable_picosat_sat'"); smgr->name = "PicoSAT"; smgr->optstr = 0; smgr->api.add = btor_picosat_add; smgr->api.assume = btor_picosat_assume; smgr->api.changed = btor_picosat_changed; smgr->api.deref = btor_picosat_deref; smgr->api.enable_verbosity = btor_picosat_enable_verbosity; smgr->api.failed = btor_picosat_failed; smgr->api.fixed = btor_picosat_fixed; smgr->api.inc_max_var = btor_picosat_inc_max_var; smgr->api.inconsistent = btor_picosat_inconsistent; smgr->api.init = btor_picosat_init; smgr->api.melt = 0; smgr->api.repr = btor_picosat_repr; smgr->api.reset = btor_picosat_reset; smgr->api.sat = btor_picosat_sat; smgr->api.set_output = btor_picosat_set_output; smgr->api.set_prefix = btor_picosat_set_prefix; smgr->api.stats = btor_picosat_stats; smgr->api.variables = btor_picosat_variables; btor_msg_sat (smgr, 1, "PicoSAT allows both incremental and non-incremental mode"); } #endif /*------------------------------------------------------------------------*/ #ifdef BTOR_USE_LINGELING typedef struct BtorLGL BtorLGL; struct BtorLGL { LGL * lgl; int nforked, blimit; }; static int btor_passdown_lingeling_options (BtorSATMgr * smgr, const char * optstr, LGL * external_lgl) { char * str, * p, * next, * eq, * opt, * val; LGL * lgl = external_lgl ? external_lgl : 0; int len, valid, res = 1; assert (optstr); len = strlen (optstr); BTOR_NEWN (smgr->mm, str, len + 1); strcpy (str, optstr); res = 1; for (p = str; *p; p = next) { if (*p == ',') next = p + 1; else { opt = p; while (*p != ',' && *p) p++; if (*p) { assert (*p == ','); *p = 0; next = p + 1; } else next = p; val = eq = 0; if (!isalpha (*opt)) valid = 0; else { for (p = opt + 1; isalnum (*p); p++) ; if (*p == '=') { *(eq = p++) = 0; val = p; if (*p == '-') p++; if (isdigit (*p)) { while (isdigit (*p)) p++; valid = !*p; } else valid = 0; } else valid = 0; } if (valid) { if (!lgl) { assert (!external_lgl); lgl = lglinit (); } if (lglhasopt (lgl, opt)) { if (external_lgl && val) { assert (lgl == external_lgl); btor_msg_sat (smgr, 2, "setting Lingeling option --%s=%s", opt, val); lglsetopt (lgl, opt, atoi (val)); } } else valid = 0; } if (!valid) res = 0; if (valid || external_lgl) continue; if (eq) *eq = '='; btor_msg_sat (smgr, 0, "*** can not pass down to Lingeling invalid option '%s'", optstr); } } BTOR_DELETEN (smgr->mm, str, len + 1); if (lgl && !external_lgl) lglrelease (lgl); return res; } #define BTOR_LGL_SIMP_DELAY 2000 #define BTOR_LGL_MIN_BLIMIT 50000 #define BTOR_LGL_MAX_BLIMIT 200000 static void * btor_lingeling_init (BtorSATMgr * smgr) { BtorLGL * res; if (smgr->verbosity >= 1) { lglbnr ("Lingeling", "[lingeling] ", stdout); fflush (stdout); } BTOR_CNEW (smgr->mm, res); res->lgl = lglminit (smgr->mm, (lglalloc) btor_malloc, (lglrealloc) btor_realloc, (lgldealloc) btor_free); res->blimit = BTOR_LGL_MIN_BLIMIT; assert (res); if (smgr->optstr) btor_passdown_lingeling_options (smgr, smgr->optstr, res->lgl); return res; } static void btor_lingeling_add (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; lgladd (blgl->lgl, lit); } static int btor_lingeling_sat (BtorSATMgr * smgr, int limit) { BtorLGL * blgl = smgr->solver; LGL * lgl = blgl->lgl, * bforked; const int clone = 1; // TODO? const char * str; int res, bfres; char name[80]; lglsetopt (lgl, "simpdelay", BTOR_LGL_SIMP_DELAY); if (!smgr->inc_required) { lglsetopt (lgl, "clim", -1); res = lglsat (lgl); return res; } lglsetopt (lgl, "flipping", 0); if (smgr->nofork || (0 <= limit && limit < blgl->blimit)) { if (limit < INT_MAX) lglsetopt (lgl, "clim", limit); res = lglsat (lgl); } else { btor_msg_sat (smgr, 1, "blimit = %d", blgl->blimit); lglsetopt (lgl, "clim", blgl->blimit); if (!(res = lglsat (lgl))) { blgl->blimit *= 2; if (blgl->blimit > BTOR_LGL_MAX_BLIMIT) blgl->blimit = BTOR_LGL_MAX_BLIMIT; blgl->nforked++; if (clone) { bforked = lglclone (lgl); lglfixate (bforked); lglmeltall (bforked); str = "clone"; } else bforked = lglbrutefork (lgl, 0), str = "fork"; lglsetopt (bforked, "seed", blgl->nforked); lglsetopt (bforked, "flipping", 1); lglsetopt (bforked, "simpdelay", 0); sprintf (name, "[lgl%s%d] ", str, blgl->nforked); lglsetprefix (bforked, name); lglsetout (bforked, smgr->output); if (lglgetopt (lgl, "verbose")) lglsetopt (bforked, "verbose", 1); lglsetopt (bforked, "clim", limit); res = lglsat (bforked); if (smgr->verbosity > 0) lglstats (bforked); if (clone) { bfres = lglunclone (lgl, bforked); lglrelease (bforked); } else bfres = lgljoin (lgl, bforked); assert (!res || bfres == res); res = bfres; } else { blgl->blimit = 9*(blgl->blimit/10); if (blgl->blimit < BTOR_LGL_MIN_BLIMIT) blgl->blimit = BTOR_LGL_MIN_BLIMIT; } } return res; } static int btor_lingeling_changed (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; return lglchanged (blgl->lgl); } static int btor_lingeling_deref (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; return lglderef (blgl->lgl, lit); } static int btor_lingeling_repr (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; return lglrepr (blgl->lgl, lit); } static void btor_lingeling_reset (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; lglrelease (blgl->lgl); BTOR_DELETE (smgr->mm, blgl); } static void btor_lingeling_set_output (BtorSATMgr * smgr, FILE * output) { BtorLGL * blgl = smgr->solver; lglsetout (blgl->lgl, output); } static void btor_lingeling_set_prefix (BtorSATMgr * smgr, const char * prefix) { BtorLGL * blgl = smgr->solver; lglsetprefix (blgl->lgl, prefix); } static void btor_lingeling_enable_verbosity (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; lglsetopt (blgl->lgl, "verbose", 1); } static int btor_lingeling_inc_max_var (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; int res = lglincvar (blgl->lgl); if (smgr->inc_required) lglfreeze (blgl->lgl, res); else smgr->used_that_inc_was_not_required = 1; return res; } static int btor_lingeling_variables (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; return lglmaxvar (blgl->lgl); } static void btor_lingeling_stats (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; lglstats (blgl->lgl); btor_msg_sat (smgr, 1, "%d forked", blgl->nforked); } /*------------------------------------------------------------------------*/ static void btor_lingeling_assume (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; lglassume (blgl->lgl, lit); } static void btor_lingeling_melt (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; if (smgr->inc_required) { assert (!smgr->used_that_inc_was_not_required); lglmelt (blgl->lgl, lit); } } static int btor_lingeling_failed (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; return lglfailed (blgl->lgl, lit); } static int btor_lingeling_fixed (BtorSATMgr * smgr, int lit) { BtorLGL * blgl = smgr->solver; return lglfixed (blgl->lgl, lit); } static int btor_lingeling_inconsistent (BtorSATMgr * smgr) { BtorLGL * blgl = smgr->solver; return lglinconsistent (blgl->lgl); } /*------------------------------------------------------------------------*/ int btor_enable_lingeling_sat (BtorSATMgr * smgr, const char * optstr, int nofork) { assert (smgr != NULL); BTOR_ABORT_SAT (smgr->initialized, "'btor_init_sat' called before 'btor_enable_lingeling_sat'"); if ((smgr->optstr = optstr) && !btor_passdown_lingeling_options (smgr, optstr, 0)) return 0; smgr->name = "Lingeling"; smgr->nofork = nofork; smgr->api.add = btor_lingeling_add; smgr->api.assume = btor_lingeling_assume; smgr->api.changed = btor_lingeling_changed; smgr->api.deref = btor_lingeling_deref; smgr->api.enable_verbosity = btor_lingeling_enable_verbosity; smgr->api.failed = btor_lingeling_failed; smgr->api.fixed = btor_lingeling_fixed; smgr->api.inc_max_var = btor_lingeling_inc_max_var; smgr->api.inconsistent = btor_lingeling_inconsistent; smgr->api.init = btor_lingeling_init; smgr->api.melt = btor_lingeling_melt; smgr->api.repr = btor_lingeling_repr; smgr->api.reset = btor_lingeling_reset; smgr->api.sat = btor_lingeling_sat; smgr->api.set_output = btor_lingeling_set_output; smgr->api.set_prefix = btor_lingeling_set_prefix; smgr->api.stats = btor_lingeling_stats; smgr->api.variables = btor_lingeling_variables; btor_msg_sat (smgr, 1, "Lingeling allows both incremental and non-incremental mode"); return 1; } #endif /*------------------------------------------------------------------------*/ #ifdef BTOR_USE_MINISAT /*------------------------------------------------------------------------*/ void btor_enable_minisat_sat (BtorSATMgr * smgr) { assert (smgr != NULL); BTOR_ABORT_SAT (smgr->initialized, "'btor_init_sat' called before 'btor_enable_minisat_sat'"); smgr->name = "MiniSAT"; smgr->optstr = 0; smgr->api.add = btor_minisat_add; smgr->api.assume = btor_minisat_assume; smgr->api.changed = btor_minisat_changed; smgr->api.deref = btor_minisat_deref; smgr->api.enable_verbosity = btor_minisat_enable_verbosity; smgr->api.failed = btor_minisat_failed; smgr->api.fixed = btor_minisat_fixed; smgr->api.inc_max_var = btor_minisat_inc_max_var; smgr->api.inconsistent = btor_minisat_inconsistent; smgr->api.init = btor_minisat_init; smgr->api.melt = 0; smgr->api.repr = btor_minisat_repr; smgr->api.reset = btor_minisat_reset; smgr->api.sat = btor_minisat_sat; smgr->api.set_output = btor_minisat_set_output; smgr->api.set_prefix = btor_minisat_set_prefix; smgr->api.stats = btor_minisat_stats; smgr->api.variables = btor_minisat_variables; btor_msg_sat (smgr, 1, "MiniSAT allows both incremental and non-incremental mode"); } #endif /*------------------------------------------------------------------------*/ boolector-1.5.118-6b56be4-121013/btorexit.h0000664000175000017500000000101511761140525016427 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTOREXIT_H_INCLUDED #define BTOREXIT_H_INCLUDED enum BtorExitCode { BTOR_SUCC_EXIT = 0, BTOR_ERR_EXIT = 1, BTOR_SAT_EXIT = 10, BTOR_UNSAT_EXIT = 20, BTOR_UNKNOWN_EXIT = 0 }; typedef enum BtorExitCode BtorExitCode; #endif boolector-1.5.118-6b56be4-121013/btoraigvec.c0000664000175000017500000004262611761140525016724 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btoraigvec.h" #include "btorutil.h" #include #include #include #include /*------------------------------------------------------------------------*/ struct BtorAIGVecMgr { BtorMemMgr *mm; BtorAIGMgr *amgr; int verbosity; }; /*------------------------------------------------------------------------*/ static BtorAIGVec * new_aigvec (BtorAIGVecMgr * avmgr, int len) { BtorAIGVec *result; assert (avmgr); assert (len > 0); BTOR_NEW (avmgr->mm, result); BTOR_NEWN (avmgr->mm, result->aigs, len); result->len = len; return result; } BtorAIGVec * btor_const_aigvec (BtorAIGVecMgr * avmgr, const char *bits) { BtorAIGVec *result; int i, len; assert (avmgr); assert (bits); len = (int) strlen (bits); assert (len > 0); result = new_aigvec (avmgr, len); for (i = 0; i < len; i++) result->aigs[i] = bits[i] == '0' ? BTOR_AIG_FALSE : BTOR_AIG_TRUE; return result; } BtorAIGVec * btor_var_aigvec (BtorAIGVecMgr * avmgr, int len) { BtorAIGVec *result; int i; assert (avmgr); assert (len > 0); result = new_aigvec (avmgr, len); for (i = len - 1; i >= 0; i--) result->aigs[i] = btor_var_aig (avmgr->amgr); return result; } void btor_invert_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av) { int i, len; (void) avmgr; assert (avmgr); assert (av); assert (av->len > 0); len = av->len; for (i = 0; i < len; i++) av->aigs[i] = BTOR_INVERT_AIG (av->aigs[i]); } BtorAIGVec * btor_not_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av) { BtorAIGVec *result; int i, len; assert (avmgr); assert (av); assert (av->len > 0); len = av->len; result = new_aigvec (avmgr, len); for (i = 0; i < len; i++) result->aigs[i] = btor_not_aig (avmgr->amgr, av->aigs[i]); return result; } BtorAIGVec * btor_slice_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av, int upper, int lower) { BtorAIGVec *result; int i, len, diff, counter; assert (avmgr); assert (av); assert (av->len > 0); assert (upper < av->len); assert (lower >= 0); assert (lower <= upper); counter = 0; len = av->len; diff = upper - lower; result = new_aigvec (avmgr, diff + 1); for (i = len - upper - 1; i <= len - upper - 1 + diff; i++) result->aigs[counter++] = btor_copy_aig (avmgr->amgr, av->aigs[i]); return result; } BtorAIGVec * btor_and_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGVec *result; int i, len; assert (avmgr); assert (av1); assert (av2); assert (av1->len == av2->len); assert (av1->len > 0); len = av1->len; result = new_aigvec (avmgr, len); for (i = 0; i < len; i++) result->aigs[i] = btor_and_aig (avmgr->amgr, av1->aigs[i], av2->aigs[i]); return result; } static BtorAIG * lt_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGMgr *amgr; BtorAIG *res, *tmp, *term0, *term1; int i; amgr = avmgr->amgr; res = BTOR_AIG_FALSE; for (i = av1->len - 1; i >= 0; i--) { term0 = btor_and_aig (amgr, av1->aigs[i], BTOR_INVERT_AIG (av2->aigs[i])); tmp = btor_and_aig (amgr, BTOR_INVERT_AIG (term0), res); btor_release_aig (amgr, term0); btor_release_aig (amgr, res); res = tmp; term1 = btor_and_aig (amgr, BTOR_INVERT_AIG (av1->aigs[i]), av2->aigs[i]); tmp = btor_or_aig (amgr, term1, res); btor_release_aig (amgr, term1); btor_release_aig (amgr, res); res = tmp; } return res; } BtorAIGVec * btor_ult_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGVec *result; assert (avmgr); assert (av1); assert (av2); assert (av1->len == av2->len); assert (av1->len > 0); result = new_aigvec (avmgr, 1); result->aigs[0] = lt_aigvec (avmgr, av1, av2); return result; } BtorAIGVec * btor_eq_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGMgr *amgr; BtorAIGVec *result; BtorAIG *result_aig, *temp1, *temp2; int i, len; assert (avmgr); assert (av1); assert (av2); assert (av1->len == av2->len); assert (av1->len > 0); amgr = avmgr->amgr; len = av1->len; result = new_aigvec (avmgr, 1); result_aig = btor_eq_aig (amgr, av1->aigs[0], av2->aigs[0]); for (i = 1; i < len; i++) { temp1 = btor_eq_aig (amgr, av1->aigs[i], av2->aigs[i]); temp2 = btor_and_aig (amgr, result_aig, temp1); btor_release_aig (amgr, temp1); btor_release_aig (amgr, result_aig); result_aig = temp2; } result->aigs[0] = result_aig; return result; } static BtorAIG * half_adder (BtorAIGMgr * amgr, BtorAIG * x, BtorAIG * y, BtorAIG ** cout) { BtorAIG *res, *x_and_y, *not_x, *not_y, *not_x_and_not_y, *x_xnor_y; x_and_y = btor_and_aig (amgr, x, y); not_x = BTOR_INVERT_AIG (x); not_y = BTOR_INVERT_AIG (y); not_x_and_not_y = btor_and_aig (amgr, not_x, not_y); x_xnor_y = btor_or_aig (amgr, x_and_y, not_x_and_not_y); res = BTOR_INVERT_AIG (x_xnor_y); *cout = x_and_y; btor_release_aig (amgr, not_x_and_not_y); return res; } static BtorAIG * full_adder (BtorAIGMgr * amgr, BtorAIG * x, BtorAIG * y, BtorAIG * cin, BtorAIG ** cout) { BtorAIG *sum, *c1, *c2, *res; sum = half_adder (amgr, x, y, &c1); res = half_adder (amgr, sum, cin, &c2); *cout = btor_or_aig (amgr, c1, c2); btor_release_aig (amgr, sum); btor_release_aig (amgr, c1); btor_release_aig (amgr, c2); return res; } BtorAIGVec * btor_add_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGMgr *amgr; BtorAIGVec *result; BtorAIG *cout, *cin; int i; assert (avmgr); assert (av1); assert (av2); assert (av1->len == av2->len); assert (av1->len > 0); amgr = avmgr->amgr; result = new_aigvec (avmgr, av1->len); cout = cin = BTOR_AIG_FALSE; /* for 'cout' to avoid warning */ for (i = av1->len - 1; i >= 0; i--) { result->aigs[i] = full_adder (amgr, av1->aigs[i], av2->aigs[i], cin, &cout); btor_release_aig (amgr, cin); cin = cout; } btor_release_aig (amgr, cout); return result; } static BtorAIGVec * btor_sll_n_bits_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av, int n, BtorAIG * shift) { BtorAIGMgr *amgr; BtorAIGVec *result; BtorAIG *and1, *and2, *not_shift; int i, len; assert (avmgr); assert (av); assert (av->len > 0); assert (n >= 0); assert (n < av->len); if (n == 0) return btor_copy_aigvec (avmgr, av); amgr = avmgr->amgr; len = av->len; not_shift = btor_not_aig (amgr, shift); result = new_aigvec (avmgr, len); for (i = 0; i < len - n; i++) { and1 = btor_and_aig (amgr, av->aigs[i], not_shift); and2 = btor_and_aig (amgr, av->aigs[i + n], shift); result->aigs[i] = btor_or_aig (amgr, and1, and2); btor_release_aig (amgr, and1); btor_release_aig (amgr, and2); } for (i = len - n; i < len; i++) result->aigs[i] = btor_and_aig (amgr, av->aigs[i], not_shift); btor_release_aig (amgr, not_shift); return result; } BtorAIGVec * btor_sll_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGVec *result, *temp; int i, len; assert (avmgr); assert (av1); assert (av2); assert (av1->len > 1); assert (btor_is_power_of_2_util (av1->len)); assert (btor_log_2_util (av1->len) == av2->len); len = av2->len; result = btor_sll_n_bits_aigvec (avmgr, av1, 1, av2->aigs[av2->len - 1]); for (i = len - 2; i >= 0; i--) { temp = result; result = btor_sll_n_bits_aigvec (avmgr, temp, btor_pow_2_util (len - i - 1), av2->aigs[i]); btor_release_delete_aigvec (avmgr, temp); } return result; } static BtorAIGVec * btor_srl_n_bits_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av, int n, BtorAIG * shift) { BtorAIGMgr *amgr; BtorAIGVec *result; BtorAIG *and1, *and2, *not_shift; int i, len; assert (avmgr); assert (av); assert (av->len > 0); assert (n >= 0); assert (n < av->len); if (n == 0) return btor_copy_aigvec (avmgr, av); amgr = avmgr->amgr; len = av->len; not_shift = btor_not_aig (amgr, shift); result = new_aigvec (avmgr, len); for (i = 0; i < n; i++) result->aigs[i] = btor_and_aig (amgr, av->aigs[i], not_shift); for (i = n; i < len; i++) { and1 = btor_and_aig (amgr, av->aigs[i], not_shift); and2 = btor_and_aig (amgr, av->aigs[i - n], shift); result->aigs[i] = btor_or_aig (amgr, and1, and2); btor_release_aig (amgr, and1); btor_release_aig (amgr, and2); } btor_release_aig (amgr, not_shift); return result; } BtorAIGVec * btor_srl_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGVec *result, *temp; int i, len; assert (avmgr); assert (av1); assert (av2); assert (av1->len > 1); assert (btor_is_power_of_2_util (av1->len)); assert (btor_log_2_util (av1->len) == av2->len); len = av2->len; result = btor_srl_n_bits_aigvec (avmgr, av1, 1, av2->aigs[av2->len - 1]); for (i = len - 2; i >= 0; i--) { temp = result; result = btor_srl_n_bits_aigvec (avmgr, temp, btor_pow_2_util (len - i - 1), av2->aigs[i]); btor_release_delete_aigvec (avmgr, temp); } return result; } static BtorAIGVec * mul_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * a, BtorAIGVec * b) { BtorAIG *cin, *cout, *and, *tmp; BtorAIGMgr *amgr; BtorAIGVec *res; int len, i, j; len = a->len; amgr = btor_get_aig_mgr_aigvec_mgr (avmgr); assert (len > 0); res = new_aigvec (avmgr, len); for (j = 0; j < len; j++) res->aigs[j] = btor_and_aig (amgr, a->aigs[j], b->aigs[len - 1]); for (i = len - 2; i >= 0; i--) { cout = BTOR_AIG_FALSE; for (j = i; j >= 0; j--) { and = btor_and_aig (amgr, a->aigs[len - 1 - i + j], b->aigs[i]); tmp = res->aigs[j]; cin = cout; res->aigs[j] = full_adder (amgr, tmp, and, cin, &cout); btor_release_aig (amgr, and); btor_release_aig (amgr, tmp); btor_release_aig (amgr, cin); } btor_release_aig (amgr, cout); } return res; } BtorAIGVec * btor_mul_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * a, BtorAIGVec * b) { return mul_aigvec (avmgr, a, b); } static void btor_SC_GATE_CO_aigvec (BtorAIGMgr * amgr, BtorAIG ** CO, BtorAIG * R, BtorAIG * D, BtorAIG * CI) { BtorAIG *D_or_CI, *D_and_CI, *M; D_or_CI = btor_or_aig (amgr, D, CI); D_and_CI = btor_and_aig (amgr, D, CI); M = btor_and_aig (amgr, D_or_CI, R); *CO = btor_or_aig (amgr, M, D_and_CI); btor_release_aig (amgr, D_or_CI); btor_release_aig (amgr, D_and_CI); btor_release_aig (amgr, M); } static void btor_SC_GATE_S_aigvec (BtorAIGMgr * amgr, BtorAIG ** S, BtorAIG * R, BtorAIG * D, BtorAIG * CI, BtorAIG * Q) { BtorAIG *D_and_CI, *D_or_CI; BtorAIG *T2_or_R, *T2_and_R; BtorAIG *T1, *T2; D_or_CI = btor_or_aig (amgr, D, CI); D_and_CI = btor_and_aig (amgr, D, CI); T1 = btor_and_aig (amgr, D_or_CI, BTOR_INVERT_AIG (D_and_CI)); T2 = btor_and_aig (amgr, T1, Q); T2_or_R = btor_or_aig (amgr, T2, R); T2_and_R = btor_and_aig (amgr, T2, R); *S = btor_and_aig (amgr, T2_or_R, BTOR_INVERT_AIG (T2_and_R)); btor_release_aig (amgr, T1); btor_release_aig (amgr, T2); btor_release_aig (amgr, D_and_CI); btor_release_aig (amgr, D_or_CI); btor_release_aig (amgr, T2_and_R); btor_release_aig (amgr, T2_or_R); } static void udiv_urem_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * Ain, BtorAIGVec * Din, BtorAIGVec ** Qptr, BtorAIGVec ** Rptr) { BtorAIG **A, **nD, ***S, ***C; BtorAIGVec *Q, *R; BtorAIGMgr *amgr; BtorMemMgr *mem; int size, i, j; size = Ain->len; assert (size > 0); amgr = btor_get_aig_mgr_aigvec_mgr (avmgr); mem = avmgr->mm; BTOR_NEWN (mem, A, size); for (i = 0; i < size; i++) A[i] = Ain->aigs[size - 1 - i]; BTOR_NEWN (mem, nD, size); for (i = 0; i < size; i++) nD[i] = BTOR_INVERT_AIG (Din->aigs[size - 1 - i]); BTOR_NEWN (mem, S, size + 1); for (j = 0; j <= size; j++) { BTOR_NEWN (mem, S[j], size + 1); for (i = 0; i <= size; i++) S[j][i] = BTOR_AIG_FALSE; } BTOR_NEWN (mem, C, size + 1); for (j = 0; j <= size; j++) { BTOR_NEWN (mem, C[j], size + 1); for (i = 0; i <= size; i++) C[j][i] = BTOR_AIG_FALSE; } R = new_aigvec (avmgr, size); Q = new_aigvec (avmgr, size); for (j = 0; j <= size - 1; j++) { S[j][0] = btor_copy_aig (amgr, A[size - j - 1]); C[j][0] = BTOR_AIG_TRUE; for (i = 0; i <= size - 1; i++) btor_SC_GATE_CO_aigvec (amgr, &C[j][i + 1], S[j][i], nD[i], C[j][i]); Q->aigs[j] = btor_or_aig (amgr, C[j][size], S[j][size]); for (i = 0; i <= size - 1; i++) btor_SC_GATE_S_aigvec (amgr, &S[j + 1][i + 1], S[j][i], nD[i], C[j][i], Q->aigs[j]); } for (i = size; i >= 1; i--) R->aigs[size - i] = btor_copy_aig (amgr, S[size][i]); for (j = 0; j <= size; j++) { for (i = 0; i <= size; i++) btor_release_aig (amgr, C[j][i]); BTOR_DELETEN (mem, C[j], size + 1); } BTOR_DELETEN (mem, C, size + 1); for (j = 0; j <= size; j++) { for (i = 0; i <= size; i++) btor_release_aig (amgr, S[j][i]); BTOR_DELETEN (mem, S[j], size + 1); } BTOR_DELETEN (mem, S, size + 1); BTOR_DELETEN (mem, nD, size); BTOR_DELETEN (mem, A, size); *Qptr = Q; *Rptr = R; } BtorAIGVec * btor_udiv_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGVec *quotient = 0; BtorAIGVec *remainder = 0; assert (avmgr); assert (av1); assert (av2); assert (av1->len == av2->len); assert (av1->len > 0); udiv_urem_aigvec (avmgr, av1, av2, "ient, &remainder); btor_release_delete_aigvec (avmgr, remainder); return quotient; } BtorAIGVec * btor_urem_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGVec *quotient, *remainder; assert (avmgr); assert (av1); assert (av2); assert (av1->len == av2->len); assert (av1->len > 0); udiv_urem_aigvec (avmgr, av1, av2, "ient, &remainder); btor_release_delete_aigvec (avmgr, quotient); return remainder; } BtorAIGVec * btor_concat_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av1, BtorAIGVec * av2) { BtorAIGMgr *amgr; BtorAIGVec *result; int i, pos, len_av1, len_av2; assert (avmgr); assert (av1); assert (av2); assert (av1->len > 0); assert (av2->len > 0); assert (INT_MAX - av1->len >= av2->len); pos = 0; amgr = avmgr->amgr; len_av1 = av1->len; len_av2 = av2->len; result = new_aigvec (avmgr, len_av1 + len_av2); for (i = 0; i < len_av1; i++) result->aigs[pos++] = btor_copy_aig (amgr, av1->aigs[i]); for (i = 0; i < len_av2; i++) result->aigs[pos++] = btor_copy_aig (amgr, av2->aigs[i]); return result; } BtorAIGVec * btor_cond_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av_cond, BtorAIGVec * av_if, BtorAIGVec * av_else) { BtorAIGMgr *amgr; BtorAIGVec *result; int i, len; assert (avmgr); assert (av_cond); assert (av_if); assert (av_else); assert (av_cond->len == 1); assert (av_if->len == av_else->len); assert (av_if->len > 0); amgr = avmgr->amgr; len = av_if->len; result = new_aigvec (avmgr, len); for (i = 0; i < len; i++) result->aigs[i] = btor_cond_aig (amgr, av_cond->aigs[0], av_if->aigs[i], av_else->aigs[i]); return result; } BtorAIGVec * btor_copy_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av) { BtorAIGMgr *amgr; BtorAIGVec *result; int i, len; assert (avmgr); assert (av); amgr = avmgr->amgr; len = av->len; result = new_aigvec (avmgr, len); for (i = 0; i < len; i++) result->aigs[i] = btor_copy_aig (amgr, av->aigs[i]); return result; } void btor_aigvec_to_sat_tseitin (BtorAIGVecMgr * avmgr, BtorAIGVec * av) { BtorAIGMgr *amgr; int i, len; assert (avmgr); assert (av); amgr = btor_get_aig_mgr_aigvec_mgr (avmgr); len = av->len; for (i = 0; i < len; i++) btor_aig_to_sat_tseitin (amgr, av->aigs[i]); } void btor_release_delete_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av) { BtorMemMgr *mm; BtorAIGMgr *amgr; int i, len; assert (avmgr); assert (av); assert (av->len > 0); mm = avmgr->mm; amgr = avmgr->amgr; len = av->len; for (i = 0; i < len; i++) btor_release_aig (amgr, av->aigs[i]); BTOR_DELETEN (mm, av->aigs, len); BTOR_DELETE (mm, av); } BtorAIGVecMgr * btor_new_aigvec_mgr (BtorMemMgr * mm) { BtorAIGVecMgr *avmgr; assert (mm); BTOR_NEW (mm, avmgr); avmgr->mm = mm; avmgr->verbosity = 0; avmgr->amgr = btor_new_aig_mgr (mm); return avmgr; } void btor_set_verbosity_aigvec_mgr (BtorAIGVecMgr * avmgr, int verbosity) { assert (avmgr); assert (verbosity >= -1 && verbosity <= 3); avmgr->verbosity = verbosity; } void btor_delete_aigvec_mgr (BtorAIGVecMgr * avmgr) { assert (avmgr); btor_delete_aig_mgr (avmgr->amgr); BTOR_DELETE (avmgr->mm, avmgr); } BtorAIGMgr * btor_get_aig_mgr_aigvec_mgr (const BtorAIGVecMgr * avmgr) { assert (avmgr); return avmgr->amgr; } char * btor_assignment_aigvec (BtorAIGVecMgr * avmgr, BtorAIGVec * av) { BtorAIGMgr *amgr; int i, len, cur; char *result; assert (avmgr); assert (av); assert (av->len > 0); amgr = avmgr->amgr; len = av->len; BTOR_NEWN (avmgr->mm, result, len + 1); for (i = 0; i < len; i++) { cur = btor_get_assignment_aig (amgr, av->aigs[i]); assert (cur >= -1); assert (cur <= 1); if (cur == 1) result[i] = '1'; else if (cur == -1) result[i] = '0'; else result[i] = 'x'; } result[i] = '\0'; return result; } boolector-1.5.118-6b56be4-121013/btoraig.h0000664000175000017500000001060511761140525016223 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #ifndef BTORAIG_H_INCLUDED #define BTORAIG_H_INCLUDED #include "btorstack.h" #include "btormem.h" #include "btorsat.h" #include "btorhash.h" #include /*------------------------------------------------------------------------*/ struct BtorAIG { int id; unsigned int refs; struct BtorAIG *children[2]; struct BtorAIG *next; int cnf_id; unsigned mark; unsigned local; }; typedef struct BtorAIG BtorAIG; typedef struct BtorAIGMgr BtorAIGMgr; BTOR_DECLARE_STACK (AIGPtr, BtorAIG *); /*------------------------------------------------------------------------*/ #define BTOR_AIG_FALSE (( BtorAIG *) 0ul) #define BTOR_AIG_TRUE (( BtorAIG *) 1ul) #define BTOR_IS_CONST_AIG(aig) \ (((aig) == BTOR_AIG_TRUE) || ((aig) == BTOR_AIG_FALSE)) #define BTOR_INVERT_AIG(aig) \ (( BtorAIG *) (1ul ^ (unsigned long int) (aig))) #define BTOR_IS_INVERTED_AIG(aig) (1ul & (unsigned long int) (aig)) #define BTOR_REAL_ADDR_AIG(aig) \ (( BtorAIG *) (~1ul & (unsigned long int) (aig))) #define BTOR_IS_VAR_AIG(aig) (!(aig)->children[0]) #define BTOR_IS_AND_AIG(aig) ((aig)->children[0]) #define BTOR_LEFT_CHILD_AIG(aig) ((aig)->children[0]) #define BTOR_RIGHT_CHILD_AIG(aig) ((aig)->children[1]) #define BTOR_GET_CNF_ID_AIG(aig) \ ((aig) == BTOR_AIG_TRUE ? 1 : \ ((aig) == BTOR_AIG_FALSE ? -1 : \ (BTOR_IS_INVERTED_AIG(aig) ? \ -BTOR_REAL_ADDR_AIG(aig)->cnf_id : (aig)->cnf_id))) /*------------------------------------------------------------------------*/ /* Creates new AIG manager. An AIG manager is used by nearly all functions * of the AIG layer. */ BtorAIGMgr *btor_new_aig_mgr (BtorMemMgr * mm); /* Sets verbosity [-1,3] */ void btor_set_verbosity_aig_mgr (BtorAIGMgr * amgr, int verbosity); /* Gets SAT manager of AIG manager. */ BtorSATMgr *btor_get_sat_mgr_aig_mgr (const BtorAIGMgr * amgr); /* Deletes AIG manager from memory. */ void btor_delete_aig_mgr (BtorAIGMgr * amgr); /* Variable representing 1 bit. */ BtorAIG *btor_var_aig (BtorAIGMgr * amgr); /* Inverter. */ BtorAIG *btor_not_aig (BtorAIGMgr * amgr, BtorAIG * aig); /* Logical AND. */ BtorAIG *btor_and_aig (BtorAIGMgr * amgr, BtorAIG * left, BtorAIG * right); /* Logical OR. */ BtorAIG *btor_or_aig (BtorAIGMgr * amgr, BtorAIG * left, BtorAIG * right); /* Logical EQUIVALENCE. */ BtorAIG *btor_eq_aig (BtorAIGMgr * amgr, BtorAIG * left, BtorAIG * right); /* If then Else. */ BtorAIG *btor_cond_aig (BtorAIGMgr * amgr, BtorAIG * aig_cond, BtorAIG * aig_if, BtorAIG * aig_else); /* Copies AIG (increments reference counter). */ BtorAIG *btor_copy_aig (BtorAIGMgr * amgr, BtorAIG * aig); /* Releases AIG (decrements reference counter). * If reference counter reaches 0, * then also the children are released * and AIG is deleted from memory. */ void btor_release_aig (BtorAIGMgr * amgr, BtorAIG * aig); /* Dumps AIG in AIGER format to file. */ void btor_dump_aig (BtorAIGMgr * amgr, int binary, FILE * output, BtorAIG * aig); /* Dumps AIGs in AIGER format to file. */ void btor_dump_aigs (BtorAIGMgr * amgr, int binary, FILE * output, int naigs, BtorAIG ** aigs, BtorPtrHashTable * back_annotation); /* Dumps sequential AIGER model to file. */ void btor_dump_aiger (BtorAIGMgr * amgr, int binary, FILE * output, int naigs, BtorAIG ** aigs, int nregs, BtorAIG ** regs, BtorAIG ** nexts, BtorPtrHashTable * back_annotation); /* Translates AIG into SAT instance. */ void btor_aig_to_sat (BtorAIGMgr * amgr, BtorAIG * aig); /* As 'btor_aig_to_sat' but also add the argument as new SAT constraint. * Actually this will result in less constraints being generated. */ void btor_add_toplevel_aig_to_sat (BtorAIGMgr *, BtorAIG *); /* Translates AIG into SAT instance in both phases. * The function guarantees that after finishing every reachable AIG * has a CNF id. */ void btor_aig_to_sat_tseitin (BtorAIGMgr * amgr, BtorAIG * aig); /* Solves SAT instance with root AIG aig. */ int btor_sat_aig (BtorAIGMgr * amgr, BtorAIG * aig); /* Gets current assignment of AIG aig (in the SAT case). * Do not call before calling btor_sat_aig. */ int btor_get_assignment_aig (BtorAIGMgr * amgr, BtorAIG * aig); #endif boolector-1.5.118-6b56be4-121013/examples/0000775000175000017500000000000012036253615016240 5ustar bierebiereboolector-1.5.118-6b56be4-121013/examples/bv/0000775000175000017500000000000012036253574016653 5ustar bierebiereboolector-1.5.118-6b56be4-121013/examples/bv/bv1.c0000664000175000017500000000357212033627211017504 0ustar bierebiere#include "../../boolector.h" #include #include #include #define BV1_EXAMPLE_NUM_BITS 8 /* We verify the XOR swap algorithm. The XOR bitwise operation can * be used to swap variables without using a temporary variable: * int x, y; * ... * x = x ^ y * y = x ^ y * x = x ^ y */ int main (void) { Btor *btor; BtorNode *x, *y, *temp, *old_x, *old_y, *eq1, *eq2, *and, *formula; int result; btor = boolector_new (); x = boolector_var (btor, BV1_EXAMPLE_NUM_BITS, NULL); y = boolector_var (btor, BV1_EXAMPLE_NUM_BITS, NULL); /* remember initial values of x and y */ old_x = boolector_copy (btor, x); old_y = boolector_copy (btor, y); /* x = x ^ y */ temp = boolector_xor (btor, x, y); boolector_release (btor, x); x = temp; /* y = x ^ y */ temp = boolector_xor (btor, x, y); boolector_release (btor, y); y = temp; /* x = x ^ y */ temp = boolector_xor (btor, x, y); boolector_release (btor, x); x = temp; /* Now, we have to show that old_x = y and old_y = x */ eq1 = boolector_eq (btor, old_x, y); eq2 = boolector_eq (btor, old_y, x); and = boolector_and (btor, eq1, eq2); /* In order to prove that this is a theorem, we negate the whole * formula and show that the negation is unsatisfiable */ formula = boolector_not (btor, and); /* We assert the formula and call Boolector */ boolector_assert (btor, formula); result = boolector_sat (btor); if (result == BOOLECTOR_UNSAT) printf ("Formula is unsatisfiable\n"); else abort (); /* cleanup */ boolector_release (btor, x); boolector_release (btor, old_x); boolector_release (btor, y); boolector_release (btor, old_y); boolector_release (btor, eq1); boolector_release (btor, eq2); boolector_release (btor, and); boolector_release (btor, formula); assert (boolector_get_refs (btor) == 0); boolector_delete (btor); return 0; } boolector-1.5.118-6b56be4-121013/examples/bv/.gitignore0000664000175000017500000000001011760722571020633 0ustar bierebierebv1 bv2 boolector-1.5.118-6b56be4-121013/examples/bv/makefile0000664000175000017500000000020412033627211020335 0ustar bierebiereinclude ../makefile.common all: $(CC) $(CFLAGS) bv1.c -o bv1 $(LIBS) $(CC) $(CFLAGS) bv2.c -o bv2 $(LIBS) clean: rm -f bv1 bv2 boolector-1.5.118-6b56be4-121013/examples/bv/bv2.c0000664000175000017500000000652112033627211017502 0ustar bierebiere#include "../../boolector.h" #include #include #include #define BV2_EXAMPLE_NUM_BITS 8 /* We try to show the following theorem: * v1 > 0 & v2 > 0 => v1 + v2 > 0 * * The theorem is valid if v1 and v2 are naturals, but not if they * are two's complement bit-vectors as addition can overflow. */ int main (void) { Btor *btor; BtorNode *v1, *v2, *add, *zero, *vars_sgt_zero, *impl; BtorNode *v1_sgt_zero, *v2_sgt_zero, *add_sgt_zero, *formula; char *assignments[10]; int result, i; btor = boolector_new (); boolector_enable_model_gen (btor); v1 = boolector_var (btor, BV2_EXAMPLE_NUM_BITS, NULL); v2 = boolector_var (btor, BV2_EXAMPLE_NUM_BITS, NULL); zero = boolector_zero (btor, BV2_EXAMPLE_NUM_BITS); v1_sgt_zero = boolector_sgt (btor, v1, zero); v2_sgt_zero = boolector_sgt (btor, v2, zero); vars_sgt_zero = boolector_and (btor, v1_sgt_zero, v2_sgt_zero); add = boolector_add (btor, v1, v2); add_sgt_zero = boolector_sgt (btor, add, zero); impl = boolector_implies (btor, vars_sgt_zero, add_sgt_zero); /* We negate the formula and try to show that the negation is unsatisfiable */ formula = boolector_not (btor, impl); /* We assert the formula and call Boolector */ boolector_assert (btor, formula); result = boolector_sat (btor); if (result == BOOLECTOR_SAT) printf ("Instance is satisfiable"); else abort (); /* The formula is not valid, we have found a counter-example. * Now, we are able to obtain assignments to arbitrary expressions */ i = 0; assignments[i++] = boolector_bv_assignment (btor, zero); assignments[i++] = boolector_bv_assignment (btor, v1); assignments[i++] = boolector_bv_assignment (btor, v2); assignments[i++] = boolector_bv_assignment (btor, add); assignments[i++] = boolector_bv_assignment (btor, v1_sgt_zero); assignments[i++] = boolector_bv_assignment (btor, v2_sgt_zero); assignments[i++] = boolector_bv_assignment (btor, vars_sgt_zero); assignments[i++] = boolector_bv_assignment (btor, add_sgt_zero); assignments[i++] = boolector_bv_assignment (btor, impl); assignments[i++] = boolector_bv_assignment (btor, formula); i = 0; printf ("Assignment to 0: %s\n", assignments[i++]); printf ("Assignment to v1: %s\n", assignments[i++]); printf ("Assignment to v2: %s\n", assignments[i++]); printf ("Assignment to v1 + v2: %s\n", assignments[i++]); printf ("Assignment to v1 > 0: %s\n", assignments[i++]); printf ("Assignment to v2 > 0: %s\n", assignments[i++]); printf ("Assignment to v1 > 0 & v2 > 0: %s\n", assignments[i++]); printf ("Assignment to v1 + v2 > 0: %s\n", assignments[i++]); printf ("Assignment to v1 > 0 & v2 > 0 => v1 + v2 > 0: %s\n", assignments[i++]); printf ("Assignment to !(v1 > 0 & v2 > 0 => v1 + v2 > 0): %s\n", assignments[i++]); for (i = 0; i < 10; i++) boolector_free_bv_assignment (btor, assignments[i]); /* cleanup */ boolector_release (btor, zero); boolector_release (btor, v1); boolector_release (btor, v2); boolector_release (btor, add); boolector_release (btor, impl); boolector_release (btor, formula); boolector_release (btor, v1_sgt_zero); boolector_release (btor, v2_sgt_zero); boolector_release (btor, vars_sgt_zero); boolector_release (btor, add_sgt_zero); assert (boolector_get_refs (btor) == 0); boolector_delete (btor); return 0; } boolector-1.5.118-6b56be4-121013/examples/makefile.common0000664000175000017500000000021412033627211021216 0ustar bierebiereCC=gcc CFLAGS=-g -Wall -W -Wextra LIBS=-L../.. -lboolector $(shell sed -e '/^LIBS=/!d' -e 's,^LIBS=,,' -e 's,-L,-L../../,g' ../../makefile) boolector-1.5.118-6b56be4-121013/examples/array/0000775000175000017500000000000012036253574017362 5ustar bierebiereboolector-1.5.118-6b56be4-121013/examples/array/array2.c0000664000175000017500000000575412033627211020727 0ustar bierebiere#include "../../boolector.h" #include #include #include #define ARRAY2_EXAMPLE_VALUE_BW 8 #define ARRAY2_EXAMPLE_INDEX_BW 1 /* We demonstrate Boolector's ability to obtain Array models. * We check the following formula for satisfiability: * write (array1, 0, 3) = write (array2, 1, 5) */ int main (void) { Btor *btor; BtorNode *array1, *array2, *zero, *one, *val1, *val2; BtorNode *write1, *write2, *formula; char **indices, **values; int result, size, i; btor = boolector_new (); boolector_enable_model_gen (btor); zero = boolector_zero (btor, ARRAY2_EXAMPLE_INDEX_BW); one = boolector_one (btor, ARRAY2_EXAMPLE_INDEX_BW); val1 = boolector_int (btor, 3, ARRAY2_EXAMPLE_VALUE_BW); val2 = boolector_int (btor, 5, ARRAY2_EXAMPLE_VALUE_BW); array1 = boolector_array (btor, ARRAY2_EXAMPLE_VALUE_BW, ARRAY2_EXAMPLE_INDEX_BW, NULL); array2 = boolector_array (btor, ARRAY2_EXAMPLE_VALUE_BW, ARRAY2_EXAMPLE_INDEX_BW, NULL); write1 = boolector_write (btor, array1, zero, val1); write2 = boolector_write (btor, array2, one, val2); /* Note: we compare two arrays for equality ---> needs extensional theory */ formula = boolector_eq (btor, write1, write2); boolector_assert (btor, formula); result = boolector_sat (btor); if (result == BOOLECTOR_SAT) printf ("Formula is satisfiable\n"); else abort (); /* Formula is satisfiable, we can obtain array models: */ boolector_array_assignment (btor, array1, &indices, &values, &size); if (size > 0) { printf ("Array1:\n"); for (i = 0; i < size; i++) printf ("Array1[%s] = %s\n", indices[i], values[i]); boolector_free_array_assignment (btor, indices, values, size); } boolector_array_assignment (btor, array2, &indices, &values, &size); if (size > 0) { printf ("\nArray2:\n"); for (i = 0; i < size; i++) printf ("Array2[%s] = %s\n", indices[i], values[i]); boolector_free_array_assignment (btor, indices, values, size); } boolector_array_assignment (btor, write1, &indices, &values, &size); if (size > 0) { printf ("\nWrite1:\n"); for (i = 0; i < size; i++) printf ("Write1[%s] = %s\n", indices[i], values[i]); boolector_free_array_assignment (btor, indices, values, size); } boolector_array_assignment (btor, write2, &indices, &values, &size); if (size > 0) { printf ("\nWrite2:\n"); for (i = 0; i < size; i++) printf ("Write2[%s] = %s\n", indices[i], values[i]); boolector_free_array_assignment (btor, indices, values, size); } /* clean up */ boolector_release (btor, formula); boolector_release (btor, write1); boolector_release (btor, write2); boolector_release (btor, array1); boolector_release (btor, array2); boolector_release (btor, val1); boolector_release (btor, val2); boolector_release (btor, zero); boolector_release (btor, one); assert (boolector_get_refs (btor) == 0); boolector_delete (btor); return 0; } boolector-1.5.118-6b56be4-121013/examples/array/.gitignore0000664000175000017500000000002511760722571021350 0ustar bierebierearray1 array2 array3 boolector-1.5.118-6b56be4-121013/examples/array/makefile0000664000175000017500000000030712033627211021050 0ustar bierebiereinclude ../makefile.common all: $(CC) $(CFLAGS) array1.c -o array1 $(LIBS) $(CC) $(CFLAGS) array2.c -o array2 $(LIBS) $(CC) $(CFLAGS) array3.c -o array3 $(LIBS) clean: rm -f array1 array2 array3 boolector-1.5.118-6b56be4-121013/examples/array/array3.c0000664000175000017500000000307412033627211020721 0ustar bierebiere#include "../../boolector.h" #include #include #define ARRAY3_EXAMPLE_VALUE_BW 8 #define ARRAY3_EXAMPLE_INDEX_BW 1 int main () { int sat_result; BtorNode *array, *index1, *index2, *read1, *read2, *eq, *ne; Btor *btor; btor = boolector_new (); boolector_enable_inc_usage (btor); array = boolector_array (btor, ARRAY3_EXAMPLE_VALUE_BW, ARRAY3_EXAMPLE_INDEX_BW, NULL); index1 = boolector_var (btor, ARRAY3_EXAMPLE_INDEX_BW, NULL); index2 = boolector_var (btor, ARRAY3_EXAMPLE_INDEX_BW, NULL); read1 = boolector_read (btor, array, index1); read2 = boolector_read (btor, array, index2); eq = boolector_eq (btor, index1, index2); ne = boolector_ne (btor, read1, read2); /* we enforce that index1 is equal to index 2 */ boolector_assert (btor, eq); sat_result = boolector_sat (btor); assert (sat_result == BOOLECTOR_SAT); /* now we additionally assume that the read values differ * the instance is now unsatasfiable as read congruence is violated */ boolector_assume (btor, ne); sat_result = boolector_sat (btor); assert (sat_result == BOOLECTOR_UNSAT); /* after the SAT call the assumptions are gone * the instance is now satisfiable again */ sat_result = boolector_sat (btor); assert (sat_result == BOOLECTOR_SAT); boolector_release (btor, array); boolector_release (btor, index1); boolector_release (btor, index2); boolector_release (btor, read1); boolector_release (btor, read2); boolector_release (btor, eq); boolector_release (btor, ne); boolector_delete (btor); return 0; } boolector-1.5.118-6b56be4-121013/examples/array/array1.c0000664000175000017500000000543012033627211020715 0ustar bierebiere#include "../../boolector.h" #include #include #include #define ARRAY1_EXAMPLE_VALUE_BW 8 #define ARRAY1_EXAMPLE_INDEX_BW 3 #define ARRAY1_EXAMPLE_ARRAY_SIZE (1 << ARRAY1_EXAMPLE_INDEX_BW) /* We verify the following linear search algorithm. We iterate over an array * and compute a maximum value as the following pseudo code shows: * * unsigned int array[ARRAY_SIZE]; * unsigned int max; * int i; * ... * max = array[0]; * for (i = 1; i < ARRAY_SIZE; i++) * if (array[i] > max) * max = array[i] * * Finally, we prove that it is not possible to find an array position * such that the value stored at this position is greater than 'max'. * If we can show this, we have proved that this algorithm indeed finds * a maximum value. Note that we prove that the algorithm finds an * arbitrary maximum (multiple maxima are possible), not necessarily * the first maximum. */ int main (void) { Btor *btor; BtorNode *array, *read, *max, *temp, *ugt, *formula, *index; BtorNode *indices[ARRAY1_EXAMPLE_ARRAY_SIZE]; int i, result; btor = boolector_new (); /* We create all possible constants that are used as read indices */ for (i = 0; i < ARRAY1_EXAMPLE_ARRAY_SIZE; i++) indices[i] = boolector_int (btor, i, ARRAY1_EXAMPLE_INDEX_BW); array = boolector_array (btor, ARRAY1_EXAMPLE_VALUE_BW, ARRAY1_EXAMPLE_INDEX_BW, NULL); /* Current maximum is first element of array */ max = boolector_read (btor, array, indices[0]); /* Symbolic loop unrolling */ for (i = 1; i < ARRAY1_EXAMPLE_ARRAY_SIZE; i++) { read = boolector_read (btor, array, indices[i]); ugt = boolector_ugt (btor, read, max); /* found a new maximum? */ temp = boolector_cond (btor, ugt, read, max); boolector_release (btor, max); max = temp; boolector_release (btor, read); boolector_release (btor, ugt); } /* Now we show that 'max' is indeed a maximum */ /* We read at an arbitrary position */ index = boolector_var (btor, ARRAY1_EXAMPLE_INDEX_BW, NULL); read = boolector_read (btor, array, index); /* We assume that it is possible that the read value is greater than 'max' */ formula = boolector_ugt (btor, read, max); /* We assert the formula and call Boolector */ boolector_assert (btor, formula); result = boolector_sat (btor); if (result == BOOLECTOR_UNSAT) printf ("Formula is unsatisfiable\n"); else abort (); /* clean up */ for (i = 0; i < ARRAY1_EXAMPLE_ARRAY_SIZE; i++) boolector_release (btor, indices[i]); boolector_release (btor, formula); boolector_release (btor, read); boolector_release (btor, index); boolector_release (btor, max); boolector_release (btor, array); assert (boolector_get_refs (btor) == 0); boolector_delete (btor); return 0; } boolector-1.5.118-6b56be4-121013/examples/Makefile0000664000175000017500000000025212033627211017671 0ustar bierebiereall: for m in `find * -name makefile`; do d=`dirname $$m`; make -C $$d all; done clean: for m in `find * -name makefile`; do d=`dirname $$m`; make -C $$d clean; done boolector-1.5.118-6b56be4-121013/btormain.c0000664000175000017500000010773112036252347016413 0ustar bierebiere/* Boolector: Satisfiablity Modulo Theories (SMT) solver. * * Copyright (C) 2007 Robert Daniel Brummayer. * Copyright (C) 2007-2012 Armin Biere. * * All rights reserved. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "btormain.h" #include "btormem.h" #include "btorconst.h" #include "btorexit.h" #include "btorutil.h" #include "btorexp.h" #include "btoraigvec.h" #include "btoraig.h" #include "btorsat.h" #include "btorparse.h" #include "btorbtor.h" #include "btorsmt.h" #include "btorsmt2.h" #include "btorstack.h" #include "btorconfig.h" #include "btorhash.h" #include "btorlogic.h" #include #include #include #include #include #include #include #include #include /*------------------------------------------------------------------------*/ enum BtorBasis { BTOR_BINARY_BASIS = 0, BTOR_DECIMAL_BASIS, BTOR_HEXADECIMAL_BASIS }; typedef enum BtorBasis BtorBasis; typedef enum BtorPrintModel BtorPrintModel; struct BtorMainApp { FILE *output_file; int close_output_file; FILE *input_file; char *input_file_name; int close_input_file; int verbosity; int incremental; #ifdef BTOR_USE_LINGELING int nofork; #endif int indepth; int lookahead; int interval; int done; int err; int argpos; int argc; char **argv; BtorBasis basis; int dump_exp; int dump_smt; int rewrite_level; int force_smt_input; int print_model; const char * forced_sat_solver_name; int forced_sat_solvers; #ifdef BTOR_USE_PICOSAT int force_picosat; #endif #ifdef BTOR_USE_LINGELING int force_lingeling; const char * lingeling_options; #endif #ifdef BTOR_USE_MINISAT int force_minisat; #endif }; typedef struct BtorMainApp BtorMainApp; /*------------------------------------------------------------------------*/ static const char *g_usage = "usage: boolector [