void interval_domaint::assume_rec( const exprt &cond, bool negation) { if(cond.id()==ID_lt || cond.id()==ID_le || cond.id()==ID_gt || cond.id()==ID_ge || cond.id()==ID_equal || cond.id()==ID_notequal) { assert(cond.operands().size()==2); if(negation) // !x<y ---> x>=y { if(cond.id()==ID_lt) assume_rec(cond.op0(), ID_ge, cond.op1()); else if(cond.id()==ID_le) assume_rec(cond.op0(), ID_gt, cond.op1()); else if(cond.id()==ID_gt) assume_rec(cond.op0(), ID_le, cond.op1()); else if(cond.id()==ID_ge) assume_rec(cond.op0(), ID_lt, cond.op1()); else if(cond.id()==ID_equal) assume_rec(cond.op0(), ID_notequal, cond.op1()); else if(cond.id()==ID_notequal) assume_rec(cond.op0(), ID_equal, cond.op1()); } else assume_rec(cond.op0(), cond.id(), cond.op1()); } else if(cond.id()==ID_not) { assume_rec(to_not_expr(cond).op(), !negation); } else if(cond.id()==ID_and) { if(!negation) forall_operands(it, cond) assume_rec(*it, false); } else if(cond.id()==ID_or) { if(negation) forall_operands(it, cond) assume_rec(*it, true); } }
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); }