Пример #1
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);
  }
}
Пример #2
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;
}
Пример #3
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();
}