guardt &operator -= (guardt &g1, const guardt &g2) { if(g1.id()!=ID_and || g2.id()!=ID_and) return g1; sort_and_join(g1); guardt g2_sorted=g2; sort_and_join(g2_sorted); exprt::operandst &op1=g1.operands(); const exprt::operandst &op2=g2_sorted.operands(); exprt::operandst::iterator it1=op1.begin(); for(exprt::operandst::const_iterator it2=op2.begin(); it2!=op2.end(); ++it2) { while(it1!=op1.end() && *it1<*it2) ++it1; if(it1!=op1.end() && *it1==*it2) it1=op1.erase(it1); } g1=conjunction(op1); return g1; }
void equality_domaint::project_on_vars( valuet &value, const var_sett &vars, exprt &result) { #if 0 if(templ.size()==0) return domaint::project_on_vars(value, vars, result); #endif equ_valuet &v=static_cast<equ_valuet &>(value); exprt::operandst c; for(unsigned index=0; index<templ.size(); index++) { const var_pairt &vv=templ[index].var_pair; #if 0 std::cout << vv.second << std::endl; #endif if(vars.find(vv.first)==vars.end() || (vars.find(vv.second)==vars.end() && !(vv.second.id()==ID_constant && to_constant_expr(vv.second).get_value()=="NULL"))) continue; if(v.equs.same_set(vv.first, vv.second)) { if(templ[index].kind==LOOP) c.push_back( implies_exprt( templ[index].pre_guard, equal_exprt(vv.first, vv.second))); else c.push_back(equal_exprt(vv.first, vv.second)); } } for(index_sett::const_iterator it=v.disequs.begin(); it!=v.disequs.end(); it++) { const var_pairt &vv=templ[*it].var_pair; if(vars.find(vv.first)==vars.end() || (vars.find(vv.second)==vars.end() && !(vv.second.id()==ID_constant && to_constant_expr(vv.second).get_value()=="NULL"))) continue; if(templ[*it].kind==LOOP) c.push_back( implies_exprt( templ[*it].pre_guard, notequal_exprt(vv.first, vv.second))); else c.push_back(notequal_exprt(vv.first, vv.second)); } result=conjunction(c); }
int cmd(string str) { string opt, who, channel; object ob; if(!str) return 0; if(!archp(previous_object())) return 0; // Attempt to remove or add a players line rights. if(sscanf(str, "%s %s %s", opt, who, channel) == 3) { if(!(ob = find_player(lower_case(who)))) return notify_fail("No such player online.\n"); if(opt == "remove") { if(member_array(channel, ob->GetChannels()) == -1) { this_player()->eventPrint(ob->GetName() + " is not currently subscribed to the " + channel + " line."); return 1; } ob->RestrictChannel(channel); this_player()->eventPrint("%^RED%^You restrict " + ob->GetName() + " from the " + channel + " line.%^RESET%^"); ob->eventPrint("%^RED%^You have lost your " + channel + " line rights.%^RESET%^"); return 1; } else if(opt == "add") { if(member_array(channel, ob->GetRestrictedChannels()) == -1) { message("system", ob->GetName() + " is not currently restricted from the " + channel + " line.", this_player()); return 1; } ob->UnrestrictChannel(channel); this_player()->eventPrint("%^RED%^You unrestrict " + ob->GetName() + " from the " + channel + " line.%^RESET%^"); ob->eventPrint("%^RED%^You have regained your " + channel + " line rights.%^RESET%^"); return 1; } } // Otherwise, return restriction information, if it is requested. else if(str) { string *channels; string tmp; int size; if(!(ob = find_player(lower_case(str)))) return notify_fail("No such player online.\n"); channels = ob->GetRestrictedChannels(); size = sizeof(channels); tmp = ob->GetName() + " is currently restricted from "; if(size) tmp += "the " + conjunction(channels); else tmp += "no"; if(size == 1) tmp += " line."; else tmp += " lines."; this_player()->eventPrint(tmp); return 1; } else return 0; }
exprt predabs_domaint::to_pre_constraints(const templ_valuet &value) { assert(value.size()==templ.size()); exprt::operandst c; for(std::size_t row=0; row<templ.size(); ++row) { c.push_back(get_row_pre_constraint(row, value[row])); } return conjunction(c); }
void summarizer_fw_termt::inline_summaries( const function_namet &function_name, local_SSAt &SSA, exprt precondition, bool context_sensitive, threevalt &calls_terminate, bool &has_function_calls) { for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { for(local_SSAt::nodet::function_callst::iterator f_it= n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) { assert(f_it->function().id()==ID_symbol); // no function pointers exprt::operandst c; c.push_back(precondition); get_assertions(SSA, c); // assertions as assumptions precondition=conjunction(c); if(!options.get_bool_option("competition-mode") && !check_call_reachable( function_name, SSA, n_it, f_it, precondition, true)) continue; has_function_calls=true; irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); if(!check_precondition( function_name, SSA, n_it, f_it, precondition, context_sensitive)) { exprt precondition_call=true_exprt(); if(context_sensitive) precondition_call=compute_calling_context( function_name, SSA, n_it, f_it, precondition, true); status() << "Recursively summarizing function " << fname << eom; compute_summary_rec(fname, precondition_call, context_sensitive); summaries_used++; } // get information about callee termination if(summary_db.exists(fname) && summary_db.get(fname).terminates!=YES) { // cannot propagate NO // because call reachability might be over-approximating calls_terminate=UNKNOWN; break; } } } }
void summarizer_fw_termt::do_termination( const function_namet &function_name, local_SSAt &SSA, summaryt &summary) { // calling context, invariant, function call summaries exprt::operandst cond; if(!summary.fw_invariant.is_nil()) cond.push_back(summary.fw_invariant); if(!summary.fw_precondition.is_nil()) cond.push_back(summary.fw_precondition); cond.push_back(ssa_inliner.get_summaries(SSA)); status() << "Synthesizing ranking function to prove termination" << eom; // solver incremental_solvert &solver=ssa_db.get_solver(function_name); solver.set_message_handler(get_message_handler()); 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); if(template_generator1.all_vars().empty()) return; // nothing to do get_assertions(SSA, cond); // add assertions as assumptions // compute ranking functions ssa_analyzert analyzer1; analyzer1.set_message_handler(get_message_handler()); analyzer1(solver, SSA, conjunction(cond), template_generator1); analyzer1.get_result( summary.termination_argument, template_generator1.all_vars()); // extract information whether a ranking function was found for all loops summary.terminates=check_termination_argument(summary.termination_argument); if(!summary.fw_precondition.is_true()) summary.termination_argument= implies_exprt(summary.fw_precondition, summary.termination_argument); // statistics solver_instances+=analyzer1.get_number_of_solver_instances(); solver_calls+=analyzer1.get_number_of_solver_calls(); termargs_computed++; }
void predabs_domaint::project_on_vars( valuet &value, const var_sett &vars, exprt &result) { const templ_valuet &v=static_cast<const templ_valuet &>(value); assert(v.size()==templ.size()); exprt::operandst c; for(std::size_t row=0; row<templ.size(); row++) { const template_rowt &templ_row=templ[row]; std::set<symbol_exprt> symbols; find_symbols(templ_row.expr, symbols); bool pure=true; for(const auto &symbol : symbols) { if(vars.find(symbol)==vars.end()) { pure=false; break; } } if(!pure) continue; const row_valuet &row_v=v[row]; if(templ_row.kind==LOOP) { c.push_back( implies_exprt( templ_row.pre_guard, implies_exprt(row_v, templ_row.expr))); } else { c.push_back(implies_exprt(row_v, templ_row.expr)); } } result=conjunction(c); }
static Node mkAnd(const std::vector<TNode>& conjunctions) { Assert(conjunctions.size() > 0); std::set<TNode> all; all.insert(conjunctions.begin(), conjunctions.end()); if (all.size() == 1) { // All the same, or just one return conjunctions[0]; } NodeBuilder<> conjunction(kind::AND); std::set<TNode>::const_iterator it = all.begin(); std::set<TNode>::const_iterator it_end = all.end(); while (it != it_end) { conjunction << *it; ++ it; } return conjunction; }
void summarizer_bw_termt::do_nontermination( const function_namet &function_name, local_SSAt &SSA, const summaryt &old_summary, summaryt &summary) { // calling context, invariant, function call summaries exprt::operandst cond; cond.push_back(old_summary.fw_invariant); cond.push_back(old_summary.fw_precondition); cond.push_back(ssa_inliner.get_summaries(SSA)); ssa_inliner.get_summaries(SSA, false, cond, cond); // backward summaries if(!check_end_reachable(function_name, SSA, conjunction(cond))) { status() << "Function never terminates" << eom; summary.bw_transformer=false_exprt(); summary.bw_precondition=false_exprt(); summary.terminates=NO; } }
bool strategy_solver_binsearch3t::iterate(invariantt &_inv) { tpolyhedra_domaint::templ_valuet &inv= static_cast<tpolyhedra_domaint::templ_valuet &>(_inv); bool improved=false; solver.new_context(); // for improvement check exprt inv_expr=tpolyhedra_domain.to_pre_constraints(inv); #if 0 debug() << "improvement check: " << eom; debug() << "pre-inv: " << from_expr(ns, "", inv_expr) << eom; #endif solver << inv_expr; exprt::operandst strategy_cond_exprs; tpolyhedra_domain.make_not_post_constraints( inv, strategy_cond_exprs, strategy_value_exprs); strategy_cond_literals.resize(strategy_cond_exprs.size()); #if 0 debug() << "post-inv: "; #endif for(std::size_t i=0; i<strategy_cond_exprs.size(); i++) { #if 0 debug() << (i>0 ? " || " : "") << from_expr(ns, "", strategy_cond_exprs[i]); #endif strategy_cond_literals[i]=solver.convert(strategy_cond_exprs[i]); strategy_cond_exprs[i]=literal_exprt(strategy_cond_literals[i]); } debug() << eom; solver << disjunction(strategy_cond_exprs); #if 0 debug() << "solve(): "; #endif std::set<tpolyhedra_domaint::rowt> improve_rows; std::map<tpolyhedra_domaint::rowt, symbol_exprt> symb_values; std::map<tpolyhedra_domaint::rowt, constant_exprt> lower_values; exprt::operandst blocking_constraint; bool improved_from_neginf=false; while(solver()==decision_proceduret::D_SATISFIABLE) // improvement check { #if 0 debug() << "SAT" << eom; #endif improved=true; std::size_t row=0; for(; row<strategy_cond_literals.size(); row++) { if(solver.l_get(strategy_cond_literals[row]).is_true()) { #if 1 debug() << "improve row " << row << eom; #endif improve_rows.insert(row); symb_values[row]=tpolyhedra_domain.get_row_symb_value(row); lower_values[row]= simplify_const(solver.get(strategy_value_exprs[row])); blocking_constraint.push_back( literal_exprt(!strategy_cond_literals[row])); if(tpolyhedra_domain.is_row_value_neginf( tpolyhedra_domain.get_row_value(row, inv))) improved_from_neginf=true; } } solver << conjunction(blocking_constraint); } solver.pop_context(); // improvement check if(!improved) // done { #if 0 debug() << "UNSAT" << eom; #endif return improved; } // symbolic value system exprt pre_inv_expr= tpolyhedra_domain.to_symb_pre_constraints(inv, improve_rows); exprt post_inv_expr= tpolyhedra_domain.to_symb_post_constraints(improve_rows); assert(lower_values.size()>=1); std::map<tpolyhedra_domaint::rowt, symbol_exprt>::iterator it=symb_values.begin(); exprt _lower=lower_values[it->first]; #if 1 debug() << "update row " << it->first << ": " << from_expr(ns, "", lower_values[it->first]) << eom; #endif tpolyhedra_domain.set_row_value(it->first, lower_values[it->first], inv); exprt _upper= tpolyhedra_domain.get_max_row_value(it->first); exprt sum=it->second; for(++it; it!=symb_values.end(); ++it) { sum=plus_exprt(sum, it->second); _upper=plus_exprt(_upper, tpolyhedra_domain.get_max_row_value(it->first)); _lower=plus_exprt(_lower, lower_values[it->first]); #if 1 debug() << "update row " << it->first << ": " << from_expr(ns, "", lower_values[it->first]) << eom; #endif tpolyhedra_domain.set_row_value(it->first, lower_values[it->first], inv); } // do not solve system if we have just reached a new loop // (the system will be very large!) if(improved_from_neginf) return improved; solver.new_context(); // symbolic value system solver << pre_inv_expr; solver << post_inv_expr; #if 1 debug() << "symbolic value system: " << eom; debug() << "pre-inv: " << from_expr(ns, "", pre_inv_expr) << eom; debug() << "post-inv: " << from_expr(ns, "", post_inv_expr) << eom; #endif extend_expr_types(sum); extend_expr_types(_upper); extend_expr_types(_lower); tpolyhedra_domaint::row_valuet upper=simplify_const(_upper); tpolyhedra_domaint::row_valuet lower=simplify_const(_lower); assert(sum.type()==upper.type()); assert(sum.type()==lower.type()); symbol_exprt sum_bound( SUM_BOUND_VAR+i2string(sum_bound_counter++), sum.type()); solver << equal_exprt(sum_bound, sum); #if 1 debug() << from_expr(ns, "", equal_exprt(sum_bound, sum)) << eom; #endif while(tpolyhedra_domain.less_than(lower, upper)) { tpolyhedra_domaint::row_valuet middle= tpolyhedra_domain.between(lower, upper); if(!tpolyhedra_domain.less_than(lower, middle)) middle=upper; // row_symb_value >= middle assert(sum_bound.type()==middle.type()); exprt c=binary_relation_exprt(sum_bound, ID_ge, middle); #if 1 debug() << "upper: " << from_expr(ns, "", upper) << eom; debug() << "middle: " << from_expr(ns, "", middle) << eom; debug() << "lower: " << from_expr(ns, "", lower) << eom; #endif solver.new_context(); // binary search iteration #if 1 debug() << "constraint: " << from_expr(ns, "", c) << eom; #endif solver << c; if(solver()==decision_proceduret::D_SATISFIABLE) { #if 0 debug() << "SAT" << eom; #endif lower=middle; for(const auto &sv : symb_values) { #if 1 debug() << "update row " << sv.first << " " << from_expr(ns, "", sv.second) << ": "; #endif constant_exprt lower_row= simplify_const(solver.get(sv.second)); #if 1 debug() << from_expr(ns, "", lower_row) << eom; #endif tpolyhedra_domain.set_row_value(sv.first, lower_row, inv); } } else { #if 0 debug() << "UNSAT" << eom; #endif if(!tpolyhedra_domain.less_than(middle, upper)) middle=lower; upper=middle; } solver.pop_context(); // binary search iteration } solver.pop_context(); // symbolic value system return improved; }
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; }
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); } }
guardt &operator |= (guardt &g1, const guardt &g2) { if(g2.is_false() || g1.is_true()) return g1; if(g1.is_false() || g2.is_true()) { g1=g2; return g1; } if(g1.id()!=ID_and || g2.id()!=ID_and) { exprt tmp(g2); tmp.make_not(); if(tmp==g1) g1.make_true(); else g1=or_exprt(g1, g2); // TODO: make simplify more capable and apply here return g1; } // find common prefix sort_and_join(g1); guardt g2_sorted=g2; sort_and_join(g2_sorted); exprt::operandst &op1=g1.operands(); const exprt::operandst &op2=g2_sorted.operands(); exprt::operandst n_op1, n_op2; n_op1.reserve(op1.size()); n_op2.reserve(op2.size()); exprt::operandst::iterator it1=op1.begin(); for(exprt::operandst::const_iterator it2=op2.begin(); it2!=op2.end(); ++it2) { while(it1!=op1.end() && *it1<*it2) { n_op1.push_back(*it1); it1=op1.erase(it1); } if(it1!=op1.end() && *it1==*it2) ++it1; else n_op2.push_back(*it2); } while(it1!=op1.end()) { n_op1.push_back(*it1); it1=op1.erase(it1); } if(n_op2.empty()) return g1; // end of common prefix exprt and_expr1=conjunction(n_op1); exprt and_expr2=conjunction(n_op2); g1=conjunction(op1); exprt tmp(and_expr2); tmp.make_not(); if(tmp!=and_expr1) { if(and_expr1.is_true() || and_expr2.is_true()) { } else // TODO: make simplify more capable and apply here g1.add(or_exprt(and_expr1, and_expr2)); } return g1; }
void summarizer_fwt::do_summary(const function_namet &function_name, local_SSAt &SSA, summaryt &summary, exprt cond, bool context_sensitive) { status() << "Computing summary" << 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_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,true); exprt::operandst conds; conds.reserve(5); conds.push_back(cond); conds.push_back(summary.fw_precondition); conds.push_back(ssa_inliner.get_summaries(SSA)); #ifdef REUSE_INVARIANTS if(summary_db.exists(function_name)) //reuse existing invariants { const exprt &old_inv = summary_db.get(function_name).fw_invariant; exprt inv = ssa_unwinder.get(function_name).rename_invariant(old_inv); conds.push_back(inv); #if 0 std::ostringstream out; out << "(original inv)" << from_expr(SSA.ns,"",old_inv) << "\n"; debug() << out.str() << eom; out << "(renamed inv)" << from_expr(SSA.ns,"",inv)<<"\n"; debug() << out.str() << eom; #endif } #endif cond = conjunction(conds); bool assertions_check = false; //options.get_bool_option("k-induction"); bool assertions_hold = analyzer(solver,SSA,cond,template_generator, assertions_check); if(assertions_hold) { analyzer.get_result(summary.fw_transformer,template_generator.inout_vars()); analyzer.get_result(summary.fw_invariant,template_generator.loop_vars()); #ifdef SHOW_WHOLE_RESULT // to see all the custom template values exprt whole_result; analyzer.get_result(whole_result,template_generator.all_vars()); debug() << "whole result: " << from_expr(SSA.ns,"",whole_result) << eom; #endif if(context_sensitive && !summary.fw_precondition.is_true()) { summary.fw_transformer = implies_exprt(summary.fw_precondition,summary.fw_transformer); summary.fw_invariant = implies_exprt(summary.fw_precondition,summary.fw_invariant); } } else //!assertions_hold { nonpassed_assertions = true; summary.nonpassed_assertions = analyzer.get_nonpassed_assertions(); } solver_instances += analyzer.get_number_of_solver_instances(); solver_calls += analyzer.get_number_of_solver_calls(); }
property_checkert::resultt summary_checker_acdlt::operator()( const goto_modelt &goto_model) { const namespacet ns(goto_model.symbol_table); SSA_functions(goto_model, ns); ssa_unwinder.init(false, false); unsigned unwind=options.get_unsigned_int_option("unwind"); if(unwind>0) { status() << "Unwinding" << messaget::eom; ssa_unwinder.init_localunwinders(); ssa_unwinder.unwind_all(unwind); } irep_idt entry_point=goto_model.goto_functions.entry_point(); std::cout << entry_point << std::endl; local_SSAt &SSA=ssa_db.get(entry_point); ssa_local_unwindert &ssa_local_unwinder=ssa_unwinder.get(entry_point); const goto_programt &goto_program=SSA.goto_function.body; for(goto_programt::instructionst::const_iterator i_it=goto_program.instructions.begin(); i_it!=goto_program.instructions.end(); i_it++) { /*if(!i_it->is_assert() || !i_it->is_assume()) continue; */ const source_locationt &location=i_it->source_location; irep_idt property_id=location.get_property_id(); if(i_it->guard.is_true()) { property_map[property_id].result=PASS; continue; } if(property_id=="") // TODO: some properties do not show up in initialize_property_map continue; // get loophead selects exprt::operandst loophead_selects; for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { if(n_it->loophead==SSA.nodes.end()) continue; symbol_exprt lsguard= SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location); ssa_unwinder.get(entry_point).unwinder_rename(lsguard, *n_it, true); loophead_selects.push_back(not_exprt(lsguard)); } // iterate over assumptions exprt::operandst assumptions; for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { for(local_SSAt::nodet::assumptionst::const_iterator a_it=n_it->assumptions.begin(); a_it!=n_it->assumptions.end(); a_it++) { std::cout << "Assumption:: " << from_expr(*a_it) << std::endl; assumptions.push_back(*a_it); } } // iterate over assertions std::list<local_SSAt::nodest::const_iterator> assertion_nodes; SSA.find_nodes(i_it, assertion_nodes); std::cout << "The number of assertions are: " << assertion_nodes.size() << std::endl; exprt::operandst assertions; for(std::list<local_SSAt::nodest::const_iterator>::const_iterator n_it=assertion_nodes.begin(); n_it!=assertion_nodes.end(); n_it++) { for(local_SSAt::nodet::assertionst::const_iterator a_it=(*n_it)->assertions.begin(); a_it!=(*n_it)->assertions.end(); a_it++) { assertions.push_back(*a_it); } } // if(simplify) property=simplify_expr(property, SSA.ns); property_map[property_id].location=i_it; // TODO: make the solver incremental // configure components of acdl solver // domain acdl_domaint domain(options, SSA, ssa_db, ssa_local_unwinder); domain.set_message_handler(get_message_handler()); // worklist heuristics std::unique_ptr<acdl_worklist_baset> worklist; if(options.get_option("propagate")=="forward") worklist=std::unique_ptr<acdl_worklist_baset>( new acdl_worklist_forwardt()); if(options.get_option("propagate")=="backward") worklist=std::unique_ptr<acdl_worklist_baset>( new acdl_worklist_backwardt()); else if(options.get_option("propagate")=="chaotic") worklist=std::unique_ptr<acdl_worklist_baset>( new acdl_worklist_orderedt()); // conflict analysis heuristics std::unique_ptr<acdl_analyze_conflict_baset> conflict_analysis; if(options.get_option("learning")=="first-uip") // TODO: no 'new' with base class! conflict_analysis=std::unique_ptr<acdl_analyze_conflict_baset>( new acdl_analyze_conflict_baset(domain)); // decision heuristics std::unique_ptr<acdl_decision_heuristics_baset> decision_heuristics; if(options.get_option("decision")=="random") decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>( new acdl_decision_heuristics_randt(domain)); else if(options.get_option("decision")=="ordered") decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>( new acdl_decision_heuristics_orderedt(domain)); else if(options.get_option("decision")=="octagon") decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>( new acdl_decision_heuristics_octagont(domain)); else if(options.get_option("decision")=="berkmin") decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>( new acdl_decision_heuristics_berkmint(domain, *conflict_analysis)); else if(options.get_option("decision")=="range") decision_heuristics=std::unique_ptr<acdl_decision_heuristics_baset>( new acdl_decision_heuristics_ranget(domain)); // now instantiate solver acdl_solvert acdl_solver( options, domain, *decision_heuristics, *worklist, *conflict_analysis); acdl_solver.set_message_handler(get_message_handler()); property_map[property_id].result= acdl_solver( ssa_db.get(goto_model.goto_functions.entry_point()), conjunction(assertions), conjunction(loophead_selects), conjunction(assumptions)); } summary_checker_baset::resultt result=property_checkert::PASS; for(property_mapt::const_iterator p_it=property_map.begin(); p_it!=property_map.end(); p_it++) { if(p_it->second.result==FAIL) return property_checkert::FAIL; if(p_it->second.result==UNKNOWN) result=property_checkert::UNKNOWN; } return result; }
exprt summarizer_bw_termt::compute_precondition( local_SSAt &SSA, summaryt &summary, const exprt::operandst &postconditions, incremental_solvert &solver, template_generator_summaryt &template_generator, bool context_sensitive) { exprt postcond=not_exprt(conjunction(postconditions)); // compute backward summary exprt bw_transformer, bw_invariant, bw_precondition; if(!template_generator.out_vars().empty()) { ssa_analyzert analyzer; analyzer.set_message_handler(get_message_handler()); analyzer(solver, SSA, postcond, template_generator); analyzer.get_result(bw_transformer, template_generator.inout_vars()); analyzer.get_result(bw_invariant, template_generator.loop_vars()); analyzer.get_result(bw_precondition, template_generator.out_vars()); // statistics solver_instances+=analyzer.get_number_of_solver_instances(); solver_calls+=analyzer.get_number_of_solver_calls(); } #if 1 // TODO: yet another workaround for ssa_analyzer // not being able to handle empty templates properly else { solver << SSA; solver.new_context(); solver << SSA.get_enabling_exprs(); solver << postcond; exprt result=true_exprt(); if(solver()==decision_proceduret::D_UNSATISFIABLE) result=false_exprt(); solver.pop_context(); bw_transformer=result; bw_invariant=result; bw_precondition=result; } #endif bw_transformer=not_exprt(bw_transformer); bw_invariant=not_exprt(bw_invariant); bw_precondition=not_exprt(bw_precondition); if(context_sensitive && !summary.bw_postcondition.is_true()) { bw_transformer=implies_exprt(summary.bw_postcondition, bw_transformer); bw_invariant=implies_exprt(summary.bw_postcondition, bw_invariant); bw_precondition=implies_exprt(summary.bw_postcondition, bw_precondition); } // join // TODO: should go into summaryt if(summary.bw_transformer.is_nil()) { summary.bw_transformer=bw_transformer; summary.bw_invariant=bw_invariant; summary.bw_precondition=bw_precondition; } else { summary.bw_transformer=or_exprt(summary.bw_transformer, bw_transformer); summary.bw_invariant=or_exprt(summary.bw_invariant, bw_invariant); summary.bw_precondition=or_exprt(summary.bw_precondition, bw_precondition); } return bw_precondition; }
bool summarizer_bw_termt::bootstrap_preconditions( local_SSAt &SSA, summaryt &summary, incremental_solvert &solver, template_generator_rankingt &template_generator1, template_generator_summaryt &template_generator2, exprt &termination_argument) { // bootstrap with a concrete model for input variables const domaint::var_sett &invars=template_generator2.out_vars(); solver.new_context(); unsigned number_bootstraps=0; termination_argument=true_exprt(); exprt::operandst checked_candidates; while(number_bootstraps++<MAX_BOOTSTRAP_ATTEMPTS) { // find new ones solver << not_exprt(summary.bw_precondition); // last node should be reachable solver << SSA.guard_symbol(--SSA.goto_function.body.instructions.end()); // statistics solver_calls++; // solve exprt precondition; if(solver()==decision_proceduret::D_SATISFIABLE) { exprt::operandst c; for(domaint::var_sett::const_iterator it=invars.begin(); it!=invars.end(); it++) { c.push_back(equal_exprt(*it, solver.solver->get(*it))); } precondition=conjunction(c); debug() << "bootstrap model for precondition: " << from_expr(SSA.ns, "", precondition) << eom; solver.pop_context(); } else // whole precondition space covered { solver.pop_context(); break; } termination_argument= compute_termination_argument( SSA, precondition, solver, template_generator1); if(summarizer_fw_termt::check_termination_argument( termination_argument)==YES) { return true; } solver.new_context(); checked_candidates.push_back(precondition); solver << not_exprt(disjunction(checked_candidates)); // next one, please! } return false; }
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(); }
exprt interval_domaint::make_expression(const symbol_exprt &src) const { if(is_int(src.type())) { int_mapt::const_iterator i_it=int_map.find(src.get_identifier()); if(i_it==int_map.end()) return true_exprt(); const integer_intervalt &interval=i_it->second; if(interval.is_top()) return true_exprt(); if(interval.is_bottom()) return false_exprt(); exprt::operandst conjuncts; if(interval.upper_set) { exprt tmp=from_integer(interval.upper, src.type()); conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp)); } if(interval.lower_set) { exprt tmp=from_integer(interval.lower, src.type()); conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src)); } return conjunction(conjuncts); } else if(is_float(src.type())) { float_mapt::const_iterator i_it=float_map.find(src.get_identifier()); if(i_it==float_map.end()) return true_exprt(); const ieee_float_intervalt &interval=i_it->second; if(interval.is_top()) return true_exprt(); if(interval.is_bottom()) return false_exprt(); exprt::operandst conjuncts; if(interval.upper_set) { exprt tmp=interval.upper.to_expr(); conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp)); } if(interval.lower_set) { exprt tmp=interval.lower.to_expr(); conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src)); } return conjunction(conjuncts); } else return true_exprt(); }
void cover_goals_extt::assignment() { // check loop head choices in model bool invariants_involved=false; if(spurious_check) { for(exprt::operandst::const_iterator l_it=loophead_selects.begin(); l_it!=loophead_selects.end(); l_it++) { if(solver.get(l_it->op0()).is_true()) { invariants_involved=true; break; } } } if(!invariants_involved || !spurious_check) { std::list<cover_goals_extt::cover_goalt>::const_iterator g_it=goals.begin(); for(goal_mapt::const_iterator it=goal_map.begin(); it!=goal_map.end(); it++, g_it++) { if(property_map[it->first].result==property_checkert::UNKNOWN && solver.l_get(g_it->condition).is_true()) { property_map[it->first].result=property_checkert::FAIL; if(build_error_trace) { ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver()); build_goto_trace(property_map[it->first].error_trace); if(!all_properties) break; } } } return; } solver.new_context(); // force avoiding paths going through invariants solver << conjunction(loophead_selects); switch(solver()) { case decision_proceduret::D_SATISFIABLE: { std::list<cover_goals_extt::cover_goalt>::const_iterator g_it=goals.begin(); for(goal_mapt::const_iterator it=goal_map.begin(); it!=goal_map.end(); it++, g_it++) { if(property_map[it->first].result==property_checkert::UNKNOWN && solver.l_get(g_it->condition).is_true()) { property_map[it->first].result=property_checkert::FAIL; if(build_error_trace) { ssa_build_goto_tracet build_goto_trace(SSA, solver.get_solver()); build_goto_trace(property_map[it->first].error_trace); #if 0 show_raw_countermodel( it->first, SSA, *solver.solver, debug(), get_message_handler()); #endif if(!all_properties) break; } } } break; } case decision_proceduret::D_UNSATISFIABLE: break; case decision_proceduret::D_ERROR: default: throw "error from decision procedure"; } solver.pop_context(); _iterations++; // statistics }