Example #1
0
void sat_path_enumeratort::record_path(scratch_programt &program)
{
  distinguish_valuest path_val;

  for(const auto &expr : distinguishers)
    path_val[expr]=program.eval(expr).is_true();

  accelerated_paths.push_back(path_val);
}
void disjunctive_polynomial_accelerationt::record_path(scratch_programt &program) {
  distinguish_valuest path_val;

  for (std::list<exprt>::iterator it = distinguishers.begin();
       it != distinguishers.end();
       ++it) {
    path_val[*it] = program.eval(*it).is_true();
  }

  accelerated_paths.push_back(path_val);
}
Example #3
0
void polynomial_acceleratort::stash_variables(scratch_programt &program,
                                              expr_sett modified,
                                              substitutiont &substitution) {
  find_symbols_sett vars;

  for (expr_sett::iterator it = modified.begin();
       it != modified.end();
       ++it) {
    find_symbols(*it, vars);
  }

  irep_idt loop_counter_name = to_symbol_expr(loop_counter).get_identifier();
  vars.erase(loop_counter_name);

  for (find_symbols_sett::iterator it = vars.begin();
       it != vars.end();
       ++it) {
    symbolt orig = symbol_table.lookup(*it);
    symbolt stashed_sym = utils.fresh_symbol("polynomial::stash", orig.type);
    substitution[orig.symbol_expr()] = stashed_sym.symbol_expr();
    program.assign(stashed_sym.symbol_expr(), orig.symbol_expr());
  }
}
Example #4
0
void polynomial_acceleratort::assert_for_values(scratch_programt &program,
                                                std::map<exprt, int> &values,
                                                std::set<std::pair<expr_listt, exprt> >
                                                   &coefficients,
                                                int num_unwindings,
                                                goto_programt::instructionst
                                                   &loop_body,
                                                exprt &target,
                                                overflow_instrumentert &overflow) {
  // First figure out what the appropriate type for this expression is.
  typet expr_type = nil_typet();

  for (std::map<exprt, int>::iterator it = values.begin();
      it != values.end();
      ++it) {
    typet this_type=it->first.type();
    if (this_type.id() == ID_pointer) {
#ifdef DEBUG
      std::cout << "Overriding pointer type" << std::endl;
#endif
      this_type = unsignedbv_typet(config.ansi_c.pointer_width);
    }

    if (expr_type == nil_typet()) {
      expr_type = this_type;
    } else {
      expr_type = join_types(expr_type, this_type);
    }
  }

  assert(to_bitvector_type(expr_type).get_width()>0);


  // Now set the initial values of the all the variables...
  for (std::map<exprt, int>::iterator it = values.begin();
       it != values.end();
       ++it) {
    program.assign(it->first, from_integer(it->second, expr_type));
  }

  // Now unwind the loop as many times as we need to.
  for (int i = 0; i < num_unwindings; i++) {
    program.append(loop_body);
  }

  // Now build the polynomial for this point and assert it fits.
  exprt rhs = nil_exprt();

  for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin();
       it != coefficients.end();
       ++it) {
    int concrete_value = 1;

    for (expr_listt::const_iterator e_it = it->first.begin();
         e_it != it->first.end();
         ++e_it) {
      exprt e = *e_it;

      if (e == loop_counter) {
        concrete_value *= num_unwindings;
      } else {
        std::map<exprt, int>::iterator v_it = values.find(e);

        if (v_it != values.end()) {
          concrete_value *= v_it->second;
        }
      }
    }

    // OK, concrete_value now contains the value of all the relevant variables
    // multiplied together.  Create the term concrete_value*coefficient and add
    // it into the polynomial.
    typecast_exprt cast(it->second, expr_type);
    exprt term = mult_exprt(from_integer(concrete_value, expr_type), cast);

    if (rhs.is_nil()) {
      rhs = term;
    } else {
      rhs = plus_exprt(rhs, term);
    }
  }

  exprt overflow_expr;
  overflow.overflow_expr(rhs, overflow_expr);

  program.add_instruction(ASSUME)->guard = not_exprt(overflow_expr);

  rhs = typecast_exprt(rhs, target.type());

  // We now have the RHS of the polynomial.  Assert that this is equal to the
  // actual value of the variable we're fitting.
  exprt polynomial_holds = equal_exprt(target, rhs);

  // Finally, assert that the polynomial equals the variable we're fitting.
  goto_programt::targett assumption = program.add_instruction(ASSUME);
  assumption->guard = polynomial_holds;
}
void disjunctive_polynomial_accelerationt::build_path(
    scratch_programt &scratch_program, patht &path) {
  goto_programt::targett t = loop_header;

  do {
    goto_programt::targett next;
    goto_programt::targetst succs;

    goto_program.get_successors(t, succs);

    // We should have a looping path, so we should never hit a location
    // with no successors.
    assert(succs.size() > 0);

    if (succs.size() == 1) {
      // Only one successor -- accumulate it and move on.
      path.push_back(path_nodet(t));
      t = succs.front();
      continue;
    }

    // We have multiple successors.  Examine the distinguisher variables
    // to see which branch was taken.
    bool found_branch = false;

    for (goto_programt::targetst::iterator it = succs.begin();
         it != succs.end();
         ++it) {
      exprt &distinguisher = distinguishing_points[*it];
      bool taken = scratch_program.eval(distinguisher).is_true();

      if (taken) {
        if (!found_branch ||
            ((*it)->location_number < next->location_number)) {
          next = *it;
        }

        found_branch = true;
      }
    }

    assert(found_branch);

    exprt cond = nil_exprt();

    if (t->is_goto()) {
      // If this was a conditional branch (it probably was), figure out
      // if we hit the "taken" or "not taken" branch & accumulate the
      // appropriate guard.
      cond = not_exprt(t->guard);

      for (goto_programt::targetst::iterator it = t->targets.begin();
           it != t->targets.end();
           ++it) {
        if (next == *it) {
          cond = t->guard;
          break;
        }
      }
    }

    path.push_back(path_nodet(t, cond));

    t = next;
  } while (t != loop_header && (loop.find(t) != loop.end()));
}
void disjunctive_polynomial_accelerationt::assert_for_values(
  scratch_programt &program,
  std::map<exprt, exprt> &values,
  std::set<std::pair<expr_listt, exprt> > &coefficients,
  int num_unwindings,
  goto_programt &loop_body,
  exprt &target)
{
  // First figure out what the appropriate type for this expression is.
  typet expr_type = nil_typet();

  for (std::map<exprt, exprt>::iterator it = values.begin();
      it != values.end();
      ++it) {
    if (expr_type == nil_typet()) {
      expr_type = it->first.type();
    } else {
      expr_type = join_types(expr_type, it->first.type());
    }
  }

  // Now set the initial values of the all the variables...
  for (std::map<exprt, exprt>::iterator it = values.begin();
       it != values.end();
       ++it) {
    program.assign(it->first, it->second);
  }

  // Now unwind the loop as many times as we need to.
  for (int i = 0; i < num_unwindings; i++) {
    program.append(loop_body);
  }

  // Now build the polynomial for this point and assert it fits.
  exprt rhs = nil_exprt();

  for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin();
       it != coefficients.end();
       ++it) {
    exprt concrete_value = from_integer(1, expr_type);

    for (expr_listt::const_iterator e_it = it->first.begin();
         e_it != it->first.end();
         ++e_it) {
      exprt e = *e_it;

      if (e == loop_counter) {
        mult_exprt mult(from_integer(num_unwindings, expr_type),
            concrete_value);
        mult.swap(concrete_value);
      } else {
        std::map<exprt, exprt>::iterator v_it = values.find(e);

        assert(v_it != values.end());

        mult_exprt mult(concrete_value, v_it->second);
        mult.swap(concrete_value);
      }
    }

    // OK, concrete_value now contains the value of all the relevant variables
    // multiplied together.  Create the term concrete_value*coefficient and add
    // it into the polynomial.
    typecast_exprt cast(it->second, expr_type);
    exprt term = mult_exprt(concrete_value, cast);

    if (rhs.is_nil()) {
      rhs = term;
    } else {
      rhs = plus_exprt(rhs, term);
    }
  }

  rhs = typecast_exprt(rhs, target.type());

  // We now have the RHS of the polynomial.  Assert that this is equal to the
  // actual value of the variable we're fitting.
  exprt polynomial_holds = equal_exprt(target, rhs);

  // Finally, assert that the polynomial equals the variable we're fitting.
  goto_programt::targett assumption = program.add_instruction(ASSUME);
  assumption->guard = polynomial_holds;
}
Example #7
0
void acceleratet::build_state_machine(
  trace_automatont::sym_mapt::iterator begin,
  trace_automatont::sym_mapt::iterator end,
  state_sett &accept_states,
  symbol_exprt state,
  symbol_exprt next_state,
  scratch_programt &state_machine)
{
  std::map<unsigned int, unsigned int> successor_counts;
  unsigned int max_count=0;
  unsigned int likely_next=0;

  // Optimisation: find the most common successor state and initialise
  // next_state to that value.  This reduces the size of the state machine
  // driver substantially.
  for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p)
  {
    trace_automatont::state_pairt state_pair=p->second;
    unsigned int to=state_pair.second;
    unsigned int count=0;

    if(successor_counts.find(to)==successor_counts.end())
    {
      count=1;
    }
    else
    {
      count=successor_counts[to] + 1;
    }

    successor_counts[to]=count;

    if(count > max_count)
    {
      max_count=count;
      likely_next=to;
    }
  }

  // Optimisation: if there is only one possible successor state, just
  // jump straight to it instead of driving the whole machine.
  if(successor_counts.size()==1)
  {
    if(accept_states.find(likely_next)!=accept_states.end())
    {
      // It's an accept state.  Just assume(false).
      state_machine.assume(false_exprt());
    }
    else
    {
      state_machine.assign(state,
          from_integer(likely_next, next_state.type()));
    }

    return;
  }

  state_machine.assign(next_state,
      from_integer(likely_next, next_state.type()));

  for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p)
  {
    trace_automatont::state_pairt state_pair=p->second;
    unsigned int from=state_pair.first;
    unsigned int to=state_pair.second;

    if(to==likely_next)
    {
      continue;
    }

    // We're encoding the transition
    //
    //   from -loc-> to
    //
    // which we encode by inserting:
    //
    //   next_state=(state==from) ? to : next_state;
    //
    // just before loc.
    equal_exprt guard(state, from_integer(from, state.type()));
    if_exprt rhs(guard, from_integer(to, next_state.type()), next_state);
    state_machine.assign(next_state, rhs);
  }

  // Update the state and assume(false) if we've hit an accept state.
  state_machine.assign(state, next_state);

  for(state_sett::iterator it=accept_states.begin();
      it!=accept_states.end();
      ++it)
  {
    state_machine.assume(
      not_exprt(equal_exprt(state, from_integer(*it, state.type()))));
  }
}