/// add axioms stating that if two strings are equal then their hash codes are /// equals /// \par parameters: function application with a string argument /// \return a integer expression corresponding to the hash code of the string exprt string_constraint_generatort::add_axioms_for_hash_code( const function_application_exprt &f) { string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); typet return_type=f.type(); typet index_type=str.length().type(); // initialisation of the missing pool variable std::map<irep_idt, string_exprt>::iterator it; for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) if(hash.find(it->second)==hash.end()) hash[it->second]=fresh_symbol("hash", return_type); // for each string s. either: // c1: hash(str)=hash(s) // c2: |str|!=|s| // c3: (|str|==|s| &&exists i<|s|. s[i]!=str[i]) // WARNING: the specification may be incomplete for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) { symbol_exprt i=fresh_exist_index("index_hash", index_type); equal_exprt c1(hash[it->second], hash[str]); not_exprt c2(equal_exprt(it->second.length(), str.length())); and_exprt c3( equal_exprt(it->second.length(), str.length()), and_exprt( not_exprt(equal_exprt(str[i], it->second[i])), and_exprt( str.axiom_for_is_strictly_longer_than(i), axiom_for_is_positive_index(i)))); axioms.push_back(or_exprt(c1, or_exprt(c2, c3))); } return hash[str]; }
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); }
exprt string_constraint_generatort::add_axioms_for_last_index_of( const string_exprt &str, const exprt &c, const exprt &from_index) { const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &index_type=ref_type.get_index_type(); symbol_exprt index=fresh_exist_index("last_index_of", index_type); symbol_exprt contains=fresh_boolean("contains_in_last_index_of"); // We add axioms: // a1 : -1 <= i <= from_index // a2 : (i=-1 <=> !contains) // a3 : (contains => i <= from_index &&s[i]=c) // a4 : forall n. i+1 <= n < from_index +1 &&contains => s[n]!=c // a5 : forall m. 0 <= m < from_index +1 &&!contains => s[m]!=c exprt index1=from_integer(1, index_type); exprt minus1=from_integer(-1, index_type); exprt from_index_plus_one=plus_exprt(from_index, index1); and_exprt a1( binary_relation_exprt(index, ID_ge, minus1), binary_relation_exprt(index, ID_lt, from_index_plus_one)); axioms.push_back(a1); equal_exprt a2(not_exprt(contains), equal_exprt(index, minus1)); axioms.push_back(a2); implies_exprt a3( contains, and_exprt( binary_relation_exprt(from_index, ID_ge, index), equal_exprt(str[index], c))); axioms.push_back(a3); symbol_exprt n=fresh_univ_index("QA_last_index_of", index_type); string_constraintt a4( n, plus_exprt(index, index1), from_index_plus_one, contains, not_exprt(equal_exprt(str[n], c))); axioms.push_back(a4); symbol_exprt m=fresh_univ_index("QA_last_index_of", index_type); string_constraintt a5( m, from_index_plus_one, not_exprt(contains), not_exprt(equal_exprt(str[m], c))); axioms.push_back(a5); return index; }
void equality_domaint::make_not_post_constraints( valuet &_value, exprt::operandst &cond_exprs) { assert(*e_it<templ.size()); cond_exprs.resize(1); if(check_dis) { cond_exprs[0]=get_post_not_disequ_constraint(*e_it); return; } const template_rowt &templ_row=templ[*e_it]; if(templ_row.kind==IN) { cond_exprs[0]=true_exprt(); return; } const var_pairt &vv=templ_row.var_pair; exprt c= and_exprt( templ_row.aux_expr, not_exprt( implies_exprt( templ_row.post_guard, equal_exprt(vv.first, vv.second)))); rename(c); cond_exprs[0]=c; }
exprt ssa_alias_guard( const exprt &e1, const exprt &e2, const namespacet &ns) { exprt a1=address_canonizer(address_of_exprt(e1), ns); exprt a2=address_canonizer(address_of_exprt(e2), ns); // in some cases, we can use plain address equality, // as we assume well-aligned-ness mp_integer size1=pointer_offset_size(e1.type(), ns); mp_integer size2=pointer_offset_size(e2.type(), ns); if(size1>=size2) { exprt lhs=a1; exprt rhs=a2; if(ns.follow(rhs.type())!=ns.follow(lhs.type())) rhs=typecast_exprt(rhs, lhs.type()); return equal_exprt(lhs, rhs); } return same_object(a1, a2); }
void symex_target_equationt::assignment( const exprt &guard, const ssa_exprt &ssa_lhs, const exprt &ssa_full_lhs, const exprt &original_full_lhs, const exprt &ssa_rhs, const sourcet &source, assignment_typet assignment_type) { assert(ssa_lhs.is_not_nil()); SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard=guard; SSA_step.ssa_lhs=ssa_lhs; SSA_step.ssa_full_lhs=ssa_full_lhs; SSA_step.original_full_lhs=original_full_lhs; SSA_step.ssa_rhs=ssa_rhs; SSA_step.assignment_type=assignment_type; SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_rhs); SSA_step.type=goto_trace_stept::ASSIGNMENT; SSA_step.hidden=(assignment_type!=STATE && assignment_type!=VISIBLE_ACTUAL_PARAMETER); SSA_step.source=source; merge_ireps(SSA_step); }
void symex_target_equationt::decl( const exprt &guard, const ssa_exprt &ssa_lhs, const sourcet &source, assignment_typet assignment_type) { assert(ssa_lhs.is_not_nil()); SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard=guard; SSA_step.ssa_lhs=ssa_lhs; SSA_step.ssa_full_lhs=ssa_lhs; SSA_step.original_full_lhs=ssa_lhs.get_original_expr(); SSA_step.type=goto_trace_stept::DECL; SSA_step.source=source; SSA_step.hidden=(assignment_type!=STATE); // the condition is trivially true, and only // there so we see the symbols SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_lhs); merge_ireps(SSA_step); }
exprt functionst::arguments_equal(const exprt::operandst &o1, const exprt::operandst &o2) { assert(o1.size()==o2.size()); if(o1.empty()) return true_exprt(); and_exprt and_expr; and_exprt::operandst &conjuncts=and_expr.operands(); conjuncts.resize(o1.size()); for(std::size_t i=0; i<o1.size(); i++) { exprt lhs=o1[i]; exprt rhs=o2[i]; if(lhs.type()!=rhs.type()) rhs.make_typecast(lhs.type()); conjuncts[i]=equal_exprt(lhs, rhs); } return and_expr; }
void functionst::add_function_constraints(const function_infot &info) { // Do Ackermann's function reduction. // This is quadratic, slow, and needs to be modernized. for(std::set<function_application_exprt>::const_iterator it1=info.applications.begin(); it1!=info.applications.end(); it1++) { for(std::set<function_application_exprt>::const_iterator it2=info.applications.begin(); it2!=it1; it2++) { exprt arguments_equal_expr= arguments_equal(it1->arguments(), it2->arguments()); implies_exprt implication(arguments_equal_expr, equal_exprt(*it1, *it2)); prop_conv.set_to_true(implication); } } }
void symex_target_equationt::convert_io( decision_proceduret &dec_proc) { unsigned io_count=0; for(SSA_stepst::iterator it=SSA_steps.begin(); it!=SSA_steps.end(); it++) if(!it->ignore) { for(std::list<exprt>::const_iterator o_it=it->io_args.begin(); o_it!=it->io_args.end(); o_it++) { exprt tmp=*o_it; if(tmp.is_constant() || tmp.id()==ID_string_constant) it->converted_io_args.push_back(tmp); else { symbol_exprt symbol; symbol.type()=tmp.type(); symbol.set_identifier("symex::io::"+i2string(io_count++)); dec_proc.set_to(equal_exprt(tmp, symbol), true); it->converted_io_args.push_back(symbol); } } } }
void symex_target_equationt::assignment( const guardt &guard, const symbol_exprt &ssa_lhs, const symbol_exprt &original_lhs_object, const exprt &ssa_full_lhs, const exprt &original_full_lhs, const exprt &ssa_rhs, const sourcet &source, assignment_typet assignment_type) { assert(ssa_lhs.is_not_nil()); SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.ssa_lhs=ssa_lhs; SSA_step.original_lhs_object=original_lhs_object; SSA_step.ssa_full_lhs=ssa_full_lhs; SSA_step.original_full_lhs=original_full_lhs; SSA_step.ssa_rhs=ssa_rhs; SSA_step.assignment_type=assignment_type; SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_rhs); SSA_step.type=goto_trace_stept::ASSIGNMENT; SSA_step.source=source; }
exprt ssa_alias_guard( const exprt &e1, const exprt &e2, const namespacet &ns) { exprt a1=address_canonizer(address_of_exprt(e1), ns); // TODO: We should compare 'base' pointers here because // we have a higher chance that there was no pointer arithmetic // on the base pointer than that the result of the pointer // arithmetic points to a base pointer. // The following hack does that: if(a1.id()==ID_plus) a1=a1.op0(); exprt a2=address_canonizer(address_of_exprt(e2), ns); // in some cases, we can use plain address equality, // as we assume well-aligned-ness mp_integer size1=pointer_offset_size(e1.type(), ns); mp_integer size2=pointer_offset_size(e2.type(), ns); if(size1>=size2) { exprt lhs=a1; exprt rhs=a2; if(ns.follow(rhs.type())!=ns.follow(lhs.type())) rhs=typecast_exprt(rhs, lhs.type()); return equal_exprt(lhs, rhs); } return same_object(a1, a2); }
void boolbvt::convert_with_bv( const typet &type, const exprt &op1, const exprt &op2, const bvt &prev_bv, bvt &next_bv) { literalt l=convert(op2); mp_integer op1_value; if(!to_integer(op1, op1_value)) { next_bv=prev_bv; if(op1_value<next_bv.size()) next_bv[integer2size_t(op1_value)]=l; return; } typet counter_type=op1.type(); for(std::size_t i=0; i<prev_bv.size(); i++) { exprt counter=from_integer(i, counter_type); literalt eq_lit=convert(equal_exprt(op1, counter)); next_bv[i]=prop.lselect(eq_lit, l, prev_bv[i]); } }
exprt string_constraint_generatort::add_axioms_for_last_index_of_string( const string_exprt &str, const string_exprt &substring, const exprt &from_index) { const typet &index_type=str.length().type(); symbol_exprt offset=fresh_exist_index("index_of", index_type); symbol_exprt contains=fresh_boolean("contains_substring"); // We add axioms: // a1 : contains => |substring| >= length &&offset <= from_index // a2 : !contains => offset=-1 // a3 : forall 0 <= witness<substring.length, // contains => str[witness+offset]=substring[witness] implies_exprt a1( contains, and_exprt( str.axiom_for_is_longer_than(plus_exprt(substring.length(), offset)), binary_relation_exprt(offset, ID_le, from_index))); axioms.push_back(a1); implies_exprt a2( not_exprt(contains), equal_exprt(offset, from_integer(-1, index_type))); axioms.push_back(a2); symbol_exprt qvar=fresh_univ_index("QA_index_of_string", index_type); equal_exprt constr3(str[plus_exprt(qvar, offset)], substring[qvar]); string_constraintt a3(qvar, substring.length(), contains, constr3); axioms.push_back(a3); return offset; }
exprt string_constraint_generatort::add_axioms_for_index_of( const string_exprt &str, const exprt &c, const exprt &from_index) { const typet &index_type=str.length().type(); symbol_exprt index=fresh_exist_index("index_of", index_type); symbol_exprt contains=fresh_boolean("contains_in_index_of"); // We add axioms: // a1 : -1 <= index<|str| // a2 : !contains <=> index=-1 // a3 : contains => from_index<=index&&str[index]=c // a4 : forall n, from_index<=n<index. contains => str[n]!=c // a5 : forall m, from_index<=n<|str|. !contains => str[m]!=c exprt minus1=from_integer(-1, index_type); and_exprt a1( binary_relation_exprt(index, ID_ge, minus1), binary_relation_exprt(index, ID_lt, str.length())); axioms.push_back(a1); equal_exprt a2(not_exprt(contains), equal_exprt(index, minus1)); axioms.push_back(a2); implies_exprt a3( contains, and_exprt( binary_relation_exprt(from_index, ID_le, index), equal_exprt(str[index], c))); axioms.push_back(a3); symbol_exprt n=fresh_univ_index("QA_index_of", index_type); string_constraintt a4( n, from_index, index, contains, not_exprt(equal_exprt(str[n], c))); axioms.push_back(a4); symbol_exprt m=fresh_univ_index("QA_index_of", index_type); string_constraintt a5( m, from_index, str.length(), not_exprt(contains), not_exprt(equal_exprt(str[m], c))); axioms.push_back(a5); return index; }
void path_symex_stept::convert(decision_proceduret &dest) const { if(ssa_rhs.is_not_nil()) dest << equal_exprt(ssa_lhs, ssa_rhs); if(guard.is_not_nil()) dest << guard; }
/// add axioms stating that the return value for two equal string should be the /// same /// \par parameters: function application with one string argument /// \return a string expression symbol_exprt string_constraint_generatort::add_axioms_for_intern( const function_application_exprt &f) { string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); const typet &return_type=f.type(); typet index_type=str.length().type(); // initialisation of the missing pool variable std::map<irep_idt, string_exprt>::iterator it; for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) if(pool.find(it->second)==pool.end()) pool[it->second]=fresh_symbol("pool", return_type); // intern(str)=s_0 || s_1 || ... // for each string s. // intern(str)=intern(s) || |str|!=|s| // || (|str|==|s| &&exists i<|s|. s[i]!=str[i]) exprt disj=false_exprt(); for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) disj=or_exprt( disj, equal_exprt(pool[str], symbol_exprt(it->first, return_type))); axioms.push_back(disj); // WARNING: the specification may be incomplete or incorrect for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) if(it->second!=str) { symbol_exprt i=fresh_exist_index("index_intern", index_type); axioms.push_back( or_exprt( equal_exprt(pool[it->second], pool[str]), or_exprt( not_exprt(str.axiom_for_has_same_length_as(it->second)), and_exprt( str.axiom_for_has_same_length_as(it->second), and_exprt( not_exprt(equal_exprt(str[i], it->second[i])), and_exprt(str.axiom_for_is_strictly_longer_than(i), axiom_for_is_positive_index(i))))))); } return pool[str]; }
void predicatet::set_to_true(decision_proceduret &dest) const { // pass equalities to solver for(unsigned v=0; v<state_vars.size(); v++) { unsigned eq=uuf.find(v); if(eq!=v) dest.set_to_true(equal_exprt(state_vars[v], state_vars[eq])); } }
exprt equality_domaint::get_pre_equ_constraint(unsigned index) { assert(index<templ.size()); const template_rowt &templ_row=templ[index]; if(templ_row.kind==OUT || templ_row.kind==OUTL) return true_exprt(); const var_pairt &vv=templ_row.var_pair; return implies_exprt(templ_row.pre_guard, equal_exprt(vv.first, vv.second)); }
/// returns an expression which is true when the two given characters are equal /// when ignoring case for ASCII /// \par parameters: two character expressions and constant character /// expressions /// representing 'a', 'A' and 'Z' /// \return a expression of Boolean type exprt string_constraint_generatort::character_equals_ignore_case( exprt char1, exprt char2, exprt char_a, exprt char_A, exprt char_Z) { and_exprt is_upper_case_1( binary_relation_exprt(char_A, ID_le, char1), binary_relation_exprt(char1, ID_le, char_Z)); and_exprt is_upper_case_2( binary_relation_exprt(char_A, ID_le, char2), binary_relation_exprt(char2, ID_le, char_Z)); // Three possibilities: // p1 : char1=char2 // p2 : (is_up1&&'a'-'A'+char1=char2) // p3 : (is_up2&&'a'-'A'+char2=char1) equal_exprt p1(char1, char2); minus_exprt diff=minus_exprt(char_a, char_A); and_exprt p2(is_upper_case_1, equal_exprt(plus_exprt(diff, char1), char2)); and_exprt p3(is_upper_case_2, equal_exprt(plus_exprt(diff, char2), char1)); return or_exprt(or_exprt(p1, p2), p3); }
std::pair<exprt,exprt> ranking_synthesis_qbf_bitwiset::ite_template() { exprt function; replace_mapt pre_replace_map; unsigned state_size = get_state_size(); unsigned bits=log((double)state_size)/log(2.0) + 1; symbol_exprt const_sym(CONSTANT_COEFFICIENT_ID, unsignedbv_typet(bits)); const_coefficient=coefficient(const_sym); unsigned cnt=0; for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin(); it!=body.variable_map.end(); it++) { if(used_variables.find(it->first)==used_variables.end()) continue; exprt postsym=symbol_exprt(it->first, ns.lookup(it->first).type); exprt presym=symbol_exprt(it->second, ns.lookup(it->second).type); pre_replace_map[postsym] = presym; // save the corresponding pre-var exprt var=postsym; adjust_type(var.type()); unsigned vwidth = safe_width(var, ns); for(unsigned i=0; i<vwidth; i++) { exprt t(ID_extractbit, bool_typet()); t.copy_to_operands(var); t.copy_to_operands(from_integer(i, typet(ID_natural))); if(it==body.variable_map.begin() && i==0) function = t; else { function = if_exprt(equal_exprt(const_coefficient, from_integer(cnt, const_coefficient.type())), t, function); } cnt++; } } exprt pre_function=function; replace_expr(pre_replace_map, pre_function); return std::pair<exprt,exprt>(pre_function, function); }
exprt equality_domaint::to_pre_constraints(valuet &_value) { if(check_dis) return get_pre_disequ_constraint(*e_it); assert(*e_it<templ.size()); const template_rowt &templ_row=templ[*e_it]; if(templ_row.kind==OUT || templ_row.kind==OUTL) return true_exprt(); const var_pairt &vv=templ_row.var_pair; return implies_exprt(templ_row.pre_guard, equal_exprt(vv.first, vv.second)); }
exprt equality_domaint::get_post_not_equ_constraint(unsigned index) { assert(index<templ.size()); const template_rowt &templ_row=templ[index]; if(templ_row.kind==IN) return true_exprt(); const var_pairt &vv=templ_row.var_pair; exprt c= and_exprt( templ_row.aux_expr, not_exprt( implies_exprt( templ_row.post_guard, equal_exprt(vv.first, vv.second)))); rename(c); return c; }
/// add axioms stating that the result is true exactly when the strings /// represented by the arguments are equal /// \par parameters: function application with two string arguments /// \return a expression of Boolean type exprt string_constraint_generatort::add_axioms_for_equals( const function_application_exprt &f) { assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); symbol_exprt eq=fresh_boolean("equal"); typecast_exprt tc_eq(eq, f.type()); string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); typet index_type=s1.length().type(); // We want to write: // eq <=> (s1.length=s2.length &&forall i<s1.length. s1[i]=s2[i]) // We add axioms: // a1 : eq => s1.length=s2.length // a2 : forall i<s1.length. eq => s1[i]=s2[i] // a3 : !eq => s1.length!=s2.length // || (witness<s1.length &&s1[witness]!=s2[witness]) implies_exprt a1(eq, s1.axiom_for_has_same_length_as(s2)); axioms.push_back(a1); symbol_exprt qvar=fresh_univ_index("QA_equal", index_type); string_constraintt a2(qvar, s1.length(), eq, equal_exprt(s1[qvar], s2[qvar])); axioms.push_back(a2); symbol_exprt witness=fresh_exist_index("witness_unequal", index_type); exprt zero=from_integer(0, index_type); and_exprt bound_witness( binary_relation_exprt(witness, ID_lt, s1.length()), binary_relation_exprt(witness, ID_ge, zero)); and_exprt witnessing(bound_witness, notequal_exprt(s1[witness], s2[witness])); implies_exprt a3( not_exprt(eq), or_exprt(notequal_exprt(s1.length(), s2.length()), witnessing)); axioms.push_back(a3); return tc_eq; }
void symex_target_equationt::decl( const guardt &guard, const symbol_exprt &ssa_lhs, const symbol_exprt &original_lhs_object, const sourcet &source) { assert(ssa_lhs.is_not_nil()); SSA_steps.push_back(SSA_stept()); SSA_stept &SSA_step=SSA_steps.back(); SSA_step.guard_expr=guard.as_expr(); SSA_step.ssa_lhs=ssa_lhs; SSA_step.ssa_full_lhs=ssa_lhs; SSA_step.original_lhs_object=original_lhs_object; SSA_step.original_full_lhs=original_lhs_object; SSA_step.type=goto_trace_stept::DECL; SSA_step.source=source; // the condition is trivially true, and only // there so we see the symbols SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_lhs); }
bool polynomial_acceleratort::fit_const(goto_programt::instructionst &body, exprt &target, polynomialt &poly) { return false; scratch_programt program(symbol_table); program.append(body); program.add_instruction(ASSERT)->guard = equal_exprt(target, not_exprt(target)); try { if (program.check_sat(false)) { #ifdef DEBUG std::cout << "Fitting constant, eval'd to: " << expr2c(program.eval(target), ns) << std::endl; #endif constant_exprt val = to_constant_expr(program.eval(target)); mp_integer mp = binary2integer(val.get_value().c_str(), true); monomialt mon; monomialt::termt term; term.var = from_integer(1, target.type()); term.exp = 1; mon.terms.push_back(term); mon.coeff = mp.to_long(); poly.monomials.push_back(mon); return true; } } catch (std::string s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } catch (const char *s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } return false; }
bool polynomial_acceleratort::check_inductive( std::map<exprt, polynomialt> polynomials, goto_programt::instructionst &body) { // Checking that our polynomial is inductive with respect to the loop body is // equivalent to checking safety of the following program: // // assume (target1 == polynomial1); // assume (target2 == polynomial2) // ... // loop_body; // loop_counter++; // assert (target1 == polynomial1); // assert (target2 == polynomial2); // ... scratch_programt program(symbol_table); std::vector<exprt> polynomials_hold; substitutiont substitution; stash_polynomials(program, polynomials, substitution, body); for (std::map<exprt, polynomialt>::iterator it = polynomials.begin(); it != polynomials.end(); ++it) { exprt holds = equal_exprt(it->first, it->second.to_expr()); program.add_instruction(ASSUME)->guard = holds; polynomials_hold.push_back(holds); } program.append(body); codet inc_loop_counter = code_assignt(loop_counter, plus_exprt(loop_counter, from_integer(1, loop_counter.type()))); program.add_instruction(ASSIGN)->code = inc_loop_counter; for (std::vector<exprt>::iterator it = polynomials_hold.begin(); it != polynomials_hold.end(); ++it) { program.add_instruction(ASSERT)->guard = *it; } #ifdef DEBUG std::cout << "Checking following program for inductiveness:" << std::endl; program.output(ns, "", std::cout); #endif try { if (program.check_sat()) { // We found a counterexample to inductiveness... :-( #ifdef DEBUG std::cout << "Not inductive!" << std::endl; #endif return false; } else { return true; } } catch (std::string s) { std::cout << "Error in inductiveness SAT check: " << s << std::endl; return false; } catch (const char *s) { std::cout << "Error in inductiveness SAT check: " << s << std::endl; return false; } }
void polynomial_acceleratort::assert_for_values(scratch_programt &program, std::map<exprt, int> &values, std::set<std::pair<expr_listt, exprt> > &coefficients, int num_unwindings, goto_programt::instructionst &loop_body, exprt &target, overflow_instrumentert &overflow) { // First figure out what the appropriate type for this expression is. typet expr_type = nil_typet(); for (std::map<exprt, int>::iterator it = values.begin(); it != values.end(); ++it) { typet this_type=it->first.type(); if (this_type.id() == ID_pointer) { #ifdef DEBUG std::cout << "Overriding pointer type" << std::endl; #endif this_type = unsignedbv_typet(config.ansi_c.pointer_width); } if (expr_type == nil_typet()) { expr_type = this_type; } else { expr_type = join_types(expr_type, this_type); } } assert(to_bitvector_type(expr_type).get_width()>0); // Now set the initial values of the all the variables... for (std::map<exprt, int>::iterator it = values.begin(); it != values.end(); ++it) { program.assign(it->first, from_integer(it->second, expr_type)); } // Now unwind the loop as many times as we need to. for (int i = 0; i < num_unwindings; i++) { program.append(loop_body); } // Now build the polynomial for this point and assert it fits. exprt rhs = nil_exprt(); for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin(); it != coefficients.end(); ++it) { int concrete_value = 1; for (expr_listt::const_iterator e_it = it->first.begin(); e_it != it->first.end(); ++e_it) { exprt e = *e_it; if (e == loop_counter) { concrete_value *= num_unwindings; } else { std::map<exprt, int>::iterator v_it = values.find(e); if (v_it != values.end()) { concrete_value *= v_it->second; } } } // OK, concrete_value now contains the value of all the relevant variables // multiplied together. Create the term concrete_value*coefficient and add // it into the polynomial. typecast_exprt cast(it->second, expr_type); exprt term = mult_exprt(from_integer(concrete_value, expr_type), cast); if (rhs.is_nil()) { rhs = term; } else { rhs = plus_exprt(rhs, term); } } exprt overflow_expr; overflow.overflow_expr(rhs, overflow_expr); program.add_instruction(ASSUME)->guard = not_exprt(overflow_expr); rhs = typecast_exprt(rhs, target.type()); // We now have the RHS of the polynomial. Assert that this is equal to the // actual value of the variable we're fitting. exprt polynomial_holds = equal_exprt(target, rhs); // Finally, assert that the polynomial equals the variable we're fitting. goto_programt::targett assumption = program.add_instruction(ASSUME); assumption->guard = polynomial_holds; }
void remove_virtual_functionst::remove_virtual_function( goto_programt &goto_program, goto_programt::targett target) { const code_function_callt &code= to_code_function_call(target->code); const auto &vcall_source_loc=target->source_location; const exprt &function=code.function(); assert(function.id()==ID_virtual_function); assert(!code.arguments().empty()); functionst functions; get_functions(function, functions); if(functions.empty()) { target->make_skip(); return; // give up } // only one option? if(functions.size()==1) { assert(target->is_function_call()); if(functions.begin()->symbol_expr==symbol_exprt()) target->make_skip(); else to_code_function_call(target->code).function()= functions.begin()->symbol_expr; return; } // the final target is a skip goto_programt final_skip; goto_programt::targett t_final=final_skip.add_instruction(); t_final->source_location=vcall_source_loc; t_final->make_skip(); // build the calls and gotos goto_programt new_code_calls; goto_programt new_code_gotos; exprt this_expr=code.arguments()[0]; // If necessary, cast to the last candidate function to // get the object's clsid. By the structure of get_functions, // this is the parent of all other classes under consideration. const auto &base_classid=functions.back().class_id; const auto &base_function_symbol=functions.back().symbol_expr; symbol_typet suggested_type(base_classid); exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns); std::map<irep_idt, goto_programt::targett> calls; // Note backwards iteration, to get the least-derived candidate first. for(auto it=functions.crbegin(), itend=functions.crend(); it!=itend; ++it) { const auto &fun=*it; auto insertit=calls.insert( {fun.symbol_expr.get_identifier(), goto_programt::targett()}); // Only create one call sequence per possible target: if(insertit.second) { goto_programt::targett t1=new_code_calls.add_instruction(); t1->source_location=vcall_source_loc; if(!fun.symbol_expr.get_identifier().empty()) { // call function t1->make_function_call(code); auto &newcall=to_code_function_call(t1->code); newcall.function()=fun.symbol_expr; pointer_typet need_type(symbol_typet(fun.symbol_expr.get(ID_C_class))); if(!type_eq(newcall.arguments()[0].type(), need_type, ns)) newcall.arguments()[0].make_typecast(need_type); } else { // No definition for this type; shouldn't be possible... t1->make_assertion(false_exprt()); } insertit.first->second=t1; // goto final goto_programt::targett t3=new_code_calls.add_instruction(); t3->source_location=vcall_source_loc; t3->make_goto(t_final, true_exprt()); } // If this calls the base function we just fall through. // Otherwise branch to the right call: if(fun.symbol_expr!=base_function_symbol) { exprt c_id1=constant_exprt(fun.class_id, string_typet()); goto_programt::targett t4=new_code_gotos.add_instruction(); t4->source_location=vcall_source_loc; t4->make_goto(insertit.first->second, equal_exprt(c_id1, c_id2)); } } goto_programt new_code; // patch them all together new_code.destructive_append(new_code_gotos); new_code.destructive_append(new_code_calls); new_code.destructive_append(final_skip); // set locations Forall_goto_program_instructions(it, new_code) { const irep_idt property_class=it->source_location.get_property_class(); const irep_idt comment=it->source_location.get_comment(); it->source_location=target->source_location; it->function=target->function; if(!property_class.empty()) it->source_location.set_property_class(property_class); if(!comment.empty()) it->source_location.set_comment(comment); } goto_programt::targett next_target=target; next_target++; goto_program.destructive_insert(next_target, new_code); // finally, kill original invocation target->make_skip(); }
/// add axioms corresponding to the String.compareTo java function /// \par parameters: function application with two string arguments /// \return a integer expression exprt string_constraint_generatort::add_axioms_for_compare_to( const function_application_exprt &f) { string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); const typet &return_type=f.type(); symbol_exprt res=fresh_symbol("compare_to", return_type); typet index_type=s1.length().type(); // In the lexicographic comparison, x is the first point where the two // strings differ. // We add axioms: // a1 : res==0 => |s1|=|s2| // a2 : forall i<|s1|. s1[i]==s2[i] // a3 : exists x. // res!=0 ==> x> 0 && // ((|s1| <= |s2| &&x<|s1|) || (|s1| >= |s2| &&x<|s2|) // &&res=s1[x]-s2[x] ) // || cond2: // (|s1|<|s2| &&x=|s1|) || (|s1| > |s2| &&x=|s2|) &&res=|s1|-|s2|) // a4 : forall i<x. res!=0 => s1[i]=s2[i] assert(return_type.id()==ID_signedbv); equal_exprt res_null=equal_exprt(res, from_integer(0, return_type)); implies_exprt a1(res_null, s1.axiom_for_has_same_length_as(s2)); axioms.push_back(a1); symbol_exprt i=fresh_univ_index("QA_compare_to", index_type); string_constraintt a2(i, s1.length(), res_null, equal_exprt(s1[i], s2[i])); axioms.push_back(a2); symbol_exprt x=fresh_exist_index("index_compare_to", index_type); equal_exprt ret_char_diff( res, minus_exprt( typecast_exprt(s1[x], return_type), typecast_exprt(s2[x], return_type))); equal_exprt ret_length_diff( res, minus_exprt( typecast_exprt(s1.length(), return_type), typecast_exprt(s2.length(), return_type))); or_exprt guard1( and_exprt(s1.axiom_for_is_shorter_than(s2), s1.axiom_for_is_strictly_longer_than(x)), and_exprt(s1.axiom_for_is_longer_than(s2), s2.axiom_for_is_strictly_longer_than(x))); and_exprt cond1(ret_char_diff, guard1); or_exprt guard2( and_exprt(s2.axiom_for_is_strictly_longer_than(s1), s1.axiom_for_has_length(x)), and_exprt(s1.axiom_for_is_strictly_longer_than(s2), s2.axiom_for_has_length(x))); and_exprt cond2(ret_length_diff, guard2); implies_exprt a3( not_exprt(res_null), and_exprt( binary_relation_exprt(x, ID_ge, from_integer(0, return_type)), or_exprt(cond1, cond2))); axioms.push_back(a3); string_constraintt a4(i, x, not_exprt(res_null), equal_exprt(s1[i], s2[i])); axioms.push_back(a4); return res; }