Exemple #1
0
void termination_baset::find_required_steps(
  const goto_tracet &goto_trace,
  goto_tracet::stepst::const_iterator &loop_begin,
  required_stepst &required_steps,
  const std::string &prefix) const
{
  find_symbols_sett required_symbols;
  unsigned before=0, after=1;

  // initialize: find all (potential) loop exits and
  // remember the symbols in them
  for(goto_tracet::stepst::const_iterator it1=loop_begin;
      it1!=goto_trace.steps.end();
      it1++)
  {
    if(it1->pc->is_goto() &&
       it1->pc->function==loop_begin->pc->function)
    {
      bool found_next=false, found_target=false;
      goto_programt::const_targett next=it1->pc; next++;
      goto_programt::const_targett target=it1->pc->targets.front();

      for(goto_tracet::stepst::const_iterator it2=loop_begin;
          it2!=goto_trace.steps.end();
          it2++)
      {
        if(it1!=it2)
        {
          if(it2->pc==next)
            found_next=true;
          else if(it2->pc==target)
            found_target=true;
        }
      }

      if(!found_target || !found_next)
      {
        exprt temp=it1->cond_expr;
        remove_ssa_ids(temp);
        find_symbols(temp, required_symbols);
      }
    }
  }

  #if 0
  std::cout << "INITIAL SYMBOLS: ";
  for(find_symbols_sett::const_iterator it=required_symbols.begin();
      it!=required_symbols.end();
      it++)
    std::cout << *it << ", ";
  std::cout << std::endl;
  #endif

  // get the fixpoint
  while(before!=after)
  {
    before=required_symbols.size();

    for(goto_tracet::stepst::const_iterator step=loop_begin;
        step!=goto_trace.steps.end();
        step++)
    {
      find_symbols_sett intersection;

      if(step->is_assignment())
      {
        exprt lhs, rhs;

        const codet &code=to_code(step->pc->code);

        if(code.get_statement()==ID_assign)
        {
          const code_assignt &acode=to_code_assign(step->pc->code);
          lhs=acode.lhs();
          rhs=acode.rhs();
        }
        else if(code.get_statement()==ID_function_call)
        {
          const code_function_callt fcode=to_code_function_call(step->pc->code);
          lhs=fcode.lhs();
          rhs=fcode.op2();
        }
        else
          throw "Unexpected assign statement";

        if(lhs.id()==ID_symbol &&
           has_prefix(lhs.get_string(ID_identifier), prefix))
        {
          // if we depend on the RHS syms, we also need the pre-symbol
          find_symbols_sett rhs_sym;
          find_symbols(rhs, rhs_sym);

          if(intersects(rhs_sym, required_symbols))
          {
            find_symbols(lhs, required_symbols);
            required_steps.insert(&(*step));
          }
        }
        else
        {
          find_symbols_sett lhs_sym;

          if(lhs.id()==ID_index)
            find_symbols(lhs.op0(), lhs_sym); // we're not modifying the index
          else
            find_symbols(lhs, lhs_sym);

           if(intersects(lhs_sym, required_symbols))
           {
             find_symbols(rhs, required_symbols);
             required_steps.insert(&(*step));
           }
        }
      }
      else if(step->is_assume())
      {
        find_symbols_sett syms;
        find_symbols(step->pc->guard, syms);

        if(intersects(syms, required_symbols))
        {
          required_symbols.insert(syms.begin(), syms.end());
          required_steps.insert(&(*step));
        }
      }
    }

    after=required_symbols.size();

  #if 0
  std::cout << "REQUIRED SYMBOLS: ";
  for(find_symbols_sett::const_iterator it=required_symbols.begin();
      it!=required_symbols.end();
      it++)
    std::cout << *it << ", ";
  std::cout << std::endl;
  #endif
  }
}