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 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_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 void recursively_dump_exp_smt (BtorSMTDumpContext * sdc, BtorNode * exp, int expect_bv, unsigned depth_limit) { assert (sdc); assert (exp); assert (btor_find_in_ptr_hash_table (sdc->dump, BTOR_REAL_ADDR_NODE (exp))); unsigned depth; int pad, i, is_bool, add_space, zero_extend, expect_bool; BtorBitVector *bitsbv; char *bits; const char *op, *fmt; BtorNode *arg, *real_exp; BtorArgsIterator it; BtorNodePtrStack dump, args; BtorIntStack expect_bv_stack, expect_bool_stack, depth_stack; BtorIntStack add_space_stack, zero_extend_stack; BtorPtrHashTable *visited; BtorMemMgr *mm; mm = sdc->btor->mm; visited = btor_new_ptr_hash_table (mm, 0, 0); BTOR_INIT_STACK (args); BTOR_INIT_STACK (dump); BTOR_INIT_STACK (expect_bv_stack); BTOR_INIT_STACK (expect_bool_stack); BTOR_INIT_STACK (add_space_stack); BTOR_INIT_STACK (zero_extend_stack); BTOR_INIT_STACK (depth_stack); PUSH_DUMP_NODE (exp, expect_bv, 0, 0, 0, 0); while (!BTOR_EMPTY_STACK (dump)) { assert (!BTOR_EMPTY_STACK (expect_bv_stack)); assert (!BTOR_EMPTY_STACK (expect_bool_stack)); assert (!BTOR_EMPTY_STACK (add_space_stack)); assert (!BTOR_EMPTY_STACK (zero_extend_stack)); assert (!BTOR_EMPTY_STACK (depth_stack)); depth = BTOR_POP_STACK (depth_stack); exp = BTOR_POP_STACK (dump); expect_bv = BTOR_POP_STACK (expect_bv_stack); expect_bool = BTOR_POP_STACK (expect_bool_stack); add_space = BTOR_POP_STACK (add_space_stack); zero_extend = BTOR_POP_STACK (zero_extend_stack); real_exp = BTOR_REAL_ADDR_NODE (exp); is_bool = is_boolean (sdc, real_exp); assert (!expect_bv || !expect_bool); assert (!expect_bool || !expect_bv); /* open s-expression */ if (!btor_find_in_ptr_hash_table (visited, real_exp)) { if (add_space) fputc (' ', sdc->file); /* wrap node with zero_extend */ if (zero_extend) { fmt = " ((_ zero_extend %d) "; fprintf (sdc->file, fmt, zero_extend); } /* always print constants */ if (BTOR_IS_BV_CONST_NODE (real_exp)) { if (exp == sdc->btor->true_exp && !expect_bv) fputs ("true", sdc->file); else if (exp == BTOR_INVERT_NODE (sdc->btor->true_exp) && !expect_bv) fputs ("false", sdc->file); else if (BTOR_IS_INVERTED_NODE (exp)) { bitsbv = btor_not_bv ( sdc->btor->mm, btor_const_get_bits (real_exp)); bits = btor_bv_to_char_bv (sdc->btor->mm, bitsbv); dump_const_value_aux_smt (sdc, bits); btor_free_bv (sdc->btor->mm, bitsbv); btor_freestr (sdc->btor->mm, bits); } else { bits = btor_bv_to_char_bv ( sdc->btor->mm, btor_const_get_bits (real_exp)); dump_const_value_aux_smt (sdc, bits); btor_freestr (sdc->btor->mm, bits); } /* close zero extend */ if (zero_extend) fputc (')', sdc->file); continue; } /* wrap non-bool node and make it bool */ if (expect_bool && !is_bool) { fputs ("(= ", sdc->file); dump_const_value_aux_smt (sdc, "1"); fputc (' ', sdc->file); } /* wrap node with bvnot/not */ if (BTOR_IS_INVERTED_NODE (exp)) fputs (expect_bv || !is_bool ? "(bvnot " : "(not ", sdc->file); /* wrap bool node and make it a bit vector expression */ if (is_bool && expect_bv) fputs ("(ite ", sdc->file); if (btor_find_in_ptr_hash_table (sdc->dumped, real_exp) || BTOR_IS_LAMBDA_NODE (real_exp) || BTOR_IS_UF_NODE (real_exp)) { #ifndef NDEBUG BtorPtrHashBucket *b; b = btor_find_in_ptr_hash_table (sdc->dump, real_exp); assert (b); /* functions and variables are declared separately */ assert (BTOR_IS_LAMBDA_NODE (real_exp) || BTOR_IS_UF_NODE (real_exp) || BTOR_IS_BV_VAR_NODE (real_exp) || BTOR_IS_PARAM_NODE (real_exp) || b->data.asInt > 1); #endif dump_smt_id (sdc, exp); goto CLOSE_WRAPPER; } if (depth_limit && depth >= depth_limit) { fprintf (sdc->file, "%s_%d", g_kind2smt[real_exp->kind], real_exp->id); goto CLOSE_WRAPPER; } PUSH_DUMP_NODE (exp, expect_bv, expect_bool, 0, zero_extend, depth); btor_insert_in_ptr_hash_table (visited, real_exp); op = ""; switch (real_exp->kind) { case BTOR_SLL_NODE: case BTOR_SRL_NODE: assert (!is_bool); op = real_exp->kind == BTOR_SRL_NODE ? "bvlshr" : "bvshl"; assert (btor_get_exp_width (sdc->btor, real_exp) > 1); pad = btor_get_exp_width (sdc->btor, real_exp) - btor_get_exp_width (sdc->btor, real_exp->e[1]); PUSH_DUMP_NODE (real_exp->e[1], 1, 0, 1, pad, depth + 1); PUSH_DUMP_NODE (real_exp->e[0], 1, 0, 1, 0, depth + 1); break; case BTOR_BCOND_NODE: op = "ite"; PUSH_DUMP_NODE (real_exp->e[2], !is_bool, 0, 1, 0, depth + 1); PUSH_DUMP_NODE (real_exp->e[1], !is_bool, 0, 1, 0, depth + 1); PUSH_DUMP_NODE (real_exp->e[0], 0, 1, 1, 0, depth + 1); break; case BTOR_APPLY_NODE: /* we need the arguments in reversed order */ btor_init_args_iterator (&it, real_exp->e[1]); while (btor_has_next_args_iterator (&it)) { arg = btor_next_args_iterator (&it); BTOR_PUSH_STACK (mm, args, arg); } while (!BTOR_EMPTY_STACK (args)) { arg = BTOR_POP_STACK (args); // TODO (ma): what about bool arguments/indices PUSH_DUMP_NODE (arg, 1, 0, 1, 0, depth + 1); } PUSH_DUMP_NODE (real_exp->e[0], 1, 0, 0, 0, depth + 1); break; #if 0 case BTOR_LAMBDA_NODE: extract_store (sdc, exp, &index, &value, &array); assert (index); assert (value); assert (array); fputs ("(store ", sdc->file); DUMP_EXP_SMT (array); fputc (' ', sdc->file); DUMP_EXP_SMT (index); fputc (' ', sdc->file); DUMP_EXP_SMT (value); fputc (')', sdc->file); break; #endif default: expect_bv = 1; switch (real_exp->kind) { case BTOR_FEQ_NODE: case BTOR_BEQ_NODE: op = "="; expect_bv = 1; break; case BTOR_ULT_NODE: op = "bvult"; expect_bv = 1; break; case BTOR_SLICE_NODE: assert (!is_bool); op = "(_ extract "; break; case BTOR_AND_NODE: op = is_bool ? "and" : "bvand"; expect_bv = !is_bool; break; case BTOR_ADD_NODE: assert (!is_bool); op = "bvadd"; break; case BTOR_MUL_NODE: assert (!is_bool); op = "bvmul"; break; case BTOR_UDIV_NODE: assert (!is_bool); op = "bvudiv"; break; case BTOR_UREM_NODE: assert (!is_bool); op = "bvurem"; break; case BTOR_CONCAT_NODE: assert (!is_bool); op = "concat"; break; default: assert (0); op = "unknown"; } if (BTOR_IS_AND_NODE (real_exp) && is_bool) { assert (BTOR_EMPTY_STACK (args)); get_children (sdc, exp, &args); for (i = 0; i < BTOR_COUNT_STACK (args); i++) { arg = BTOR_PEEK_STACK (args, i); PUSH_DUMP_NODE (arg, expect_bv, 0, 1, 0, depth + 1); } BTOR_RESET_STACK (args); } else for (i = real_exp->arity - 1; i >= 0; i--) PUSH_DUMP_NODE (real_exp->e[i], expect_bv, 0, 1, 0, depth + 1); } /* open s-expression */ assert (op); fprintf (sdc->file, "(%s", op); if (BTOR_IS_SLICE_NODE (real_exp)) { fmt = "%d %d)"; fprintf (sdc->file, fmt, btor_slice_get_upper (real_exp), btor_slice_get_lower (real_exp)); } } /* close s-expression */ else { if (!btor_find_in_ptr_hash_table (sdc->dumped, real_exp)) btor_insert_in_ptr_hash_table (sdc->dumped, real_exp); /* close s-expression */ if (real_exp->arity > 0) fputc (')', sdc->file); CLOSE_WRAPPER: /* close wrappers */ /* wrap boolean expressions in bit vector expression */ if (is_bool && expect_bv && !BTOR_IS_BV_CONST_NODE (real_exp)) { fputc (' ', sdc->file); dump_const_value_aux_smt (sdc, "1"); fputc (' ', sdc->file); dump_const_value_aux_smt (sdc, "0"); fputc (')', sdc->file); } /* close bvnot for non-constants */ if (BTOR_IS_INVERTED_NODE (exp) && !BTOR_IS_BV_CONST_NODE (real_exp)) fputc (')', sdc->file); /* close bool wrapper */ if (expect_bool && !is_boolean (sdc, real_exp)) fputc (')', sdc->file); /* close zero extend wrapper */ if (zero_extend) fputc (')', sdc->file); } } assert (BTOR_EMPTY_STACK (expect_bv_stack)); BTOR_RELEASE_STACK (mm, args); BTOR_RELEASE_STACK (mm, dump); BTOR_RELEASE_STACK (mm, expect_bv_stack); BTOR_RELEASE_STACK (mm, expect_bool_stack); BTOR_RELEASE_STACK (mm, add_space_stack); BTOR_RELEASE_STACK (mm, zero_extend_stack); BTOR_RELEASE_STACK (mm, depth_stack); btor_delete_ptr_hash_table (visited); }
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 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 unsigned extract_lambdas (Btor * btor, BtorPtrHashTable * map_value_index, BtorPtrHashTable * map_lambda_base) { assert (btor); assert (map_value_index); assert (map_lambda_base); bool is_top_eq; BtorBitVector *inc; unsigned i_range, i_index, i_value, i_inc; BtorNode *subst, *base, *tmp, *array, *value, *lower, *upper; BtorNode *src_array, *src_addr, *dst_addr; BtorHashTableIterator it, iit; BtorPtrHashTable *t, *index_value_map; BtorPtrHashBucket *b; BtorNodePtrStack ranges, indices, values, indices_itoi, indices_itoip1; BtorNodePtrStack indices_cpy, indices_rem, *stack; BtorBitVectorPtrStack increments; BtorMemMgr *mm; /* statistics */ unsigned num_total = 0, num_writes = 0; unsigned num_set = 0, num_set_inc = 0, num_set_itoi = 0, num_set_itoip1 = 0; unsigned num_cpy = 0, size_set = 0, size_set_inc = 0, size_set_itoi = 0; unsigned size_set_itoip1 = 0, size_cpy = 0; mm = btor->mm; BTOR_INIT_STACK (ranges); BTOR_INIT_STACK (indices); BTOR_INIT_STACK (increments); BTOR_INIT_STACK (values); BTOR_INIT_STACK (indices_itoi); BTOR_INIT_STACK (indices_itoip1); BTOR_INIT_STACK (indices_cpy); BTOR_INIT_STACK (indices_rem); btor_init_node_hash_table_iterator (&it, map_value_index); while (btor_has_next_node_hash_table_iterator (&it)) { t = it.bucket->data.asPtr; array = btor_next_node_hash_table_iterator (&it); assert (t); /* find memset patterns, the remaining unused indices are pushed onto * stack 'indices' */ btor_init_node_hash_table_iterator (&iit, t); while (btor_has_next_node_hash_table_iterator (&iit)) { stack = iit.bucket->data.asPtr; value = btor_next_node_hash_table_iterator (&iit); assert (stack); find_ranges (btor, stack, &ranges, &increments, &indices, &num_set, &num_set_inc, &size_set, &size_set_inc); BTOR_RELEASE_STACK (mm, *stack); BTOR_DELETE (mm, stack); BTOR_PUSH_STACK (mm, ranges, 0); BTOR_PUSH_STACK (mm, indices, 0); BTOR_PUSH_STACK (mm, values, value); assert (BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values) > 0 || BTOR_COUNT_STACK (indices) - BTOR_COUNT_STACK (values) > 0); assert ((BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values)) % 2 == 0); assert ((BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values)) / 2 == BTOR_COUNT_STACK (increments)); } /* choose base array for patterns/writes: * 1) write chains: base array of the write chains * 2) top eqs: a new UF symbol */ if ((b = btor_find_in_ptr_hash_table (map_lambda_base, array))) { assert (BTOR_IS_LAMBDA_NODE (array)); b = btor_find_in_ptr_hash_table (map_lambda_base, array); assert (b); subst = btor_copy_exp (btor, b->data.asPtr); is_top_eq = false; } else { assert (BTOR_IS_UF_ARRAY_NODE (array)); subst = btor_array_exp (btor, btor_get_fun_exp_width (btor, array), btor_get_index_exp_width (btor, array), 0); is_top_eq = true; } index_value_map = btor_new_ptr_hash_table (mm, 0, 0); base = subst; i_range = i_index = i_inc = 0; for (i_value = 0; i_value < BTOR_COUNT_STACK (values); i_value++) { value = BTOR_PEEK_STACK (values, i_value); /* create memset regions */ for (; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2) { lower = BTOR_PEEK_STACK (ranges, i_range); /* next value */ if (!lower) { i_range++; break; } upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_memset (btor, lower, upper, value, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); i_inc++; } /* find patterns that are dependent on the current index */ for (; i_index < BTOR_COUNT_STACK (indices); i_index++) { lower = BTOR_PEEK_STACK (indices, i_index); /* next value */ if (!lower) { i_index++; break; } assert (!btor_find_in_ptr_hash_table (index_value_map, lower)); /* save index value pairs for later */ btor_insert_in_ptr_hash_table (index_value_map, lower)->data.asPtr = value; /* pattern 1: index -> index */ if (is_itoi_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_itoi, lower); /* pattern 2: index -> index + 1 */ else if (is_itoip1_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_itoip1, lower); /* pattern 3: memcopy pattern */ else if (is_cpy_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_cpy, lower); else /* no pattern found */ BTOR_PUSH_STACK (mm, indices_rem, lower); } } /* pattern: index -> index */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_itoi, &ranges, &increments, &indices_rem, &num_set_itoi, 0, &size_set_itoi, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_itoi (btor, lower, upper, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } /* pattern: index -> index + 1 */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_itoip1, &ranges, &increments, &indices_rem, &num_set_itoip1, 0, &size_set_itoip1, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_itoip1 (btor, lower, upper, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } /* pattern: memcopy */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_cpy, &ranges, &increments, &indices_rem, &num_cpy, 0, &size_cpy, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (base == subst); assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); b = btor_find_in_ptr_hash_table (index_value_map, lower); value = b->data.asPtr; extract_cpy_src_dst_info (lower, value, &src_array, &src_addr, &dst_addr, 0); /* 'subst' == destination array */ tmp = create_pattern_cpy (btor, lower, upper, src_array, subst, src_addr, dst_addr, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } num_total = num_set + num_set_inc + num_set_itoi + num_set_itoip1 + num_cpy; /* we can skip creating writes if we did not find any pattern in a write * chain, and thus can leave the write chain as-is. * for the top equality case we always have to create writes since we * convert top level equalities to writes. */ if (is_top_eq || num_total > 0) { /* no pattern found for indices in 'indices_rem'. create writes */ for (i_index = 0; i_index < BTOR_COUNT_STACK (indices_rem); i_index++) { lower = BTOR_PEEK_STACK (indices_rem, i_index); b = btor_find_in_ptr_hash_table (index_value_map, lower); assert (b); value = b->data.asPtr; tmp = btor_write_exp (btor, subst, lower, value); btor_release_exp (btor, subst); subst = tmp; num_writes++; } } assert ((is_top_eq || num_total > 0) || base == subst); if (base != subst) btor_insert_substitution (btor, array, subst, 0); btor_release_exp (btor, subst); btor_delete_ptr_hash_table (index_value_map); btor_delete_ptr_hash_table (t); BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (indices); BTOR_RESET_STACK (values); BTOR_RESET_STACK (increments); BTOR_RESET_STACK (indices_itoi); BTOR_RESET_STACK (indices_itoip1); BTOR_RESET_STACK (indices_cpy); BTOR_RESET_STACK (indices_rem); } BTOR_RELEASE_STACK (mm, ranges); BTOR_RELEASE_STACK (mm, indices); BTOR_RELEASE_STACK (mm, values); BTOR_RELEASE_STACK (mm, increments); BTOR_RELEASE_STACK (mm, indices_itoi); BTOR_RELEASE_STACK (mm, indices_itoip1); BTOR_RELEASE_STACK (mm, indices_cpy); BTOR_RELEASE_STACK (mm, indices_rem); BTOR_MSG (btor->msg, 1, "set: %u (%u), " "set_inc: %u (%u), " "set_itoi: %u (%u), " "set_itoip1: %u (%u), " "cpy: %u (%u)", num_set, size_set, num_set_inc, size_set_inc, num_set_itoi, size_set_itoi, num_set_itoip1, size_set_itoip1, num_cpy, size_cpy); return num_total; }