Example #1
0
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;
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
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 void
add_to_index_map (Btor * btor,
                  BtorPtrHashTable * map_value_index,
                  BtorNode * lambda,
                  BtorNode * index,
                  BtorNode * value)
{
  BtorMemMgr *mm;
  BtorPtrHashBucket *b;
  BtorPtrHashTable *t;
  BtorNodePtrStack *indices;
  BtorNode *offset;

  mm = btor->mm;

  if (!(b = btor_find_in_ptr_hash_table (map_value_index, lambda)))
    {
      b = btor_insert_in_ptr_hash_table (map_value_index, lambda);
      t = btor_new_ptr_hash_table (mm, 0, 0);
      b->data.asPtr = t;
    }
  else
    t = b->data.asPtr;
  assert (t);

  if (!(b = btor_find_in_ptr_hash_table (t, value)))
    {
      b = btor_insert_in_ptr_hash_table (t, value);
      BTOR_NEW (mm, indices);
      BTOR_INIT_STACK (*indices);
      b->data.asPtr = indices;
    }
  else
    indices = (BtorNodePtrStack *) b->data.asPtr;
  assert (indices);
  if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (index)))
    offset = index;
  else
    {
      assert (BTOR_IS_REGULAR_NODE (index));
      assert (BTOR_IS_ADD_NODE (index));
      extract_base_addr_offset (index, 0, &offset);
      assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (offset)));
    }

  /* generate inverted bit string for constants if required */
  if (BTOR_IS_INVERTED_NODE (offset) && !btor_const_get_invbits (offset))
    btor_const_set_invbits (
        offset, btor_not_bv (mm, btor_const_get_bits (offset)));

  BTOR_PUSH_STACK (mm, *indices, index);
}
Example #6
0
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;
}
Example #7
0
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 void
get_children (BtorSMTDumpContext * sdc, BtorNode * exp,
              BtorNodePtrStack * children)
{
  assert (children);
  assert (BTOR_EMPTY_STACK (*children));

  int i, is_and = 0;
  BtorNode *cur, *real_cur;
  BtorPtrHashTable *mark;
  BtorNodePtrQueue visit;
  BtorPtrHashBucket *b;

  mark = btor_new_ptr_hash_table (sdc->btor->mm, 0, 0);

  if (BTOR_IS_AND_NODE (BTOR_REAL_ADDR_NODE (exp)))
    is_and = 1;

  BTOR_INIT_QUEUE (visit);
  for (i = 0; i < BTOR_REAL_ADDR_NODE (exp)->arity; i++)
    BTOR_ENQUEUE (sdc->btor->mm, visit, BTOR_REAL_ADDR_NODE (exp)->e[i]);

  /* get children of multi-input and/or */
  while (!BTOR_EMPTY_QUEUE (visit))
    {
      cur = BTOR_DEQUEUE (visit);
      real_cur = BTOR_REAL_ADDR_NODE (cur);

      if (btor_find_in_ptr_hash_table (mark, real_cur))
        continue;

      b = btor_find_in_ptr_hash_table (sdc->dump, real_cur);
      btor_insert_in_ptr_hash_table (mark, real_cur);
      if (!BTOR_IS_AND_NODE (real_cur)
          || (b && b->data.asInt > 1)
          || (is_and && BTOR_IS_INVERTED_NODE (cur)))
        {
          BTOR_PUSH_STACK (sdc->btor->mm, *children, cur);
          continue;
        }

      assert (!btor_find_in_ptr_hash_table (sdc->dumped, real_cur));
      btor_insert_in_ptr_hash_table (sdc->dumped, real_cur);
      for (i = 0; i < real_cur->arity; i++)
        BTOR_ENQUEUE (sdc->btor->mm, visit, real_cur->e[i]);
    }
  BTOR_RELEASE_QUEUE (sdc->btor->mm, visit);
  btor_delete_ptr_hash_table (mark);
}
Example #9
0
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;
}
Example #10
0
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;
}
void
btor_dump_smt2_node (Btor * btor, FILE * file, BtorNode * exp, unsigned depth)
{
  assert (btor);
  assert (depth);

  int i;
  BtorNode *cur, *real_exp;
  BtorSMTDumpContext *sdc;
  BtorNodePtrStack visit, all;
  BtorArgsIterator ait;
  BtorPtrHashBucket *b;

  real_exp = BTOR_REAL_ADDR_NODE (exp);

  BTOR_INIT_STACK (all);
  BTOR_INIT_STACK (visit);
  sdc = new_smt_dump_context (btor, file);

  if (!exp)
    {
      fprintf (file, "null\n");
      goto CLEANUP;
    }
  else if (BTOR_IS_ARGS_NODE (real_exp) || BTOR_IS_PARAM_NODE (real_exp))
    {
      fprintf (file, "%s_%d\n", g_kind2smt[real_exp->kind], real_exp->id);
      goto CLEANUP;
    }
  else if (BTOR_IS_BV_VAR_NODE (exp) || BTOR_IS_UF_NODE (exp))
    {
      dump_declare_fun_smt (sdc, exp);
      goto CLEANUP;
    }

  BTOR_PUSH_STACK (btor->mm, visit, exp);
  while (!BTOR_EMPTY_STACK (visit))
    {
      cur = BTOR_REAL_ADDR_NODE (BTOR_POP_STACK (visit));

      if (btor_find_in_ptr_hash_table (sdc->dump, cur))
        continue;

      if (BTOR_IS_BV_VAR_NODE (cur)
          || BTOR_IS_UF_NODE (cur)
          || (!BTOR_IS_LAMBDA_NODE (real_exp) && BTOR_IS_PARAM_NODE (cur)))
        btor_insert_in_ptr_hash_table (sdc->dumped, cur);

      btor_insert_in_ptr_hash_table (sdc->dump, cur);
      BTOR_PUSH_STACK (btor->mm, all, cur);

      for (i = 0; i < cur->arity; i++)
        BTOR_PUSH_STACK (btor->mm, visit, cur->e[i]);
    }


  /* compute reference counts of expressions (required for determining shared
   * expressions)*/
  if (all.start)
    qsort (all.start, BTOR_COUNT_STACK (all), sizeof (BtorNode *), cmp_node_id);

  for (i = 0; i < BTOR_COUNT_STACK (all); i++)
    {
      cur = BTOR_PEEK_STACK (all, i);
      b = btor_find_in_ptr_hash_table (sdc->dump, cur);
      assert (b);
      assert (b->data.asInt == 0);
      /* cache result for later reuse */
      b->data.asInt = get_references (sdc, cur);

      /* update references for expressions under argument nodes */
      if (BTOR_IS_ARGS_NODE (cur) && b->data.asInt > 0)
        {
          btor_init_args_iterator (&ait, cur);
          while (btor_has_next_args_iterator (&ait))
            {
              cur = BTOR_REAL_ADDR_NODE (btor_next_args_iterator (&ait));
              assert (btor_find_in_ptr_hash_table (sdc->dump, cur));
              btor_find_in_ptr_hash_table (sdc->dump, cur)->data.asInt +=
                  b->data.asInt;
            }
        }
    }

  mark_boolean (sdc, &all);
  if (BTOR_IS_LAMBDA_NODE (BTOR_REAL_ADDR_NODE (exp)))
    dump_fun_smt2 (sdc, exp);
  else
    {
      recursively_dump_exp_smt (sdc, exp, 0, depth);
      fprintf (file, "\n");
    }
CLEANUP:
  delete_smt_dump_context (sdc);
  BTOR_RELEASE_STACK (btor->mm, all);
  BTOR_RELEASE_STACK (btor->mm, visit);
}
static void
dump_smt (BtorSMTDumpContext * sdc)
{
  assert (sdc);

  int i, j;
  BtorNode *e, *cur;
  BtorMemMgr *mm;
  BtorNodePtrStack visit, all, vars, shared, ufs;
  BtorPtrHashBucket *b;
  BtorHashTableIterator it;
  BtorArgsIterator ait;

  mm = sdc->btor->mm;
  BTOR_INIT_STACK (visit);
  BTOR_INIT_STACK (shared);
  BTOR_INIT_STACK (all);
  BTOR_INIT_STACK (vars);
  BTOR_INIT_STACK (ufs);

  btor_init_node_hash_table_iterator (&it, sdc->roots);
  while (btor_has_next_node_hash_table_iterator (&it))
    {
      cur = btor_next_node_hash_table_iterator (&it);
      BTOR_PUSH_STACK (mm, visit, BTOR_REAL_ADDR_NODE (cur));
    }

  /* collect constants, variables, array variables and functions */
  while (!BTOR_EMPTY_STACK (visit))
    {
      cur = BTOR_POP_STACK (visit);
      assert (BTOR_IS_REGULAR_NODE (cur));
      assert (!btor_find_in_ptr_hash_table (sdc->dumped, cur));

      if (btor_find_in_ptr_hash_table (sdc->dump, cur))
        continue;

      btor_insert_in_ptr_hash_table (sdc->dump, cur)->data.asInt = 0;
      BTOR_PUSH_STACK (mm, all, cur);

      if (BTOR_IS_BV_VAR_NODE (cur))
        BTOR_PUSH_STACK (mm, vars, cur);
      else if (BTOR_IS_UF_NODE (cur))
        BTOR_PUSH_STACK (mm, ufs, cur);
      else if (BTOR_IS_LAMBDA_NODE (cur)
               && !cur->parameterized
               && !has_lambda_parents_only (cur))
        BTOR_PUSH_STACK (mm, shared, cur);

      for (j = 0; j < cur->arity; j++)
        BTOR_PUSH_STACK (mm, visit, BTOR_REAL_ADDR_NODE (cur->e[j]));
    }

  /* compute reference counts of expressions (required for determining shared
   * expressions)*/
  if (all.start)
    qsort (all.start, BTOR_COUNT_STACK (all), sizeof e, cmp_node_id);

  for (i = 0; i < BTOR_COUNT_STACK (all); i++)
    {
      cur = BTOR_PEEK_STACK (all, i);
      b = btor_find_in_ptr_hash_table (sdc->dump, cur);
      assert (b);
      assert (b->data.asInt == 0);
      /* cache result for later reuse */
      b->data.asInt = get_references (sdc, cur);

      /* update references for expressions under argument nodes */
      if (BTOR_IS_ARGS_NODE (cur) && b->data.asInt > 0)
        {
          btor_init_args_iterator (&ait, cur);
          while (btor_has_next_args_iterator (&ait))
            {
              e = BTOR_REAL_ADDR_NODE (btor_next_args_iterator (&ait));
              assert (btor_find_in_ptr_hash_table (sdc->dump, e));
              btor_find_in_ptr_hash_table (sdc->dump, e)->data.asInt +=
                  b->data.asInt;
            }
        }
    }

  /* collect globally shared expressions */
  for (i = 0; i < BTOR_COUNT_STACK (all); i++)
    {
      cur = BTOR_PEEK_STACK (all, i);
      b = btor_find_in_ptr_hash_table (sdc->dump, cur);
      assert (b);

      if (b->data.asInt <= 1
          /* parameterized expressions are only shared within a function */
          || cur->parameterized
          || BTOR_IS_PARAM_NODE (cur)
          /* constants are always printed */
          || BTOR_IS_BV_CONST_NODE (cur)
          /* for variables and functions the resp. symbols are always printed */
          || BTOR_IS_BV_VAR_NODE (cur)
          || BTOR_IS_LAMBDA_NODE (cur)
          || BTOR_IS_UF_NODE (cur)
          /* argument nodes are never printed */
          || BTOR_IS_ARGS_NODE (cur))
        continue;

      BTOR_PUSH_STACK (mm, shared, cur);
    }

  /* collect boolean terms */
  mark_boolean (sdc, &all);

  /* begin dump */
  if (BTOR_EMPTY_STACK (ufs))
    set_logic_smt (sdc, "QF_BV");
  else
    set_logic_smt (sdc, "QF_UFBV");

  /* dump inputs */
  if (vars.start)
    qsort (vars.start, BTOR_COUNT_STACK (vars), sizeof e, cmp_node_id);

  for (i = 0; i < BTOR_COUNT_STACK (vars); i++)
    {
      cur = BTOR_PEEK_STACK (vars, i);
      dump_declare_fun_smt (sdc, cur);
    }

  if (ufs.start)
    qsort (ufs.start, BTOR_COUNT_STACK (ufs), sizeof e, cmp_node_id);

  for (i = 0; i < BTOR_COUNT_STACK (ufs); i++)
    {
      cur = BTOR_PEEK_STACK (ufs, i);
      dump_declare_fun_smt (sdc, cur);
    }

  /* dump shared expressions and functions */
  if (shared.start)
    qsort (shared.start, BTOR_COUNT_STACK (shared), sizeof e, cmp_node_id);

  for (i = 0; i < BTOR_COUNT_STACK (shared); i++)
    {
      cur = BTOR_PEEK_STACK (shared, i);
      assert (BTOR_IS_REGULAR_NODE (cur));

      if (btor_find_in_ptr_hash_table (sdc->dumped, cur))
        continue;

      assert (!cur->parameterized);

      if (BTOR_IS_LAMBDA_NODE (cur))
        dump_fun_smt2 (sdc, cur);
      else
        dump_fun_let_smt2 (sdc, cur);
    }

  /* dump assertions/build root */
    btor_init_node_hash_table_iterator (&it, sdc->roots);
    while (btor_has_next_node_hash_table_iterator (&it))
      {
        cur = btor_next_node_hash_table_iterator (&it);
        dump_assert_smt2 (sdc, cur);
      }
  assert (sdc->open_lets == 0);

#ifndef NDEBUG
  btor_init_node_hash_table_iterator (&it, sdc->dump);
  while (btor_has_next_node_hash_table_iterator (&it))
    {
      cur = btor_next_node_hash_table_iterator (&it);
      /* constants and function applications are always dumped (hence, not in
       * mark) */
      if (BTOR_IS_BV_CONST_NODE (cur)
          || BTOR_IS_APPLY_NODE (cur)
          /* argument nodes are never dumped and not in mark */
          || BTOR_IS_ARGS_NODE (cur))
        continue;
      assert (btor_find_in_ptr_hash_table (sdc->dumped, cur));
    }
#endif

  BTOR_RELEASE_STACK (mm, shared);
  BTOR_RELEASE_STACK (mm, visit);
  BTOR_RELEASE_STACK (mm, all);
  BTOR_RELEASE_STACK (mm, vars);
  BTOR_RELEASE_STACK (mm, ufs);

  fputs ("(check-sat)\n", sdc->file);
  fputs ("(exit)\n", sdc->file);
  fflush (sdc->file);
}
Example #13
0
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;
}
Example #14
0
int
main (int argc, char ** argv)
{
  int i, j, verbosity, close_input, close_output, binary, merge;
  const char * input_name, * output_name;
  FILE * input_file, * output_file, * file;
  BtorAIG * aig, * tmp, * merged, ** p;
  BtorPtrHashTable * back_annotation;
  const char * parse_error;
  BtorPtrHashBucket *b;
  BtorParseResult model;
  BtorAIGVecMgr * avmgr;
  BtorAIGPtrStack regs;
  BtorAIGPtrStack nexts;
  BtorAIGPtrStack aigs;
  BtorParser * parser;
  BtorAIGMgr * amgr;
  BtorMemMgr * mem;
  BtorAIGVec * av;
  Btor * btor;

  verbosity = 0;
  close_input = 0;
  close_output = 0;
  binary = 0;
  merge = 0;
  input_name = "<stdin>";
  output_name = "<stdout>";
  input_file = stdin;
  output_file = stdout;

  for (i = 1; i < argc; i++)
    {
      if (!strcmp (argv[i], "-h"))
	{
	  printf ("usage: synthebor [-h][-v][-m][<input>[<output>]]\n");
	  exit (0);
	}
      else if (!strcmp (argv[i], "-v"))
	verbosity++;
      else if (!strcmp (argv[i], "-m"))
	merge = 1;
      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;
	  output_name = argv[i];
	  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, 1);
  parser = btor_btor_parser_api ()->init (btor, verbosity);

  parse_error = btor_btor_parser_api()->parse (parser,
                                             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;
}
static void
dump_fun_smt2 (BtorSMTDumpContext * sdc, BtorNode * fun)
{
  assert (fun);
  assert (sdc);
  assert (BTOR_IS_REGULAR_NODE (fun));
  assert (BTOR_IS_LAMBDA_NODE (fun));
  assert (!fun->parameterized);
  assert (!btor_find_in_ptr_hash_table (sdc->dumped, fun)); 

  int i, refs;
  BtorNode *cur, *param, *fun_body, *p;
  BtorMemMgr *mm = sdc->btor->mm;
  BtorNodePtrStack visit, shared;
  BtorNodeIterator it, iit;
  BtorPtrHashTable *mark;
  BtorPtrHashBucket *b;

  mark = btor_new_ptr_hash_table (mm,
                                  (BtorHashPtr) btor_hash_exp_by_id,
                                  (BtorCmpPtr) btor_compare_exp_by_id);
  BTOR_INIT_STACK (visit);
  BTOR_INIT_STACK (shared);

#if 0
  extract_store (sdc, fun, &index, &value, &array);

  if (index)
    {
      assert (value);
      assert (array);
      btor_insert_in_ptr_hash_table (sdc->stores, fun);
      return;
    }
#endif

  /* collect shared parameterized expressions in function body */
  fun_body = btor_lambda_get_body (fun);
  BTOR_PUSH_STACK (mm, visit, fun_body);
  while (!BTOR_EMPTY_STACK (visit))
    {
      cur = BTOR_REAL_ADDR_NODE (BTOR_POP_STACK (visit));

      if (btor_find_in_ptr_hash_table (mark, cur)
          || btor_find_in_ptr_hash_table (sdc->dumped, cur)
          || BTOR_IS_LAMBDA_NODE (cur))
        continue;

      b = btor_find_in_ptr_hash_table (sdc->dump, cur);
      assert (b);
      refs = b->data.asInt; 

      /* args and params are handled differently */
      /* collect shared parameterized expressions in function body.
       * arguments, parameters, and constants are excluded. */
      if (!BTOR_IS_ARGS_NODE (cur)
          && !BTOR_IS_PARAM_NODE (cur)
          /* constants are always printed */
          && !BTOR_IS_BV_CONST_NODE (cur)
          && cur->parameterized
          && refs > 1)
        BTOR_PUSH_STACK (mm, shared, cur);

      btor_insert_in_ptr_hash_table (mark, cur);
      for (i = 0; i < cur->arity; i++)
        BTOR_PUSH_STACK (mm, visit, cur->e[i]);
    }

  /* dump function signature */
  fputs ("(define-fun ", sdc->file);
  dump_smt_id (sdc, fun);
  fputs (" (", sdc->file);

  btor_init_lambda_iterator (&it, fun);
  while (btor_has_next_lambda_iterator (&it))
    {
      cur = btor_next_lambda_iterator (&it);
      param = cur->e[0];
      if (!btor_find_in_ptr_hash_table (mark, cur))
        btor_insert_in_ptr_hash_table (mark, cur);
      if (!btor_find_in_ptr_hash_table (mark, param))
        btor_insert_in_ptr_hash_table (mark, param);
      btor_insert_in_ptr_hash_table (sdc->dumped, cur);
      btor_insert_in_ptr_hash_table (sdc->dumped, param);
      if (fun != cur)
        fputc (' ', sdc->file);
      fputc ('(', sdc->file);
      dump_smt_id (sdc, param);
      fputc (' ', sdc->file);
      btor_dump_sort_smt_node (param, sdc->file);
      fputc (')', sdc->file);
    }
  fputs (") ", sdc->file);

  // TODO (ma): again wait for aina merge for dump_sort_smt
  if (is_boolean (sdc, fun_body))
    fputs ("Bool", sdc->file);
  else
    btor_dump_sort_smt_node (fun_body, sdc->file);
  fputc (' ', sdc->file);

  assert (sdc->open_lets == 0);

  /* dump expressions that are shared in 'fun' */
  if (shared.start)
    qsort (shared.start, BTOR_COUNT_STACK (shared), sizeof (BtorNode *),
           cmp_node_id);

  for (i = 0; i < BTOR_COUNT_STACK (shared); i++)
    {
      cur = BTOR_PEEK_STACK (shared, i);
      assert (BTOR_IS_REGULAR_NODE (cur));
      assert (cur->parameterized);
      dump_let_smt (sdc, cur);
      fputc (' ', sdc->file);
    }
  recursively_dump_exp_smt (sdc, fun_body, !is_boolean (sdc, fun_body), 0);

  /* close lets */
  for (i = 0; i < sdc->open_lets; i++)
    fputc (')', sdc->file);
  sdc->open_lets = 0;

  /* close define-fun */
  fputs (")\n", sdc->file);

  /* due to lambda hashing it is possible that a lambda in 'fun' is shared in
   * different functions. hence, we have to check if all lambda parents of
   * the resp. lambda have already been dumped as otherwise all expressions
   * below have to be removed from 'sdc->dumped' as they will be dumped
   * again in a different function definition. */
  btor_init_lambda_iterator (&it, fun);
  while (btor_has_next_lambda_iterator (&it))
    {
      cur = btor_next_lambda_iterator (&it);
      btor_init_parent_iterator (&iit, cur);
      while (btor_has_next_parent_iterator (&iit))
        {
          p = btor_next_parent_iterator (&iit);
          /* find lambda parent that needs to be dumped but has not yet been
           * dumped */
          if (btor_find_in_ptr_hash_table (sdc->dump, p)
              && !btor_find_in_ptr_hash_table (sdc->dumped, p)
              && BTOR_IS_LAMBDA_NODE (p))
            {
              BTOR_PUSH_STACK (mm, visit, cur);
              while (!BTOR_EMPTY_STACK (visit))
                {
                  cur = BTOR_REAL_ADDR_NODE (BTOR_POP_STACK (visit));
                  assert (BTOR_IS_REGULAR_NODE (cur));

                  if (!cur->parameterized
                      && (!btor_find_in_ptr_hash_table (mark, cur)
                          || !btor_find_in_ptr_hash_table (sdc->dumped, cur)))
                    continue;

                  if (btor_find_in_ptr_hash_table (sdc->dumped, cur))
                    btor_remove_from_ptr_hash_table (sdc->dumped, cur, 0, 0);

                  for (i = 0; i < cur->arity; i++)
                    BTOR_PUSH_STACK (mm, visit, cur->e[i]);
                }
              break;
            }
        }
    }

  BTOR_RELEASE_STACK (mm, shared);
  BTOR_RELEASE_STACK (mm, visit);
  btor_delete_ptr_hash_table (mark);
}
Example #16
0
static void
process_skeleton_tseitin (Btor * btor, LGL * lgl,
                          BtorNodePtrStack * work_stack,
                          BtorNodePtrStack * unmark_stack,
                          BtorPtrHashTable * ids,
                          BtorNode * root)
{
  assert (btor);

  int i, lhs, rhs[3], fixed;
  BtorNode * exp;

  BTOR_PUSH_STACK (btor->mm, *work_stack, root);

  do {
    exp = BTOR_POP_STACK (*work_stack);
    assert (exp);
    exp = BTOR_REAL_ADDR_NODE (exp);
    if (!exp->mark)
      {
        exp->mark = 1;
        BTOR_PUSH_STACK (btor->mm, *unmark_stack, exp);

        BTOR_PUSH_STACK (btor->mm, *work_stack, exp);
        for (i = exp->arity-1; i >= 0; i--)
          BTOR_PUSH_STACK (btor->mm, *work_stack, exp->e[i]);
      }
    else if (exp->mark == 1)
      {
        exp->mark = 2;
        if (BTOR_IS_FUN_NODE (exp)
            || BTOR_IS_ARGS_NODE (exp)
            || exp->parameterized
            || btor_get_exp_width (btor, exp) != 1)
          continue;

#ifndef NDEBUG
        for (i = 0; i < exp->arity; i++)
          {
            BtorNode * child = exp->e[i];
            child = BTOR_REAL_ADDR_NODE (child);
            assert (child->mark == 2);
            if (!BTOR_IS_FUN_NODE (child)
                && !BTOR_IS_ARGS_NODE (child)
                && !child->parameterized
                && btor_get_exp_width (btor, child) == 1)
              assert (btor_find_in_ptr_hash_table (ids, child));
          }
#endif
        lhs = process_skeleton_tseitin_lit (ids, exp);
        fixed = fixed_exp (btor, exp);
        if (fixed)
          {
            lgladd (lgl, (fixed > 0) ? lhs : -lhs);
            lgladd (lgl, 0);
          }

        switch (exp->kind)
          {
            case BTOR_AND_NODE:
              rhs[0] = process_skeleton_tseitin_lit (ids, exp->e[0]);
              rhs[1] = process_skeleton_tseitin_lit (ids, exp->e[1]);

              lgladd (lgl, -lhs);
              lgladd (lgl, rhs[0]);
              lgladd (lgl, 0);

              lgladd (lgl, -lhs);
              lgladd (lgl, rhs[1]);
              lgladd (lgl, 0);

              lgladd (lgl, lhs);
              lgladd (lgl, -rhs[0]);
              lgladd (lgl, -rhs[1]);
              lgladd (lgl, 0);
              break;

            case BTOR_BEQ_NODE:
              if (btor_get_exp_width (btor, exp->e[0]) != 1)
                break;
              assert (btor_get_exp_width (btor, exp->e[1]) == 1);
              rhs[0] = process_skeleton_tseitin_lit (ids, exp->e[0]);
              rhs[1] = process_skeleton_tseitin_lit (ids, exp->e[1]);

              lgladd (lgl, -lhs);
              lgladd (lgl, -rhs[0]);
              lgladd (lgl, rhs[1]);
              lgladd (lgl, 0);

              lgladd (lgl, -lhs);
              lgladd (lgl, rhs[0]);
              lgladd (lgl, -rhs[1]);
              lgladd (lgl, 0);

              lgladd (lgl, lhs);
              lgladd (lgl, rhs[0]);
              lgladd (lgl, rhs[1]);
              lgladd (lgl, 0);

              lgladd (lgl, lhs);
              lgladd (lgl, -rhs[0]);
              lgladd (lgl, -rhs[1]);
              lgladd (lgl, 0);

              break;

            case BTOR_BCOND_NODE:
              assert (btor_get_exp_width (btor, exp->e[0]) == 1);
              if (btor_get_exp_width (btor, exp->e[1]) != 1)
                break;
              assert (btor_get_exp_width (btor, exp->e[2]) == 1);
              rhs[0] = process_skeleton_tseitin_lit (ids, exp->e[0]);
              rhs[1] = process_skeleton_tseitin_lit (ids, exp->e[1]);
              rhs[2] = process_skeleton_tseitin_lit (ids, exp->e[2]);

              lgladd (lgl, -lhs);
              lgladd (lgl, -rhs[0]);
              lgladd (lgl, rhs[1]);
              lgladd (lgl, 0);

              lgladd (lgl, -lhs);
              lgladd (lgl, rhs[0]);
              lgladd (lgl, rhs[2]);
              lgladd (lgl, 0);

              lgladd (lgl, lhs);
              lgladd (lgl, -rhs[0]);
              lgladd (lgl, -rhs[1]);
              lgladd (lgl, 0);

              lgladd (lgl, lhs);
              lgladd (lgl, rhs[0]);
              lgladd (lgl, -rhs[2]);
              lgladd (lgl, 0);
              break;

            default:
              assert (exp->kind != BTOR_PROXY_NODE);
              break;
          }
      }
  } while (!BTOR_EMPTY_STACK (*work_stack));
}
Example #17
0
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;
}
void
find_ranges (Btor * btor,
             BtorNodePtrStack * stack,
             BtorNodePtrStack * ranges,
             BtorBitVectorPtrStack * increments,
             BtorNodePtrStack * indices,
             unsigned * num_pat,
             unsigned * num_pat_inc,
             unsigned * size_pat,
             unsigned * size_pat_inc)
{
  assert (stack);
  assert (ranges);
  assert (increments);
  assert (indices);
  assert (num_pat);
  assert (size_pat);

#ifndef NDEBUG
  unsigned num_indices = 0;
  int i;
#endif
  bool in_range;
  BtorBitVector *b0, *b1, *inc, *prev_inc;
  unsigned cnt, lower, upper;
  unsigned num_pattern = 0, num_pattern_inc = 0, size_pattern = 0;
  unsigned size_pattern_inc = 0;
  BtorNode *n0, *n1, *n0_base_addr, *n1_base_addr, *n0_offset, *n1_offset;
  BtorMemMgr *mm;
  BtorNodePtrStack index_stack;

  mm = btor->mm;
  index_stack = *stack;
  cnt = BTOR_COUNT_STACK (index_stack);
  if (cnt == 0)
    return;

  if (cnt == 1)
    BTOR_PUSH_STACK (mm, *indices, BTOR_PEEK_STACK (index_stack, 0));
  else
    {
      assert (cnt > 1);
#ifndef NDEBUG
      /* sanity check: 'index_stack' contains either absolute or relative
       * addresses */
      for (i = 1; i < BTOR_COUNT_STACK (index_stack); i++)
        {
          n0 = BTOR_REAL_ADDR_NODE (BTOR_PEEK_STACK (index_stack, i - 1));
          n1 = BTOR_REAL_ADDR_NODE (BTOR_PEEK_STACK (index_stack, i));
          assert (n0->kind == n1->kind);
          assert (BTOR_IS_ADD_NODE (n0) || BTOR_IS_BV_CONST_NODE (n0));
          if (BTOR_IS_ADD_NODE (n0))
            {
              extract_base_addr_offset (n0, &n0_base_addr, &n0_offset);
              extract_base_addr_offset (n1, &n1_base_addr, &n1_offset);
              assert (n0_base_addr == n1_base_addr);
              assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n0_offset)));
              assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n1_offset)));
            }
        }
