Esempio n. 1
0
void havoc_loopst::get_modifies(
  const loopt &loop,
  modifiest &modifies)
{
  for(loopt::const_iterator
      i_it=loop.begin(); i_it!=loop.end(); i_it++)
  {
    const goto_programt::instructiont &instruction=**i_it;

    if(instruction.is_assign())
    {
      const exprt &lhs=to_code_assign(instruction.code).lhs();
      function_modifies.get_modifies_lhs(local_may_alias, *i_it, lhs, modifies);
    }
    else if(instruction.is_function_call())
    {
      const code_function_callt &code_function_call=
        to_code_function_call(instruction.code);
      const exprt &lhs=code_function_call.lhs();

      // return value assignment
      if(lhs.is_not_nil())
        function_modifies.get_modifies_lhs(
          local_may_alias, *i_it, lhs, modifies);

      function_modifies(code_function_call.function(), modifies);
    }
  }
}
Esempio n. 2
0
goto_programt::targett havoc_loopst::get_loop_exit(const loopt &loop)
{
  assert(!loop.empty());

  // find the last instruction in the loop
  std::map<unsigned, goto_programt::targett> loop_map;

  for(loopt::const_iterator l_it=loop.begin();
      l_it!=loop.end();
      l_it++)
    loop_map[(*l_it)->location_number]=*l_it;

  // get the one with the highest number
  goto_programt::targett last=(--loop_map.end())->second;

  return ++last;
}
Esempio n. 3
0
void havoc_loopst::havoc_loop(
  const goto_programt::targett loop_head,
  const loopt &loop)
{
  assert(!loop.empty());

  // first find out what can get changed in the loop
  modifiest modifies;
  get_modifies(loop, modifies);

  // build the havocking code
  goto_programt havoc_code;
  build_havoc_code(loop_head, modifies, havoc_code);

  // Now havoc at the loop head. Use insert_swap to
  // preserve jumps to loop head.
  goto_function.body.insert_before_swap(loop_head, havoc_code);

  // compute the loop exit
  goto_programt::targett loop_exit=
    get_loop_exit(loop);

  // divert all gotos to the loop head to the loop exit
  for(loopt::const_iterator
      l_it=loop.begin(); l_it!=loop.end(); l_it++)
  {
    goto_programt::instructiont &instruction=**l_it;
    if(instruction.is_goto())
    {
      for(goto_programt::targetst::iterator
          t_it=instruction.targets.begin();
          t_it!=instruction.targets.end();
          t_it++)
      {
        if(*t_it==loop_head)
          *t_it=loop_exit; // divert
      }
    }
  }

  // remove skips
  remove_skip(goto_function.body);
}
Esempio n. 4
0
void k_inductiont::get_modifies(
  const loopt &loop,
  modifiest &modifies)
{
  for(loopt::const_iterator
      i_it=loop.begin(); i_it!=loop.end(); i_it++)
  {
    const goto_programt::instructiont &instruction=**i_it;

    if(instruction.is_assign())
    {
      const exprt &lhs=to_code_assign(instruction.code).lhs();
      get_modifies_lhs(*i_it, lhs, modifies);
    }
    else if(instruction.is_function_call())
    {
      const exprt &lhs=to_code_function_call(instruction.code).lhs();
      get_modifies_lhs(*i_it, lhs, modifies);
    }
  }
}
Esempio n. 5
0
void k_inductiont::process_loop(
  const goto_programt::targett loop_head,
  const loopt &loop)
{
  assert(!loop.empty());

  // compute the loop exit
  goto_programt::targett loop_exit=
    get_loop_exit(loop);

  if(base_case)
  {
    // now unwind k times
    unwind(goto_function.body, loop_head, loop_exit, k);

    // assume the loop condition has become false
    goto_programt::instructiont assume(ASSUME);
    assume.guard=loop_head->guard;
    goto_function.body.insert_before_swap(loop_exit, assume);
  }

  if(step_case)
  {
    // step case

    // find out what can get changed in the loop  
    modifiest modifies;
    get_modifies(loop, modifies);
    
    // build the havoc-ing code
    goto_programt havoc_code;
    build_havoc_code(loop_head, modifies, havoc_code);
    
    // unwind to get k+1 copies
    std::vector<goto_programt::targett> iteration_points;
    unwind(goto_function.body, loop_head, loop_exit, k+1, iteration_points);

    // now turn any assertions in iterations 0..k-1 into assumptions
    assert(iteration_points.size()==k+1);

    assert(k>=1);
    goto_programt::targett end=iteration_points[k-1];
    std::size_t it_p_count=0;
    bool after_it_p=true;
    for(goto_programt::targett t=loop_head; t!=end; t++)
    {
      assert(t!=goto_function.body.instructions.end());
      if(t->is_assert()) t->type=ASSUME;

      if(t==iteration_points[it_p_count])
      {
        after_it_p=true;
        ++it_p_count;
      }
      else if(t->is_goto() && after_it_p)
      {
        assert(t==loop_head ||
               not_exprt(t->guard)==loop_head->guard);
        t->type=ASSUME;
        t->targets.clear();
        t->guard=not_exprt(t->guard);
        after_it_p=false;
      }
    }

    // assume the loop condition has become false
    goto_programt::instructiont assume(ASSUME);
    assume.guard=to_not_expr(loop_head->guard).op();
    goto_function.body.insert_before_swap(loop_exit, assume);

    // Now havoc at the loop head. Use insert_swap to
    // preserve jumps to loop head.
    goto_function.body.insert_before_swap(loop_head, havoc_code);    
  }

  // remove skips
  remove_skip(goto_function.body);
}
Esempio n. 6
0
void k_inductiont::process_loop(
  const goto_programt::targett loop_head,
  const loopt &loop)
{
  assert(!loop.empty());

  // save the loop guard
  const exprt loop_guard=loop_head->guard;

  // compute the loop exit
  goto_programt::targett loop_exit=
    get_loop_exit(loop);

  if(base_case)
  {
    // now unwind k times
    unwind(goto_function.body, loop_head, loop_exit, k);

    // assume the loop condition has become false
    goto_programt::instructiont assume(ASSUME);
    assume.guard=loop_guard;
    goto_function.body.insert_before_swap(loop_exit, assume);
  }

  if(step_case)
  {
    // step case

    // find out what can get changed in the loop  
    modifiest modifies;
    get_modifies(loop, modifies);
    
    // build the havoc-ing code
    goto_programt havoc_code;
    build_havoc_code(loop_head, modifies, havoc_code);
    
    // unwind to get k+1 copies
    std::vector<goto_programt::targett> iteration_points;
    unwind(goto_function.body, loop_head, loop_exit, k+1, iteration_points);
    
    // we can remove everything up to the first assertion
    for(goto_programt::targett t=loop_head; t!=loop_exit; t++)
    {
      if(t->is_assert()) break;
      t->make_skip();
    }
    
    // now turn any assertions in iterations 0..k-1 into assumptions
    assert(iteration_points.size()==k+1);

    assert(k>=1);
    goto_programt::targett end=iteration_points[k-1];

    for(goto_programt::targett t=loop_head; t!=end; t++)
    {
      assert(t!=goto_function.body.instructions.end());
      if(t->is_assert()) t->type=ASSUME;
    }

    // assume the loop condition has become false
    goto_programt::instructiont assume(ASSUME);
    assume.guard=loop_guard;
    goto_function.body.insert_before_swap(loop_exit, assume);

    // Now havoc at the loop head. Use insert_swap to
    // preserve jumps to loop head.
    goto_function.body.insert_before_swap(loop_head, havoc_code);    
  }

  // remove skips
  remove_skip(goto_function.body);
}