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); } } }
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; }
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); }
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); } } }
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); }
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); }