#endif
      qsort (index_stack.start, cnt, sizeof (BtorNode *), cmp_abs_rel_indices);
      inc = prev_inc = 0;
      lower = upper = 0;
      while (upper < cnt)
        {
          in_range = false;
          inc = 0;
          if (upper + 1 < cnt)
            {
              n0 = BTOR_PEEK_STACK (index_stack, upper);
              n1 = BTOR_PEEK_STACK (index_stack, upper + 1);
      
              if (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n0)))
                {
                  assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (n1)));
                  b0 = BTOR_CONST_GET_BITS (n0);
                  b1 = BTOR_CONST_GET_BITS (n1);
                }
              else
                {
                  assert (!BTOR_IS_INVERTED_NODE (n0));
                  assert (!BTOR_IS_INVERTED_NODE (n1));
                  assert (BTOR_IS_ADD_NODE (n0));
                  assert (BTOR_IS_ADD_NODE (n1));
                  extract_base_addr_offset (n0, &n0_base_addr, &n0_offset);
                  extract_base_addr_offset (n1, &n1_base_addr, &n1_offset);
                  assert (n0_base_addr == n1_base_addr);
                  b0 = BTOR_CONST_GET_BITS (n0_offset);
                  b1 = BTOR_CONST_GET_BITS (n1_offset);
                }
              assert (b0);
              assert (b1);
              inc = btor_sub_bv (mm, b1, b0);

              if (!prev_inc)
                prev_inc = btor_copy_bv (mm, inc);

              /* increment upper bound of range */
              in_range = btor_compare_bv (inc, prev_inc) == 0;
              if (in_range) upper += 1;
            }

          if (!in_range)
            {
              /* push index */
              if (upper == lower)
                {
                  BTOR_PUSH_STACK (mm, *indices,
                                   BTOR_PEEK_STACK (index_stack, lower));
#ifndef NDEBUG
                  num_indices++;
#endif
                  goto NEW_RANGE;
                }
              /* range is too small, push separate indices */
              else if (upper - lower <= 1
                       /* range with an offset greater than 1 */
                       && btor_is_power_of_two_bv (prev_inc) != 0)
                {
                  /* last iteration step: if range contains all indices
                   * up to the last one, we can push all indices */
                  if (upper == cnt - 1)
                    upper += 1;

                  /* push all indices from lower until upper - 1 */
                  for (; lower < upper; lower++)
                    {
                      BTOR_PUSH_STACK (mm, *indices,
                                       BTOR_PEEK_STACK (index_stack, lower));
#ifndef NDEBUG
                      num_indices++;
#endif
                    }
                  /* lower is now that last index in the range, from
                   * which we try to find a new range */
                  upper += 1;
                }
              /* found range */
              else
                {
                  assert (upper - lower > 0);
                  BTOR_PUSH_STACK (mm, *increments, prev_inc);
                  BTOR_PUSH_STACK (mm, *ranges,
                                   BTOR_PEEK_STACK (index_stack, lower));
                  BTOR_PUSH_STACK (mm, *ranges,
                                   BTOR_PEEK_STACK (index_stack, upper));
#ifndef NDEBUG
                  num_indices += upper - lower + 1;
#endif
                  if (btor_is_one_bv (prev_inc))
                    {
                      size_pattern += upper - lower + 1;
                      num_pattern++;
                    }
                  else
                    {
                      size_pattern_inc += upper - lower + 1;
                      num_pattern_inc++;
                    }
                  /* 'prev_inc' will be released later */
                  prev_inc = 0;
NEW_RANGE:
                  /* reset range */
                  upper += 1;
                  lower = upper;
                  if (inc) btor_free_bv (mm, inc);
                  inc = 0;
                }
            }
          if (prev_inc) btor_free_bv (mm, prev_inc);
          prev_inc = inc;
        }
      if (inc) btor_free_bv (mm, inc);
      assert (num_indices == cnt);
    }

  /* return statistics */
  if (num_pat) 
    {
      *num_pat += num_pattern;
      /* if no separate statistic variable is given for the 'inc' pattern,
       * we just add the number to the normal one */
      if (!num_pat_inc) *num_pat += num_pattern_inc;
    }
  if (num_pat_inc) *num_pat_inc += num_pattern_inc;
  if (size_pat)
    {
      *size_pat += size_pattern;
      /* if no separate statistic variable is given for the 'inc' pattern,
       * we just add the size to the normal one */
      if (!size_pat_inc) *size_pat += size_pattern_inc;
    }
  if (size_pat_inc) *size_pat_inc += size_pattern_inc;
}
static void
collect_indices_writes (Btor * btor,
                        BtorPtrHashTable * map_value_index, 
                        BtorPtrHashTable * map_lambda_base)
{
  int is_top;
  BtorNode *lambda, *cur, *array, *index, *value, *tmp, *array_if, *array_else;
  BtorNode *prev_index, *prev_value;
  BtorHashTableIterator it;
  BtorNodeIterator pit;
  BtorNodePtrStack lambdas;
  BtorPtrHashTable *index_cache, *visit_cache;
  BtorMemMgr *mm;

  mm = btor->mm;
  BTOR_INIT_STACK (lambdas);
  visit_cache = btor_new_ptr_hash_table (mm, 0, 0);

  /* collect lambdas that are at the top of lambda chains */
  btor_init_reversed_hash_table_iterator (&it, btor->lambdas);
  while (btor_has_next_node_hash_table_iterator (&it))
    {
      lambda = btor_next_node_hash_table_iterator (&it);
      assert (BTOR_IS_REGULAR_NODE (lambda));

      /* already visited */
      if (btor_find_in_ptr_hash_table (map_value_index, lambda))
        continue;

      /* we only consider writes */
      if (btor_get_fun_arity (btor, lambda) > 1)
        continue;

      is_top = 0;
      btor_init_apply_parent_iterator (&pit, lambda);
      while (btor_has_next_apply_parent_iterator (&pit))
        {
          tmp = btor_next_apply_parent_iterator (&pit);

          if (!tmp->parameterized)
            {
              is_top = 1;
              break;
            }
        }

      if (!is_top)
        continue;

      BTOR_PUSH_STACK (mm, lambdas, lambda);
      while (!BTOR_EMPTY_STACK (lambdas))
        {
          lambda = BTOR_POP_STACK (lambdas);
          
          /* already visited */
          if (btor_find_in_ptr_hash_table (visit_cache, lambda))
            continue;

          btor_insert_in_ptr_hash_table (visit_cache, lambda);

          cur = lambda;
          index_cache = btor_new_ptr_hash_table (mm, 0, 0);
          prev_index = prev_value = 0;
          while (is_write_exp (cur, &array, &index, &value))
            {
              assert (BTOR_IS_REGULAR_NODE (array));
              assert (BTOR_IS_FUN_NODE (array));

              /* index already cached, this index will be overwritten anyways,
               * so we can skip it */
              if (btor_find_in_ptr_hash_table (index_cache, index))
                {
                  cur = array;
                  continue;
                }

              /* collect index/value pairs for absolute set patterns */
              if (is_abs_set_pattern (index, prev_index))
                {
                  btor_insert_in_ptr_hash_table (index_cache, index);
                  add_to_index_map (btor, map_value_index,
                                    lambda, index, value);
                }
              // TODO (ma): is there a way to recognize base_addr + 0 as
              //            relative?
              //            -> only if its the last index
              //               - prev_index->base_addr == index
              else if (is_rel_set_pattern (index, prev_index))
                {
                  /* collect index/value pairs for memcopy pattern if 'index'
                   * and 'value' still belong to current memcopy pattern */
                  if (is_copy_pattern (index, value,
                                       prev_index, prev_value, array))
                    {
                      /* optimization for memcopy: do not visit lambdas that
                       * are only accessed via this lambda (reduces number of
                       * redundant memcopy patterns) */
                      if (value->e[0] == array && array->parents == 2)
                        btor_insert_in_ptr_hash_table (visit_cache, array);
                      btor_insert_in_ptr_hash_table (index_cache, index);
                      add_to_index_map (btor, map_value_index,
                                        lambda, index, value);
                    }
                  /* collect index/value pairs for relative set patterns */
                  else
                    {
                      btor_insert_in_ptr_hash_table (index_cache, index);
                      add_to_index_map (btor, map_value_index,
                                        lambda, index, value);
                    }
                }
              /* use array as new start point */
              else
                {
                  BTOR_PUSH_STACK (mm, lambdas, array); 
                  break;
                }

              cur = array;
              prev_index = index;
              prev_value = value;
            }
          if (btor_find_in_ptr_hash_table (map_value_index, lambda))
            {
              assert (!btor_find_in_ptr_hash_table (map_lambda_base, lambda));
              btor_insert_in_ptr_hash_table (
                  map_lambda_base, lambda)->data.asPtr = cur;
            }
          btor_delete_ptr_hash_table (index_cache);

          // TODO (ma): can only be ite now
          if (is_array_ite_exp (cur, &array_if, &array_else))
            {
              BTOR_PUSH_STACK (mm, lambdas, array_if);
              BTOR_PUSH_STACK (mm, lambdas, array_else);
            }
        }
    }
  btor_delete_ptr_hash_table (visit_cache);
  BTOR_RELEASE_STACK (mm, lambdas);
}
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);
}
Example #21
0
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;
}
Example #22
0
BtorNode *
btor_non_recursive_extended_substitute_node (
  Btor * btor,
  BtorNodeMap * map,
  void * state,
  BtorNodeMapper mapper,
  BtorNodeReleaser release,
  BtorNode * root)
{
  BtorNodePtrStack working_stack, marked_stack;
  BtorNode * res, * node, * mapped;
  BtorMemMgr * mm;
  int i;

  if (map->simplify)
    root = btor_simplify_exp (BTOR_REAL_ADDR_NODE (root)->btor, root);

  mm  = btor->mm;

  BTOR_INIT_STACK (working_stack);
  BTOR_INIT_STACK (marked_stack);
  BTOR_PUSH_STACK (mm, working_stack, root);
  
  while (!BTOR_EMPTY_STACK (working_stack))
    {
      node = BTOR_POP_STACK (working_stack);
      node = BTOR_REAL_ADDR_NODE (node);
      assert (node->kind != BTOR_PROXY_NODE);
      if (btor_mapped_node (map, node))
        continue;
      if (node->mark == 2)
        continue;
      mapped = mapper (btor, state, node);
      if (mapped)
        {
          btor_map_node (map, node, mapped);
          release (btor, mapped);
        }
      else
      if (!node->mark)
        {
          node->mark = 1;
          BTOR_PUSH_STACK (mm, working_stack, node);
          BTOR_PUSH_STACK (mm, marked_stack, node);
          for (i = node->arity - 1; i >= 0; i--)
            BTOR_PUSH_STACK (mm, working_stack, node->e[i]);
        }
      else
        {
          mapped = btor_map_node_internal (btor, map, node);
          btor_map_node (map, node, mapped);
          btor_release_exp (btor, mapped);
          assert (node->mark == 1);
          node->mark = 2;
        }
    }
  BTOR_RELEASE_STACK (mm, working_stack);
  while (!BTOR_EMPTY_STACK (marked_stack))
    {
      node = BTOR_POP_STACK (marked_stack);
      assert (node->mark == 2);
      node->mark = 0;
    }
  BTOR_RELEASE_STACK (mm, marked_stack);
  res = btor_mapped_node (map, root);
  assert (res);
  return res;
}
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;
}