Exemple #1
0
guardt &operator -= (guardt &g1, const guardt &g2)
{
  if(g1.id()!=ID_and || g2.id()!=ID_and)
    return g1;

  sort_and_join(g1);
  guardt g2_sorted=g2;
  sort_and_join(g2_sorted);

  exprt::operandst &op1=g1.operands();
  const exprt::operandst &op2=g2_sorted.operands();

  exprt::operandst::iterator it1=op1.begin();
  for(exprt::operandst::const_iterator
      it2=op2.begin();
      it2!=op2.end();
      ++it2)
  {
    while(it1!=op1.end() && *it1<*it2)
      ++it1;
    if(it1!=op1.end() && *it1==*it2)
      it1=op1.erase(it1);
  }

  g1=conjunction(op1);

  return g1;
}
Exemple #2
0
void equality_domaint::project_on_vars(
  valuet &value,
  const var_sett &vars,
  exprt &result)
{
#if 0
  if(templ.size()==0)
    return domaint::project_on_vars(value, vars, result);
#endif

  equ_valuet &v=static_cast<equ_valuet &>(value);

  exprt::operandst c;
  for(unsigned index=0; index<templ.size(); index++)
  {
    const var_pairt &vv=templ[index].var_pair;

#if 0
    std::cout << vv.second << std::endl;
#endif
    if(vars.find(vv.first)==vars.end() ||
       (vars.find(vv.second)==vars.end() &&
        !(vv.second.id()==ID_constant &&
          to_constant_expr(vv.second).get_value()=="NULL")))
      continue;

    if(v.equs.same_set(vv.first, vv.second))
    {
      if(templ[index].kind==LOOP)
        c.push_back(
          implies_exprt(
            templ[index].pre_guard,
            equal_exprt(vv.first, vv.second)));
      else
        c.push_back(equal_exprt(vv.first, vv.second));
    }
  }

  for(index_sett::const_iterator it=v.disequs.begin();
      it!=v.disequs.end(); it++)
  {
    const var_pairt &vv=templ[*it].var_pair;

    if(vars.find(vv.first)==vars.end() ||
       (vars.find(vv.second)==vars.end() &&
        !(vv.second.id()==ID_constant &&
          to_constant_expr(vv.second).get_value()=="NULL")))
      continue;

    if(templ[*it].kind==LOOP)
      c.push_back(
        implies_exprt(
          templ[*it].pre_guard,
          notequal_exprt(vv.first, vv.second)));
    else
      c.push_back(notequal_exprt(vv.first, vv.second));
  }
  result=conjunction(c);
}
Exemple #3
0
int cmd(string str) {
    string opt, who, channel;
    object ob;

    if(!str) return 0;
    if(!archp(previous_object())) return 0;

    // Attempt to remove or add a players line rights.
    if(sscanf(str, "%s %s %s", opt, who, channel) == 3) {
        if(!(ob = find_player(lower_case(who)))) 
            return notify_fail("No such player online.\n");
        if(opt == "remove") {
            if(member_array(channel, ob->GetChannels()) == -1) {
                this_player()->eventPrint(ob->GetName()
                        + " is not currently subscribed to the " + channel + " line.");
                return 1;
            }
            ob->RestrictChannel(channel);
            this_player()->eventPrint("%^RED%^You restrict " + ob->GetName()
                    + " from the " + channel + " line.%^RESET%^");
            ob->eventPrint("%^RED%^You have lost your " + channel
                    + " line rights.%^RESET%^");
            return 1;
        }
        else if(opt == "add") {
            if(member_array(channel, ob->GetRestrictedChannels()) == -1) {
                message("system", ob->GetName() + " is not currently restricted from the "
                        + channel + " line.", this_player());
                return 1;
            }
            ob->UnrestrictChannel(channel);
            this_player()->eventPrint("%^RED%^You unrestrict " + ob->GetName()
                    + " from the " + channel + " line.%^RESET%^");
            ob->eventPrint("%^RED%^You have regained your " + channel
                    + " line rights.%^RESET%^");
            return 1;
        }
    }
    // Otherwise, return restriction information, if it is requested.
    else if(str) {
        string *channels;
        string tmp;
        int size;

        if(!(ob = find_player(lower_case(str)))) 
            return notify_fail("No such player online.\n");
        channels = ob->GetRestrictedChannels();
        size = sizeof(channels);
        tmp = ob->GetName() + " is currently restricted from ";
        if(size) tmp += "the " + conjunction(channels);
        else tmp += "no";
        if(size == 1) tmp += " line.";
        else tmp += " lines.";
        this_player()->eventPrint(tmp);
        return 1;
    }
    else return 0;
}
Exemple #4
0
exprt predabs_domaint::to_pre_constraints(const templ_valuet &value)
{
  assert(value.size()==templ.size());
  exprt::operandst c;
  for(std::size_t row=0; row<templ.size(); ++row)
  {
    c.push_back(get_row_pre_constraint(row, value[row]));
  }
  return conjunction(c);
}
Exemple #5
0
void summarizer_fw_termt::inline_summaries(
  const function_namet &function_name,
  local_SSAt &SSA, exprt precondition,
  bool context_sensitive,
  threevalt &calls_terminate,
  bool &has_function_calls)
{
  for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin();
      n_it!=SSA.nodes.end(); n_it++)
  {
    for(local_SSAt::nodet::function_callst::iterator f_it=
          n_it->function_calls.begin();
        f_it!=n_it->function_calls.end(); f_it++)
    {
      assert(f_it->function().id()==ID_symbol); // no function pointers

      exprt::operandst c;
      c.push_back(precondition);
      get_assertions(SSA, c); // assertions as assumptions
      precondition=conjunction(c);

      if(!options.get_bool_option("competition-mode") &&
         !check_call_reachable(
           function_name, SSA, n_it, f_it, precondition, true))
        continue;

      has_function_calls=true;
      irep_idt fname=to_symbol_expr(f_it->function()).get_identifier();

      if(!check_precondition(
           function_name, SSA, n_it, f_it, precondition, context_sensitive))
      {
        exprt precondition_call=true_exprt();
        if(context_sensitive)
          precondition_call=compute_calling_context(
            function_name, SSA, n_it, f_it, precondition, true);

        status() << "Recursively summarizing function " << fname << eom;
        compute_summary_rec(fname, precondition_call, context_sensitive);
        summaries_used++;
      }

      // get information about callee termination
      if(summary_db.exists(fname) && summary_db.get(fname).terminates!=YES)
      {
        // cannot propagate NO
        // because call reachability might be over-approximating
        calls_terminate=UNKNOWN;
        break;
      }
    }
  }
}
Exemple #6
0
void summarizer_fw_termt::do_termination(
  const function_namet &function_name,
  local_SSAt &SSA,
  summaryt &summary)
{
  // calling context, invariant, function call summaries
  exprt::operandst cond;
  if(!summary.fw_invariant.is_nil())
    cond.push_back(summary.fw_invariant);
  if(!summary.fw_precondition.is_nil())
    cond.push_back(summary.fw_precondition);
  cond.push_back(ssa_inliner.get_summaries(SSA));

  status() << "Synthesizing ranking function to prove termination" << eom;
  // solver
  incremental_solvert &solver=ssa_db.get_solver(function_name);
  solver.set_message_handler(get_message_handler());

  template_generator_rankingt template_generator1(
    options, ssa_db, ssa_unwinder.get(function_name));
  template_generator1.set_message_handler(get_message_handler());
  template_generator1(solver.next_domain_number(), SSA, true);

  if(template_generator1.all_vars().empty())
    return; // nothing to do

  get_assertions(SSA, cond); // add assertions as assumptions

  // compute ranking functions
  ssa_analyzert analyzer1;
  analyzer1.set_message_handler(get_message_handler());
  analyzer1(solver, SSA, conjunction(cond), template_generator1);
  analyzer1.get_result(
    summary.termination_argument, template_generator1.all_vars());

  // extract information whether a ranking function was found for all loops
  summary.terminates=check_termination_argument(summary.termination_argument);
  if(!summary.fw_precondition.is_true())
    summary.termination_argument=
      implies_exprt(summary.fw_precondition, summary.termination_argument);

  // statistics
  solver_instances+=analyzer1.get_number_of_solver_instances();
  solver_calls+=analyzer1.get_number_of_solver_calls();
  termargs_computed++;
}
Exemple #7
0
void predabs_domaint::project_on_vars(
  valuet &value,
  const var_sett &vars,
  exprt &result)
{
  const templ_valuet &v=static_cast<const templ_valuet &>(value);

  assert(v.size()==templ.size());
  exprt::operandst c;
  for(std::size_t row=0; row<templ.size(); row++)
  {
    const template_rowt &templ_row=templ[row];

    std::set<symbol_exprt> symbols;
    find_symbols(templ_row.expr, symbols);

    bool pure=true;
    for(const auto &symbol : symbols)
    {
      if(vars.find(symbol)==vars.end())
      {
        pure=false;
        break;
      }
    }
    if(!pure)
      continue;

    const row_valuet &row_v=v[row];
    if(templ_row.kind==LOOP)
    {
      c.push_back(
        implies_exprt(
          templ_row.pre_guard,
          implies_exprt(row_v, templ_row.expr)));
    }
    else
    {
      c.push_back(implies_exprt(row_v, templ_row.expr));
    }
  }
  result=conjunction(c);
}
Exemple #8
0
static Node mkAnd(const std::vector<TNode>& conjunctions) {
  Assert(conjunctions.size() > 0);

  std::set<TNode> all;
  all.insert(conjunctions.begin(), conjunctions.end());

  if (all.size() == 1) {
    // All the same, or just one
    return conjunctions[0];
  }

  NodeBuilder<> conjunction(kind::AND);
  std::set<TNode>::const_iterator it = all.begin();
  std::set<TNode>::const_iterator it_end = all.end();
  while (it != it_end) {
    conjunction << *it;
    ++ it;
  }

  return conjunction;
}
Exemple #9
0
void summarizer_bw_termt::do_nontermination(
  const function_namet &function_name,
  local_SSAt &SSA,
  const summaryt &old_summary,
  summaryt &summary)
{
  // calling context, invariant, function call summaries
  exprt::operandst cond;
  cond.push_back(old_summary.fw_invariant);
  cond.push_back(old_summary.fw_precondition);
  cond.push_back(ssa_inliner.get_summaries(SSA));
  ssa_inliner.get_summaries(SSA, false, cond, cond); // backward summaries

  if(!check_end_reachable(function_name, SSA, conjunction(cond)))
  {
    status() << "Function never terminates" << eom;
    summary.bw_transformer=false_exprt();
    summary.bw_precondition=false_exprt();
    summary.terminates=NO;
  }
}
bool strategy_solver_binsearch3t::iterate(invariantt &_inv)
{
  tpolyhedra_domaint::templ_valuet &inv=
    static_cast<tpolyhedra_domaint::templ_valuet &>(_inv);

  bool improved=false;

  solver.new_context(); // for improvement check

  exprt inv_expr=tpolyhedra_domain.to_pre_constraints(inv);

#if 0
  debug() << "improvement check: " << eom;
  debug() << "pre-inv: " << from_expr(ns, "", inv_expr) << eom;
#endif

  solver << inv_expr;

  exprt::operandst strategy_cond_exprs;
  tpolyhedra_domain.make_not_post_constraints(
    inv, strategy_cond_exprs, strategy_value_exprs);

  strategy_cond_literals.resize(strategy_cond_exprs.size());

#if 0
  debug() << "post-inv: ";
#endif
  for(std::size_t i=0; i<strategy_cond_exprs.size(); i++)
  {
#if 0
    debug() << (i>0 ? " || " : "") << from_expr(ns, "", strategy_cond_exprs[i]);
#endif
    strategy_cond_literals[i]=solver.convert(strategy_cond_exprs[i]);
    strategy_cond_exprs[i]=literal_exprt(strategy_cond_literals[i]);
  }
  debug() << eom;

  solver << disjunction(strategy_cond_exprs);

#if 0
  debug() << "solve(): ";
#endif

  std::set<tpolyhedra_domaint::rowt> improve_rows;
  std::map<tpolyhedra_domaint::rowt, symbol_exprt> symb_values;
  std::map<tpolyhedra_domaint::rowt, constant_exprt> lower_values;
  exprt::operandst blocking_constraint;
  bool improved_from_neginf=false;
  while(solver()==decision_proceduret::D_SATISFIABLE) // improvement check
  {
#if 0
    debug() << "SAT" << eom;
#endif
    improved=true;

    std::size_t row=0;
    for(; row<strategy_cond_literals.size(); row++)
    {
      if(solver.l_get(strategy_cond_literals[row]).is_true())
      {
#if 1
        debug() << "improve row " << row  << eom;
#endif
        improve_rows.insert(row);
        symb_values[row]=tpolyhedra_domain.get_row_symb_value(row);
        lower_values[row]=
          simplify_const(solver.get(strategy_value_exprs[row]));
        blocking_constraint.push_back(
          literal_exprt(!strategy_cond_literals[row]));
        if(tpolyhedra_domain.is_row_value_neginf(
             tpolyhedra_domain.get_row_value(row, inv)))
          improved_from_neginf=true;
      }
    }
    solver << conjunction(blocking_constraint);
  }
  solver.pop_context(); // improvement check

  if(!improved) // done
  {
#if 0
    debug() << "UNSAT" << eom;
#endif
    return improved;
  }

  // symbolic value system
  exprt pre_inv_expr=
    tpolyhedra_domain.to_symb_pre_constraints(inv, improve_rows);
  exprt post_inv_expr=
    tpolyhedra_domain.to_symb_post_constraints(improve_rows);

  assert(lower_values.size()>=1);
  std::map<tpolyhedra_domaint::rowt, symbol_exprt>::iterator
    it=symb_values.begin();
  exprt _lower=lower_values[it->first];
#if 1
  debug() << "update row " << it->first << ": "
          << from_expr(ns, "", lower_values[it->first]) << eom;
#endif
  tpolyhedra_domain.set_row_value(it->first, lower_values[it->first], inv);
  exprt _upper=
    tpolyhedra_domain.get_max_row_value(it->first);
  exprt sum=it->second;
  for(++it; it!=symb_values.end(); ++it)
  {
    sum=plus_exprt(sum, it->second);
    _upper=plus_exprt(_upper, tpolyhedra_domain.get_max_row_value(it->first));
    _lower=plus_exprt(_lower, lower_values[it->first]);

#if 1
    debug() << "update row " << it->first << ": "
            << from_expr(ns, "", lower_values[it->first]) << eom;
#endif
    tpolyhedra_domain.set_row_value(it->first, lower_values[it->first], inv);
  }

  // do not solve system if we have just reached a new loop
  //   (the system will be very large!)
  if(improved_from_neginf)
    return improved;

  solver.new_context(); // symbolic value system
  solver << pre_inv_expr;
  solver << post_inv_expr;

#if 1
  debug() << "symbolic value system: " << eom;
  debug() << "pre-inv: " << from_expr(ns, "", pre_inv_expr) << eom;
  debug() << "post-inv: " << from_expr(ns, "", post_inv_expr) << eom;
#endif

  extend_expr_types(sum);
  extend_expr_types(_upper);
  extend_expr_types(_lower);
  tpolyhedra_domaint::row_valuet upper=simplify_const(_upper);
  tpolyhedra_domaint::row_valuet lower=simplify_const(_lower);
  assert(sum.type()==upper.type());
  assert(sum.type()==lower.type());

  symbol_exprt sum_bound(
    SUM_BOUND_VAR+i2string(sum_bound_counter++),
    sum.type());
  solver << equal_exprt(sum_bound, sum);

#if 1
  debug() << from_expr(ns, "", equal_exprt(sum_bound, sum)) << eom;
#endif

  while(tpolyhedra_domain.less_than(lower, upper))
  {
    tpolyhedra_domaint::row_valuet middle=
      tpolyhedra_domain.between(lower, upper);
    if(!tpolyhedra_domain.less_than(lower, middle))
      middle=upper;

    // row_symb_value >= middle
    assert(sum_bound.type()==middle.type());
    exprt c=binary_relation_exprt(sum_bound, ID_ge, middle);

#if 1
    debug() << "upper: " << from_expr(ns, "", upper) << eom;
    debug() << "middle: " << from_expr(ns, "", middle) << eom;
    debug() << "lower: " << from_expr(ns, "", lower) << eom;
#endif

    solver.new_context(); // binary search iteration

#if 1
    debug() << "constraint: " << from_expr(ns, "", c) << eom;
#endif

    solver << c;

    if(solver()==decision_proceduret::D_SATISFIABLE)
    {
#if 0
      debug() << "SAT" << eom;
#endif

      lower=middle;

      for(const auto &sv : symb_values)
      {
#if 1
        debug() << "update row " << sv.first << " "
                << from_expr(ns, "", sv.second) << ": ";
#endif
        constant_exprt lower_row=
          simplify_const(solver.get(sv.second));
#if 1
        debug() << from_expr(ns, "", lower_row) << eom;
#endif
        tpolyhedra_domain.set_row_value(sv.first, lower_row, inv);
      }
    }
    else
    {
#if 0
      debug() << "UNSAT" << eom;
#endif

      if(!tpolyhedra_domain.less_than(middle, upper))
        middle=lower;

      upper=middle;
    }
    solver.pop_context(); // binary search iteration
  }

  solver.pop_context();  // symbolic value system

  return improved;
}
Exemple #11
0
exprt summarizer_bwt::compute_calling_context2(  
  const function_namet &function_name, 
  local_SSAt &SSA,
  summaryt old_summary,
  local_SSAt::nodest::const_iterator n_it, 
  local_SSAt::nodet::function_callst::const_iterator f_it,
  const exprt &postcondition,
  bool sufficient)
{
  assert(f_it->function().id()==ID_symbol); //no function pointers
  irep_idt fname = to_symbol_expr(f_it->function()).get_identifier();

  status() << "Computing calling context for function " << fname << eom;

  // solver
  incremental_solvert &solver = ssa_db.get_solver(function_name);
  solver.set_message_handler(get_message_handler());

  //analyze
  ssa_analyzert analyzer;
  analyzer.set_message_handler(get_message_handler());

  template_generator_callingcontextt template_generator(
    options,ssa_db,ssa_unwinder.get(function_name));
  template_generator.set_message_handler(get_message_handler());
  template_generator(solver.next_domain_number(),SSA,n_it,f_it,false);

  // collect globals at call site
  std::map<local_SSAt::nodet::function_callst::const_iterator, local_SSAt::var_sett>
    cs_globals_out;
  SSA.get_globals(n_it->location,cs_globals_out[f_it],false);

  exprt::operandst c;
  c.push_back(old_summary.fw_precondition);
  c.push_back(old_summary.fw_invariant);
  c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries
  exprt::operandst postcond;
  ssa_inliner.get_summaries(SSA,false,postcond,c); //backward summaries
  old_summary.bw_postcondition = postcondition; //that's a bit awkward
  collect_postconditions(function_name, SSA, old_summary, postcond,sufficient);
  if(!sufficient)
  {
    c.push_back(conjunction(postcond)); 
  }
  else //sufficient
  {
    c.push_back(not_exprt(conjunction(postcond))); 
  }

  analyzer(solver,SSA,conjunction(c),template_generator);

  // set preconditions
  local_SSAt &fSSA = ssa_db.get(fname); 

  exprt postcondition_call;
  analyzer.get_result(postcondition_call,
		      template_generator.callingcontext_vars());

  ssa_inliner.rename_to_callee(f_it, fSSA.params,
			     cs_globals_out[f_it],fSSA.globals_out,
			     postcondition_call);

  if(sufficient && 
     !postcondition_call.is_true()) //TODO: this should actually be handled by ssa_analyzer using a "guard-reachabiliity-only" analysis if template is empty
  {
    postcondition_call = not_exprt(postcondition_call); 
  }

  debug() << "Backward calling context for " << 
    from_expr(SSA.ns, "", *f_it) << ": " 
	  << from_expr(SSA.ns, "", postcondition_call) << eom;

  //statistics
  solver_instances += analyzer.get_number_of_solver_instances();
  solver_calls += analyzer.get_number_of_solver_calls();

  return postcondition_call;
}
Exemple #12
0
void summarizer_bwt::do_summary(const function_namet &function_name, 
				local_SSAt &SSA,
				const summaryt &old_summary,
				summaryt &summary,
				bool context_sensitive)
{
  bool sufficient = options.get_bool_option("sufficient");
  status() << "Computing preconditions" << eom;

  // solver
  incremental_solvert &solver = ssa_db.get_solver(function_name);
  solver.set_message_handler(get_message_handler());

  template_generator_summaryt template_generator(
    options,ssa_db,ssa_unwinder.get(function_name));
  template_generator.set_message_handler(get_message_handler());
  template_generator(solver.next_domain_number(),SSA,false);

  exprt::operandst c;
  c.push_back(old_summary.fw_precondition);
  c.push_back(old_summary.fw_invariant);
  c.push_back(ssa_inliner.get_summaries(SSA)); //forward summaries
  exprt::operandst postcond;
  ssa_inliner.get_summaries(SSA,false,postcond,c); //backward summaries
  collect_postconditions(function_name, SSA, summary, postcond,sufficient);
  if(!sufficient)
  {
    c.push_back(conjunction(postcond)); 
  }
  else //sufficient
  {
    c.push_back(not_exprt(conjunction(postcond))); 
  }

  if(!template_generator.out_vars().empty())
  {
    ssa_analyzert analyzer;
    analyzer.set_message_handler(get_message_handler());
    analyzer(solver,SSA,conjunction(c),template_generator);
    analyzer.get_result(summary.bw_transformer,template_generator.inout_vars());
    analyzer.get_result(summary.bw_invariant,template_generator.loop_vars());
    analyzer.get_result(summary.bw_precondition,template_generator.out_vars());

    //statistics
    solver_instances += analyzer.get_number_of_solver_instances();
    solver_calls += analyzer.get_number_of_solver_calls();
  }
  else // TODO: yet another workaround for ssa_analyzer not being able to handle empty templates properly
  {
    solver << SSA;
    solver.new_context();
    solver << SSA.get_enabling_exprs();
    solver << conjunction(c);
    exprt result = true_exprt();
    if(solver()==decision_proceduret::D_UNSATISFIABLE) result = false_exprt();
    solver.pop_context();
    summary.bw_transformer = result;
    summary.bw_invariant = result;
    summary.bw_precondition = result;
  }

  if(sufficient)
  {
    summary.bw_transformer = not_exprt(summary.bw_transformer);
    summary.bw_invariant = not_exprt(summary.bw_invariant);
    summary.bw_precondition = not_exprt(summary.bw_precondition);
  }

  if(context_sensitive && !summary.bw_postcondition.is_true())
  {
    summary.bw_transformer = 
      implies_exprt(summary.bw_postcondition,summary.bw_transformer);
    summary.bw_invariant = 
      implies_exprt(summary.bw_postcondition,summary.bw_invariant);
    summary.bw_precondition = 
      implies_exprt(summary.bw_postcondition,summary.bw_precondition);
  }
}
Exemple #13
0
guardt &operator |= (guardt &g1, const guardt &g2)
{
  if(g2.is_false() || g1.is_true()) return g1;
  if(g1.is_false() || g2.is_true()) { g1=g2; return g1; }

  if(g1.id()!=ID_and || g2.id()!=ID_and)
  {
    exprt tmp(g2);
    tmp.make_not();

    if(tmp==g1)
      g1.make_true();
    else
      g1=or_exprt(g1, g2);

    // TODO: make simplify more capable and apply here

    return g1;
  }

  // find common prefix
  sort_and_join(g1);
  guardt g2_sorted=g2;
  sort_and_join(g2_sorted);

  exprt::operandst &op1=g1.operands();
  const exprt::operandst &op2=g2_sorted.operands();

  exprt::operandst n_op1, n_op2;
  n_op1.reserve(op1.size());
  n_op2.reserve(op2.size());

  exprt::operandst::iterator it1=op1.begin();
  for(exprt::operandst::const_iterator
      it2=op2.begin();
      it2!=op2.end();
      ++it2)
  {
    while(it1!=op1.end() && *it1<*it2)
    {
      n_op1.push_back(*it1);
      it1=op1.erase(it1);
    }
    if(it1!=op1.end() && *it1==*it2)
      ++it1;
    else
      n_op2.push_back(*it2);
  }
  while(it1!=op1.end())
  {
    n_op1.push_back(*it1);
    it1=op1.erase(it1);
  }

  if(n_op2.empty()) return g1;

  // end of common prefix
  exprt and_expr1=conjunction(n_op1);
  exprt and_expr2=conjunction(n_op2);

  g1=conjunction(op1);

  exprt tmp(and_expr2);
  tmp.make_not();

  if(tmp!=and_expr1)
  {
    if(and_expr1.is_true() || and_expr2.is_true())
    {
    }
    else
      // TODO: make simplify more capable and apply here
      g1.add(or_exprt(and_expr1, and_expr2));
  }

  return g1;
}
Exemple #14
0
void summarizer_fwt::do_summary(const function_namet &function_name, 
				local_SSAt &SSA,
				summaryt &summary,
				exprt cond,
				bool context_sensitive)
{
  status() << "Computing summary" << eom;

  // solver
  incremental_solvert &solver = ssa_db.get_solver(function_name);
  solver.set_message_handler(get_message_handler());

  //analyze
  ssa_analyzert analyzer;
  analyzer.set_message_handler(get_message_handler());

  template_generator_summaryt template_generator(
    options,ssa_db,ssa_unwinder.get(function_name));
  template_generator.set_message_handler(get_message_handler());
  template_generator(solver.next_domain_number(),SSA,true);

  exprt::operandst conds;
  conds.reserve(5);
  conds.push_back(cond);
  conds.push_back(summary.fw_precondition);
  conds.push_back(ssa_inliner.get_summaries(SSA));

#ifdef REUSE_INVARIANTS
  if(summary_db.exists(function_name)) //reuse existing invariants
  {
    const exprt &old_inv = summary_db.get(function_name).fw_invariant;
    exprt inv = ssa_unwinder.get(function_name).rename_invariant(old_inv);
    conds.push_back(inv);

#if 0
    std::ostringstream out;
    out << "(original inv)" << from_expr(SSA.ns,"",old_inv) << "\n";
    debug() << out.str() << eom;
    out << "(renamed inv)" << from_expr(SSA.ns,"",inv)<<"\n";
    debug() << out.str() << eom;
#endif
  }
#endif

  cond = conjunction(conds);

  bool assertions_check = false; //options.get_bool_option("k-induction");
  bool assertions_hold = analyzer(solver,SSA,cond,template_generator,
                                  assertions_check);
  if(assertions_hold)
  {
    analyzer.get_result(summary.fw_transformer,template_generator.inout_vars());
    analyzer.get_result(summary.fw_invariant,template_generator.loop_vars());

#ifdef SHOW_WHOLE_RESULT
    // to see all the custom template values
    exprt whole_result;
    analyzer.get_result(whole_result,template_generator.all_vars());
    debug() << "whole result: " << from_expr(SSA.ns,"",whole_result) << eom;
#endif

    if(context_sensitive && !summary.fw_precondition.is_true())
    {
      summary.fw_transformer = 
	implies_exprt(summary.fw_precondition,summary.fw_transformer);
      summary.fw_invariant = 
	implies_exprt(summary.fw_precondition,summary.fw_invariant);
    }
  }
  else //!assertions_hold
  {
    nonpassed_assertions = true; 
    summary.nonpassed_assertions = analyzer.get_nonpassed_assertions();
  }

  solver_instances += analyzer.get_number_of_solver_instances();
  solver_calls += analyzer.get_number_of_solver_calls();
}
property_checkert::resultt summary_checker_acdlt::operator()(
  const goto_modelt &goto_model)
{
  const namespacet ns(goto_model.symbol_table);

  SSA_functions(goto_model, ns);
  ssa_unwinder.init(false, false);

  unsigned unwind=options.get_unsigned_int_option("unwind");
  if(unwind>0)
  {
    status() << "Unwinding" << messaget::eom;
    ssa_unwinder.init_localunwinders();
    ssa_unwinder.unwind_all(unwind);
  }

  irep_idt entry_point=goto_model.goto_functions.entry_point();
  std::cout << entry_point << std::endl;
  local_SSAt &SSA=ssa_db.get(entry_point);
  ssa_local_unwindert &ssa_local_unwinder=ssa_unwinder.get(entry_point);

  const goto_programt &goto_program=SSA.goto_function.body;
  for(goto_programt::instructionst::const_iterator
        i_it=goto_program.instructions.begin();
      i_it!=goto_program.instructions.end();
      i_it++)
  {
    /*if(!i_it->is_assert() || !i_it->is_assume())
      continue;
    */

    const source_locationt &location=i_it->source_location;
    irep_idt property_id=location.get_property_id();

    if(i_it->guard.is_true())
    {
      property_map[property_id].result=PASS;
      continue;
    }

    if(property_id=="") // TODO: some properties do not show up in initialize_property_map
      continue;

    // get loophead selects
    exprt::operandst loophead_selects;
    for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin();
        n_it!=SSA.nodes.end(); n_it++)
    {
      if(n_it->loophead==SSA.nodes.end()) continue;
      symbol_exprt lsguard=
        SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location);
      ssa_unwinder.get(entry_point).unwinder_rename(lsguard, *n_it, true);
      loophead_selects.push_back(not_exprt(lsguard));
    }

    // iterate over assumptions
    exprt::operandst assumptions;
    for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin();
        n_it!=SSA.nodes.end(); n_it++)
    {
      for(local_SSAt::nodet::assumptionst::const_iterator
            a_it=n_it->assumptions.begin();
          a_it!=n_it->assumptions.end(); a_it++)
      {
        std::cout << "Assumption:: " << from_expr(*a_it) << std::endl;
        assumptions.push_back(*a_it);
      }
    }
    // iterate over assertions
    std::list<local_SSAt::nodest::const_iterator> assertion_nodes;
    SSA.find_nodes(i_it, assertion_nodes);
    std::cout << "The number of assertions are: "
              << assertion_nodes.size() << std::endl;
    exprt::operandst assertions;
    for(std::list<local_SSAt::nodest::const_iterator>::const_iterator
          n_it=assertion_nodes.begin();
        n_it!=assertion_nodes.end();
        n_it++)
    {
      for(local_SSAt::nodet::assertionst::const_iterator
            a_it=(*n_it)->assertions.begin();
          a_it!=(*n_it)->assertions.end();
          a_it++)
      {
        assertions.push_back(*a_it);
      }
    }

    // if(simplify) property=simplify_expr(property, SSA.ns);
    property_map[property_id].location=i_it;

    // TODO: make the solver incremental

    // configure components of acdl solver
    // domain
    acdl_domaint domain(options, SSA, ssa_db, ssa_local_unwinder);
    domain.set_message_handler(get_message_handler());

    // worklist heuristics
    std::unique_ptr<acdl_worklist_baset> worklist;
    if(options.get_option("propagate")=="forward")
      worklist=std::unique_ptr<acdl_worklist_baset>(
        new acdl_worklist_forwardt());
    if(options.get_option("propagate")=="backward")
      worklist=std::unique_ptr<acdl_worklist_baset>(
        new acdl_worklist_backwardt());
    else if(options.get_option("propagate")=="chaotic")
      worklist=std::unique_ptr<acdl_worklist_baset>(
        new acdl_worklist_orderedt());

    // conflict analysis heuristics
    std::unique_ptr<acdl_analyze_conflict_baset> conflict_analysis;
    if(options.get_option("learning")=="first-uip")
      // TODO: no 'new' with base class!
      conflict_analysis=std::unique_ptr<acdl_analyze_conflict_baset>(
        new acdl_analyze_conflict_baset(domain));

    // decision heuristics
    std::unique_ptr<acdl_decision_heuristics_baset> decision_heuristics;
    if(options.get_option("decision")=="random")
      decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>(
        new acdl_decision_heuristics_randt(domain));
    else if(options.get_option("decision")=="ordered")
      decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>(
        new acdl_decision_heuristics_orderedt(domain));
    else if(options.get_option("decision")=="octagon")
      decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>(
        new acdl_decision_heuristics_octagont(domain));
    else if(options.get_option("decision")=="berkmin")
      decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>(
        new acdl_decision_heuristics_berkmint(domain, *conflict_analysis));
    else if(options.get_option("decision")=="range")
      decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>(
        new acdl_decision_heuristics_ranget(domain));

    // now instantiate solver
    acdl_solvert acdl_solver(
      options,
      domain,
      *decision_heuristics,
      *worklist,
      *conflict_analysis);

    acdl_solver.set_message_handler(get_message_handler());

    property_map[property_id].result=
      acdl_solver(
        ssa_db.get(goto_model.goto_functions.entry_point()),
        conjunction(assertions),
        conjunction(loophead_selects),
        conjunction(assumptions));
  }

  summary_checker_baset::resultt result=property_checkert::PASS;
  for(property_mapt::const_iterator
        p_it=property_map.begin(); p_it!=property_map.end(); p_it++)
  {
    if(p_it->second.result==FAIL)
      return property_checkert::FAIL;
    if(p_it->second.result==UNKNOWN)
      result=property_checkert::UNKNOWN;
  }

  return result;
}
Exemple #16
0
exprt summarizer_bw_termt::compute_precondition(
  local_SSAt &SSA,
  summaryt &summary,
  const exprt::operandst &postconditions,
  incremental_solvert &solver,
  template_generator_summaryt &template_generator,
  bool context_sensitive)
{
  exprt postcond=not_exprt(conjunction(postconditions));

  // compute backward summary
  exprt bw_transformer, bw_invariant, bw_precondition;
  if(!template_generator.out_vars().empty())
  {
    ssa_analyzert analyzer;
    analyzer.set_message_handler(get_message_handler());
    analyzer(solver, SSA, postcond, template_generator);
    analyzer.get_result(bw_transformer, template_generator.inout_vars());
    analyzer.get_result(bw_invariant, template_generator.loop_vars());
    analyzer.get_result(bw_precondition, template_generator.out_vars());

    // statistics
    solver_instances+=analyzer.get_number_of_solver_instances();
    solver_calls+=analyzer.get_number_of_solver_calls();
  }
#if 1
  // TODO: yet another workaround for ssa_analyzer
  //  not being able to handle empty templates properly
  else
  {
    solver << SSA;
    solver.new_context();
    solver << SSA.get_enabling_exprs();
    solver << postcond;
    exprt result=true_exprt();
    if(solver()==decision_proceduret::D_UNSATISFIABLE)
      result=false_exprt();
    solver.pop_context();
    bw_transformer=result;
    bw_invariant=result;
    bw_precondition=result;
  }
#endif

  bw_transformer=not_exprt(bw_transformer);
  bw_invariant=not_exprt(bw_invariant);
  bw_precondition=not_exprt(bw_precondition);

  if(context_sensitive && !summary.bw_postcondition.is_true())
  {
    bw_transformer=implies_exprt(summary.bw_postcondition, bw_transformer);
    bw_invariant=implies_exprt(summary.bw_postcondition, bw_invariant);
    bw_precondition=implies_exprt(summary.bw_postcondition, bw_precondition);
  }

  // join // TODO: should go into summaryt
  if(summary.bw_transformer.is_nil())
  {
    summary.bw_transformer=bw_transformer;
    summary.bw_invariant=bw_invariant;
    summary.bw_precondition=bw_precondition;
  }
  else
  {
    summary.bw_transformer=or_exprt(summary.bw_transformer, bw_transformer);
    summary.bw_invariant=or_exprt(summary.bw_invariant, bw_invariant);
    summary.bw_precondition=or_exprt(summary.bw_precondition, bw_precondition);
  }

  return bw_precondition;
}
Exemple #17
0
bool summarizer_bw_termt::bootstrap_preconditions(
  local_SSAt &SSA,
  summaryt &summary,
  incremental_solvert &solver,
  template_generator_rankingt &template_generator1,
  template_generator_summaryt &template_generator2,
  exprt &termination_argument)
{
  // bootstrap with a concrete model for input variables
  const domaint::var_sett &invars=template_generator2.out_vars();
  solver.new_context();

  unsigned number_bootstraps=0;
  termination_argument=true_exprt();
  exprt::operandst checked_candidates;
  while(number_bootstraps++<MAX_BOOTSTRAP_ATTEMPTS)
  {
    // find new ones
    solver << not_exprt(summary.bw_precondition);
    // last node should be reachable
    solver << SSA.guard_symbol(--SSA.goto_function.body.instructions.end());

    // statistics
    solver_calls++;

    // solve
    exprt precondition;
    if(solver()==decision_proceduret::D_SATISFIABLE)
    {
      exprt::operandst c;
      for(domaint::var_sett::const_iterator it=invars.begin();
          it!=invars.end(); it++)
      {
        c.push_back(equal_exprt(*it, solver.solver->get(*it)));
      }
      precondition=conjunction(c);
      debug() << "bootstrap model for precondition: "
              << from_expr(SSA.ns, "", precondition) << eom;
      solver.pop_context();
    }
    else // whole precondition space covered
    {
      solver.pop_context();
      break;
    }

    termination_argument=
      compute_termination_argument(
        SSA, precondition, solver, template_generator1);

    if(summarizer_fw_termt::check_termination_argument(
         termination_argument)==YES)
    {
      return true;
    }

    solver.new_context();
    checked_candidates.push_back(precondition);
    solver << not_exprt(disjunction(checked_candidates)); // next one, please!
  }

  return false;
}
Exemple #18
0
void summarizer_bw_termt::do_summary_term(
  const function_namet &function_name,
  local_SSAt &SSA,
  const summaryt &old_summary,
  summaryt &summary,
  bool context_sensitive)
{
  status() << "Computing preconditions for termination" << eom;

  // solver
  incremental_solvert &solver=ssa_db.get_solver(function_name);
  solver.set_message_handler(get_message_handler());

  // templates for ranking functions
  template_generator_rankingt template_generator1(
    options, ssa_db, ssa_unwinder.get(function_name));
  template_generator1.set_message_handler(get_message_handler());
  template_generator1(solver.next_domain_number(), SSA, true);

  // templates for backward summary
  template_generator_summaryt template_generator2(
    options, ssa_db, ssa_unwinder.get(function_name));
  template_generator2.set_message_handler(get_message_handler());
  template_generator2(solver.next_domain_number(), SSA, false);

  exprt::operandst bindings;
  exprt::operandst postcond;
  // backward summaries
  ssa_inliner.get_summaries(SSA, false, postcond, bindings);
  collect_postconditions(function_name, SSA, summary, postcond, true);

  // prepare solver
  solver << SSA;
  solver.new_context();
  solver << SSA.get_enabling_exprs();
  solver << old_summary.fw_precondition;
  solver << old_summary.fw_invariant;
  solver << ssa_inliner.get_summaries(SSA); // forward summaries
  solver << conjunction(bindings); // bindings for backward summaries

#if 0
  // compute preconditions individually
  // TODO: this should be done more transparently
  for(unsigned i=0; i<postcond.size(); i++)
  {
    exprt::operandst postcond2;
    postcond2.push_back(postcond[i]);
    compute_precondition(
      SSA, summary, postcond2, solver, template_generator2, context_sensitive);
  }
  postcond.clear();
#endif

  if(template_generator1.all_vars().empty())
  {
    compute_precondition(
      SSA, summary, postcond, solver, template_generator2, context_sensitive);
    solver.pop_context();
    return;
  }

  summary.bw_precondition=false_exprt(); // initialize
  unsigned number_disjuncts=0;
  while(number_disjuncts++<MAX_PRECONDITION_DISJUNCTS)
  {
    // bootstrap preconditions
    exprt termination_argument;
    if(!bootstrap_preconditions(
         SSA,
         summary,
         solver,
         template_generator1,
         template_generator2,
         termination_argument))
    {
      break;
    }

    // compute precondition
    // compute for individual termination arguments separately
    // TODO: this should be done more transparently
    if(termination_argument.id()==ID_and)
    {
      for(unsigned i=0; i<termination_argument.operands().size(); i++)
      {
        postcond.push_back(termination_argument.operands()[i]);

        exprt precondition=
          compute_precondition(
            SSA,
            summary,
            postcond,
            solver,
            template_generator2,
            context_sensitive);

        // join results
        if(summary.termination_argument.is_nil())
        {
          summary.termination_argument=
            implies_exprt(precondition, termination_argument);
        }
        else
        {
          summary.termination_argument=
            and_exprt(
              summary.termination_argument,
              implies_exprt(precondition, termination_argument));
        }

        // TODO: this is a bit asymmetric:
        //  the first precondition is joined with all other sources
        //  of non-termination (calls, bw calling context)
        postcond.clear();
      }
    }
    else // do not split termination arguments
    {
      postcond.push_back(termination_argument);
      exprt precondition=
        compute_precondition(
          SSA,
          summary,
          postcond,
          solver,
          template_generator2,
          context_sensitive);

      // join results
      if(summary.termination_argument.is_nil())
      {
        summary.termination_argument=
          implies_exprt(precondition, termination_argument);
      }
      else
      {
        summary.termination_argument=
          and_exprt(
            summary.termination_argument,
            implies_exprt(precondition, termination_argument));
      }

      // TODO: this is a bit asymmetric:
      //  the first precondition is joined with all other sources
      //  of non-termination (calls, bw calling context)
      postcond.clear();
    }
  }

  solver.pop_context();
}
exprt interval_domaint::make_expression(const symbol_exprt &src) const
{
  if(is_int(src.type()))
  {
    int_mapt::const_iterator i_it=int_map.find(src.get_identifier());
    if(i_it==int_map.end())
      return true_exprt();

    const integer_intervalt &interval=i_it->second;
    if(interval.is_top())
      return true_exprt();
    if(interval.is_bottom())
      return false_exprt();

    exprt::operandst conjuncts;

    if(interval.upper_set)
    {
      exprt tmp=from_integer(interval.upper, src.type());
      conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp));
    }

    if(interval.lower_set)
    {
      exprt tmp=from_integer(interval.lower, src.type());
      conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src));
    }

    return conjunction(conjuncts);
  }
  else if(is_float(src.type()))
  {
    float_mapt::const_iterator i_it=float_map.find(src.get_identifier());
    if(i_it==float_map.end())
      return true_exprt();

    const ieee_float_intervalt &interval=i_it->second;
    if(interval.is_top())
      return true_exprt();
    if(interval.is_bottom())
      return false_exprt();

    exprt::operandst conjuncts;

    if(interval.upper_set)
    {
      exprt tmp=interval.upper.to_expr();
      conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp));
    }

    if(interval.lower_set)
    {
      exprt tmp=interval.lower.to_expr();
      conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src));
    }

    return conjunction(conjuncts);
  }
  else
    return true_exprt();
}
Exemple #20
0
void cover_goals_extt::assignment()
{
  // check loop head choices in model
  bool invariants_involved=false;
  if(spurious_check)
  {
    for(exprt::operandst::const_iterator l_it=loophead_selects.begin();
        l_it!=loophead_selects.end(); l_it++)
    {
      if(solver.get(l_it->op0()).is_true())
      {
        invariants_involved=true;
        break;
      }
    }
  }
  if(!invariants_involved || !spurious_check)
  {
    std::list<cover_goals_extt::cover_goalt>::const_iterator g_it=goals.begin();
    for(goal_mapt::const_iterator it=goal_map.begin();
        it!=goal_map.end(); it++, g_it++)
    {
      if(property_map[it->first].result==property_checkert::UNKNOWN &&
         solver.l_get(g_it->condition).is_true())
      {
        property_map[it->first].result=property_checkert::FAIL;
        if(build_error_trace)
        {
          ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver());
          build_goto_trace(property_map[it->first].error_trace);
          if(!all_properties)
            break;
        }
      }
    }
    return;
  }

  solver.new_context();
  // force avoiding paths going through invariants

  solver << conjunction(loophead_selects);

  switch(solver())
  {
  case decision_proceduret::D_SATISFIABLE:
  {
    std::list<cover_goals_extt::cover_goalt>::const_iterator g_it=goals.begin();
    for(goal_mapt::const_iterator it=goal_map.begin();
        it!=goal_map.end(); it++, g_it++)
    {
      if(property_map[it->first].result==property_checkert::UNKNOWN &&
         solver.l_get(g_it->condition).is_true())
      {
        property_map[it->first].result=property_checkert::FAIL;
        if(build_error_trace)
        {
          ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver());
          build_goto_trace(property_map[it->first].error_trace);

#if 0
          show_raw_countermodel(
            it->first, SSA, *solver.solver, debug(), get_message_handler());
#endif
          if(!all_properties)
            break;
        }
      }
    }
    break;
  }
  case decision_proceduret::D_UNSATISFIABLE:
    break;

  case decision_proceduret::D_ERROR:
  default:
    throw "error from decision procedure";
  }

  solver.pop_context();

  _iterations++; // statistics
}