const exprt qbf_squolem_coret::f_get(literalt l) { if(squolem->isUniversal(l.var_no())) { assert(l.var_no()!=0); variable_mapt::const_iterator it=variable_map.find(l.var_no()); if(it==variable_map.end()) throw "Variable map error"; const exprt &sym=it->second.first; unsigned index=it->second.second; exprt extract_expr(ID_extractbit, typet(ID_bool)); extract_expr.copy_to_operands(sym); typet uint_type(ID_unsignedbv); uint_type.set(ID_width, 32); extract_expr.copy_to_operands(from_integer(index, uint_type)); if(l.sign()) extract_expr.negate(); return extract_expr; } function_cachet::const_iterator it=function_cache.find(l.var_no()); if(it!=function_cache.end()) { #if 0 std::cout << "CACHE HIT for " << l.dimacs() << std::endl; #endif if(l.sign()) return not_exprt(it->second); else return it->second; } else { WitnessStack *wsp = squolem->getModelFunction(Literal(l.dimacs())); exprt res; if(wsp==NULL || wsp->empty()) { // res=exprt(ID_nondet_bool, typet(ID_bool)); res=false_exprt(); // just set it to zero } else if(wsp->pSize<=wsp->nSize) res=f_get_cnf(wsp); else res=f_get_dnf(wsp); function_cache[l.var_no()] = res; if(l.sign()) return not_exprt(res); else return res; } }
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; }
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; }
void goto_checkt::pointer_overflow_check( const exprt &expr, const guardt &guard) { if(!enable_pointer_overflow_check) return; if(expr.id()==ID_plus || expr.id()==ID_minus) { if(expr.operands().size()==2) { exprt overflow("overflow-"+expr.id_string(), bool_typet()); overflow.operands()=expr.operands(); add_guarded_claim( not_exprt(overflow), "pointer arithmetic overflow on "+expr.id_string(), "overflow", expr.find_source_location(), expr, guard); } } }
/// 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 all_paths_enumeratort::extend_path(patht &path, goto_programt::targett t, int succ) { goto_programt::targett next; goto_programt::targetst succs; exprt guard = true_exprt(); goto_program.get_successors(t, succs); for (goto_programt::targetst::iterator it = succs.begin(); it != succs.end(); ++it) { if (succ == 0) { next = *it; break; } succ--; } if (t->is_goto()) { guard = not_exprt(t->guard); for (goto_programt::targetst::iterator it = t->targets.begin(); it != t->targets.end(); ++it) { if (next == *it) { guard = t->guard; break; } } } path.push_back(path_nodet(next, guard)); }
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; }
void thread_exit_instrumentation(goto_programt &goto_program) { if(goto_program.instructions.empty()) return; // add assertion that all may flags for mutex-locked are gone // at the end goto_programt::targett end=goto_program.instructions.end(); end--; assert(end->is_end_function()); source_locationt source_location=end->source_location; irep_idt function=end->function; goto_program.insert_before_swap(end); exprt mutex_locked_string= string_constantt("mutex-locked"); binary_exprt get_may("get_may"); // NULL is any get_may.op0()=constant_exprt(ID_NULL, pointer_typet(empty_typet())); get_may.op1()=address_of_exprt(mutex_locked_string); end->make_assertion(not_exprt(get_may)); end->source_location=source_location; end->source_location.set_comment("mutexes must not be locked on thread exit"); end->function=function; }
/// 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]; }
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 memory_model_sct::write_serialization_external( symex_target_equationt &equation) { for(address_mapt::const_iterator a_it=address_map.begin(); a_it!=address_map.end(); a_it++) { const a_rect &a_rec=a_it->second; // This is quadratic in the number of writes // per address. Perhaps some better encoding // based on 'places'? for(event_listt::const_iterator w_it1=a_rec.writes.begin(); w_it1!=a_rec.writes.end(); ++w_it1) { event_listt::const_iterator next=w_it1; ++next; for(event_listt::const_iterator w_it2=next; w_it2!=a_rec.writes.end(); ++w_it2) { // external? if((*w_it1)->source.thread_nr== (*w_it2)->source.thread_nr) continue; // ws is a total order, no two elements have the same rank // s -> w_evt1 before w_evt2; !s -> w_evt2 before w_evt1 symbol_exprt s=nondet_bool_symbol("ws-ext"); // write-to-write edge add_constraint( equation, implies_exprt(s, before(*w_it1, *w_it2)), "ws-ext", (*w_it1)->source); add_constraint( equation, implies_exprt(not_exprt(s), before(*w_it2, *w_it1)), "ws-ext", (*w_it1)->source); } } } }
void interval_domaint::transform( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { const goto_programt::instructiont &instruction=*from; switch(instruction.type) { case DECL: havoc_rec(to_code_decl(instruction.code).symbol()); break; case DEAD: havoc_rec(to_code_dead(instruction.code).symbol()); break; case ASSIGN: assign(to_code_assign(instruction.code)); break; case GOTO: { locationt next=from; next++; if(next==to) assume(not_exprt(instruction.guard), ns); else assume(instruction.guard, ns); } break; case ASSUME: assume(instruction.guard, ns); break; case FUNCTION_CALL: { const code_function_callt &code_function_call= to_code_function_call(instruction.code); if(code_function_call.lhs().is_not_nil()) havoc_rec(code_function_call.lhs()); } break; default: { } } }
void predabs_domaint::make_not_post_constraints( const templ_valuet &value, exprt::operandst &cond_exprs) { assert(value.size()==templ.size()); cond_exprs.resize(templ.size()); exprt::operandst c; for(std::size_t row=0; row<templ.size(); row++) { cond_exprs[row]=and_exprt( templ[row].aux_expr, not_exprt(get_row_post_constraint(row, value))); } }
exprt ranking_synthesis_qbf_bitwiset::bitwise_chain( const irep_idt &termOp, const exprt &expr) const { unsigned width=safe_width(expr, ns); assert(width>0); if(width==1) { if(expr.type()!=bool_typet()) { typecast_exprt t(typet(ID_bool)); t.op() = expr; return t; } else return expr; } exprt res; exprt e(ID_extractbit, bool_typet()); e.copy_to_operands(expr); res = e; res.copy_to_operands(from_integer(0, typet(ID_natural))); for(unsigned i=1; i<width; i++) { if(termOp==ID_notequal) { exprt t(ID_equal, bool_typet()); t.copy_to_operands(res, e); t.op1().copy_to_operands(from_integer(i, typet(ID_natural))); res=not_exprt(t); } else { exprt t(termOp, bool_typet()); t.copy_to_operands(res, e); t.op1().copy_to_operands(from_integer(i, typet(ID_natural))); res=t; } } return res; }
/// add axioms corresponding to the String.equalsIgnoreCase java function /// \par parameters: function application with two string arguments /// \return a Boolean expression exprt string_constraint_generatort::add_axioms_for_equals_ignore_case( const function_application_exprt &f) { assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); symbol_exprt eq=fresh_boolean("equal_ignore_case"); 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 char_type=to_refined_string_type(s1.type()).get_char_type(); exprt char_a=constant_char('a', char_type); exprt char_A=constant_char('A', char_type); exprt char_Z=constant_char('Z', char_type); typet index_type=s1.length().type(); // We add axioms: // a1 : eq => |s1|=|s2| // a2 : forall qvar, 0<=qvar<|s1|, // eq => char_equal_ignore_case(s1[qvar],s2[qvar]); // a3 : !eq => |s1|!=s2 || (0 <=witness<|s1| &&!char_equal_ignore_case) implies_exprt a1(eq, s1.axiom_for_has_same_length_as(s2)); axioms.push_back(a1); symbol_exprt qvar=fresh_univ_index("QA_equal_ignore_case", index_type); exprt constr2=character_equals_ignore_case( s1[qvar], s2[qvar], char_a, char_A, char_Z); string_constraintt a2(qvar, s1.length(), eq, constr2); axioms.push_back(a2); symbol_exprt witness=fresh_exist_index( "witness_unequal_ignore_case", index_type); exprt zero=from_integer(0, witness.type()); and_exprt bound_witness( binary_relation_exprt(witness, ID_lt, s1.length()), binary_relation_exprt(witness, ID_ge, zero)); exprt witness_eq=character_equals_ignore_case( s1[witness], s2[witness], char_a, char_A, char_Z); not_exprt witness_diff(witness_eq); implies_exprt a3( not_exprt(eq), or_exprt( notequal_exprt(s1.length(), s2.length()), and_exprt(bound_witness, witness_diff))); axioms.push_back(a3); return tc_eq; }
void acceleratet::make_overflow_loc( goto_programt::targett loop_header, goto_programt::targett &loop_end, goto_programt::targett &overflow_loc) { symbolt overflow_sym=utils.fresh_symbol("accelerate::overflow", bool_typet()); const exprt &overflow_var=overflow_sym.symbol_expr(); natural_loops_mutablet::natural_loopt &loop = natural_loops.loop_map[loop_header]; overflow_instrumentert instrumenter(program, overflow_var, symbol_table); for(natural_loops_mutablet::natural_loopt::iterator it=loop.begin(); it!=loop.end(); ++it) { overflow_locs[*it]=goto_programt::targetst(); goto_programt::targetst &added=overflow_locs[*it]; instrumenter.add_overflow_checks(*it, added); loop.insert(added.begin(), added.end()); } goto_programt::targett t=program.insert_after(loop_header); t->make_assignment(); t->code=code_assignt(overflow_var, false_exprt()); t->swap(*loop_header); loop.insert(t); overflow_locs[loop_header].push_back(t); goto_programt::instructiont s(SKIP); overflow_loc=program.insert_after(loop_end); *overflow_loc=s; overflow_loc->swap(*loop_end); loop.insert(overflow_loc); goto_programt::instructiont g(GOTO); g.guard=not_exprt(overflow_var); g.targets.push_back(overflow_loc); goto_programt::targett t2=program.insert_after(loop_end); *t2=g; t2->swap(*loop_end); overflow_locs[overflow_loc].push_back(t2); loop.insert(t2); goto_programt::targett tmp=overflow_loc; overflow_loc=loop_end; loop_end=tmp; }
exprt local_SSAt::edge_guard(locationt from, locationt to) const { if(from->is_goto()) { // big question: taken or not taken? if(to==from->get_target()) return and_exprt(guard_symbol(from), cond_symbol(from)); else return and_exprt(guard_symbol(from), not_exprt(cond_symbol(from))); } else if(from->is_assume()) { return and_exprt(guard_symbol(from), cond_symbol(from)); } else return guard_symbol(from); }
exprt equality_domaint::get_post_not_disequ_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, notequal_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; }
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 interval_domaint::ai_simplify( exprt &condition, const namespacet &ns) const { bool unchanged=true; interval_domaint d(*this); // merge intervals to properly handle conjunction if(condition.id()==ID_and) // May be directly representable { interval_domaint a; a.make_top(); // a is everything a.assume(condition, ns); // Restrict a to an over-approximation // of when condition is true if(!a.join(d)) // If d (this) is included in a... { // Then the condition is always true unchanged=condition.is_true(); condition.make_true(); } } else if(condition.id()==ID_symbol) { // TODO: we have to handle symbol expression } else // Less likely to be representable { d.assume(not_exprt(condition), ns); // Restrict to when condition is false if(d.is_bottom()) // If there there are none... { // Then the condition is always true unchanged=condition.is_true(); condition.make_true(); } } return unchanged; }
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; }
/// 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; }
std::pair<exprt,exprt> ranking_synthesis_qbf_bitwiset::affine_template( const irep_idt &termOp, const irep_idt &coefOp) { exprt function; replace_mapt pre_replace_map; 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()); exprt co = coefficient(var); irep_idt bitop = (coefOp==ID_and) ? ID_bitand : (coefOp==ID_or) ? ID_bitor : (coefOp==ID_notequal) ? ID_bitxor : ""; exprt varblock(bitop, var.type()); varblock.copy_to_operands(var, co); exprt bchain = bitwise_chain(termOp, varblock); if(it==body.variable_map.begin()) // first one function=bchain; else { if(termOp==ID_notequal) { exprt t(ID_equal, bool_typet()); t.move_to_operands(function); t.move_to_operands(bchain); function=not_exprt(t); } else { exprt t(termOp, bool_typet()); t.move_to_operands(function); t.move_to_operands(bchain); function=t; } } } // ... and a constant coefficient symbol_exprt const_sym(CONSTANT_COEFFICIENT_ID, bool_typet()); const_coefficient=coefficient(const_sym); if(termOp==ID_notequal) { exprt t(ID_equal, bool_typet()); t.move_to_operands(function); t.copy_to_operands(const_coefficient); function = not_exprt(t); } else { exprt t(termOp, bool_typet()); t.move_to_operands(function); t.copy_to_operands(const_coefficient); function = t; } exprt pre_function=function; replace_expr(pre_replace_map, pre_function); return std::pair<exprt,exprt>(pre_function, function); }
void goto_checkt::float_overflow_check( const exprt &expr, const guardt &guard) { if(!enable_float_overflow_check) return; // First, check type. const typet &type=ns.follow(expr.type()); if(type.id()!=ID_floatbv) return; // add overflow subgoal if(expr.id()==ID_typecast) { // Can overflow if casting from larger // to smaller type. assert(expr.operands().size()==1); if(ns.follow(expr.op0().type()).id()==ID_floatbv) { // float-to-float unary_exprt op0_inf(ID_isinf, expr.op0(), bool_typet()); unary_exprt new_inf(ID_isinf, expr, bool_typet()); or_exprt overflow_check(op0_inf, not_exprt(new_inf)); add_guarded_claim( overflow_check, "arithmetic overflow on floating-point typecast", "overflow", expr.find_source_location(), expr, guard); } else { // non-float-to-float unary_exprt new_inf(ID_isinf, expr, bool_typet()); add_guarded_claim( not_exprt(new_inf), "arithmetic overflow on floating-point typecast", "overflow", expr.find_source_location(), expr, guard); } return; } else if(expr.id()==ID_div) { assert(expr.operands().size()==2); // Can overflow if dividing by something small unary_exprt new_inf(ID_isinf, expr, bool_typet()); unary_exprt op0_inf(ID_isinf, expr.op0(), bool_typet()); or_exprt overflow_check(op0_inf, not_exprt(new_inf)); add_guarded_claim( overflow_check, "arithmetic overflow on floating-point division", "overflow", expr.find_source_location(), expr, guard); return; } else if(expr.id()==ID_mod) { // Can't overflow return; } else if(expr.id()==ID_unary_minus) { // Can't overflow return; } else if(expr.id()==ID_plus || expr.id()==ID_mult || expr.id()==ID_minus) { if(expr.operands().size()==2) { // Can overflow unary_exprt new_inf(ID_isinf, expr, bool_typet()); unary_exprt op0_inf(ID_isinf, expr.op0(), bool_typet()); unary_exprt op1_inf(ID_isinf, expr.op1(), bool_typet()); or_exprt overflow_check(op0_inf, op1_inf, not_exprt(new_inf)); std::string kind= expr.id()==ID_plus?"addition": expr.id()==ID_minus?"subtraction": expr.id()==ID_mult?"multiplication":""; add_guarded_claim( overflow_check, "arithmetic overflow on floating-point "+kind, "overflow", expr.find_source_location(), expr, guard); return; } else if(expr.operands().size()>=3) { assert(expr.id()!=ID_minus); // break up exprt tmp=make_binary(expr); float_overflow_check(tmp, guard); return; } } }
void goto_checkt::pointer_validity_check( const dereference_exprt &expr, const guardt &guard) { if(!enable_pointer_check) return; const exprt &pointer=expr.op0(); const typet &pointer_type=to_pointer_type(ns.follow(pointer.type())); assert(base_type_eq(pointer_type.subtype(), expr.type(), ns)); local_bitvector_analysist::flagst flags= local_bitvector_analysis->get(t, pointer); const typet &dereference_type=pointer_type.subtype(); // For Java, we only need to check for null if(mode==ID_java) { if(flags.is_unknown() || flags.is_null()) { notequal_exprt not_eq_null(pointer, gen_zero(pointer.type())); add_guarded_claim( not_eq_null, "reference is null", "pointer dereference", expr.find_source_location(), expr, guard); } } else { if(flags.is_unknown() || flags.is_null()) { add_guarded_claim( not_exprt(null_pointer(pointer)), "dereference failure: pointer NULL", "pointer dereference", expr.find_source_location(), expr, guard); } if(flags.is_unknown()) add_guarded_claim( not_exprt(invalid_pointer(pointer)), "dereference failure: pointer invalid", "pointer dereference", expr.find_source_location(), expr, guard); if(flags.is_uninitialized()) add_guarded_claim( not_exprt(invalid_pointer(pointer)), "dereference failure: pointer uninitialized", "pointer dereference", expr.find_source_location(), expr, guard); if(mode != ID_java) { if(flags.is_unknown() || flags.is_dynamic_heap()) add_guarded_claim( not_exprt(deallocated(pointer, ns)), "dereference failure: deallocated dynamic object", "pointer dereference", expr.find_source_location(), expr, guard); if(flags.is_unknown() || flags.is_dynamic_local()) add_guarded_claim( not_exprt(dead_object(pointer, ns)), "dereference failure: dead object", "pointer dereference", expr.find_source_location(), expr, guard); } if(enable_bounds_check) { if(flags.is_unknown() || flags.is_dynamic_heap()) { exprt dynamic_bounds= or_exprt(dynamic_object_lower_bound(pointer), dynamic_object_upper_bound(pointer, dereference_type, ns)); add_guarded_claim( implies_exprt(malloc_object(pointer, ns), not_exprt(dynamic_bounds)), "dereference failure: dynamic object bounds", "pointer dereference", expr.find_source_location(), expr, guard); } } if(enable_bounds_check) { if(flags.is_unknown() || flags.is_dynamic_local() || flags.is_static_lifetime()) { exprt object_bounds= or_exprt(object_lower_bound(pointer), object_upper_bound(pointer, dereference_type, ns)); add_guarded_claim( or_exprt(dynamic_object(pointer), not_exprt(object_bounds)), "dereference failure: object bounds", "pointer dereference", expr.find_source_location(), expr, guard); } } } }
void disjunctive_polynomial_accelerationt::build_path( scratch_programt &scratch_program, patht &path) { goto_programt::targett t = loop_header; do { goto_programt::targett next; goto_programt::targetst succs; goto_program.get_successors(t, succs); // We should have a looping path, so we should never hit a location // with no successors. assert(succs.size() > 0); if (succs.size() == 1) { // Only one successor -- accumulate it and move on. path.push_back(path_nodet(t)); t = succs.front(); continue; } // We have multiple successors. Examine the distinguisher variables // to see which branch was taken. bool found_branch = false; for (goto_programt::targetst::iterator it = succs.begin(); it != succs.end(); ++it) { exprt &distinguisher = distinguishing_points[*it]; bool taken = scratch_program.eval(distinguisher).is_true(); if (taken) { if (!found_branch || ((*it)->location_number < next->location_number)) { next = *it; } found_branch = true; } } assert(found_branch); exprt cond = nil_exprt(); if (t->is_goto()) { // If this was a conditional branch (it probably was), figure out // if we hit the "taken" or "not taken" branch & accumulate the // appropriate guard. cond = not_exprt(t->guard); for (goto_programt::targetst::iterator it = t->targets.begin(); it != t->targets.end(); ++it) { if (next == *it) { cond = t->guard; break; } } } path.push_back(path_nodet(t, cond)); t = next; } while (t != loop_header && (loop.find(t) != loop.end())); }
void acceleratet::build_state_machine( trace_automatont::sym_mapt::iterator begin, trace_automatont::sym_mapt::iterator end, state_sett &accept_states, symbol_exprt state, symbol_exprt next_state, scratch_programt &state_machine) { std::map<unsigned int, unsigned int> successor_counts; unsigned int max_count=0; unsigned int likely_next=0; // Optimisation: find the most common successor state and initialise // next_state to that value. This reduces the size of the state machine // driver substantially. for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p) { trace_automatont::state_pairt state_pair=p->second; unsigned int to=state_pair.second; unsigned int count=0; if(successor_counts.find(to)==successor_counts.end()) { count=1; } else { count=successor_counts[to] + 1; } successor_counts[to]=count; if(count > max_count) { max_count=count; likely_next=to; } } // Optimisation: if there is only one possible successor state, just // jump straight to it instead of driving the whole machine. if(successor_counts.size()==1) { if(accept_states.find(likely_next)!=accept_states.end()) { // It's an accept state. Just assume(false). state_machine.assume(false_exprt()); } else { state_machine.assign(state, from_integer(likely_next, next_state.type())); } return; } state_machine.assign(next_state, from_integer(likely_next, next_state.type())); for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p) { trace_automatont::state_pairt state_pair=p->second; unsigned int from=state_pair.first; unsigned int to=state_pair.second; if(to==likely_next) { continue; } // We're encoding the transition // // from -loc-> to // // which we encode by inserting: // // next_state=(state==from) ? to : next_state; // // just before loc. equal_exprt guard(state, from_integer(from, state.type())); if_exprt rhs(guard, from_integer(to, next_state.type()), next_state); state_machine.assign(next_state, rhs); } // Update the state and assume(false) if we've hit an accept state. state_machine.assign(state, next_state); for(state_sett::iterator it=accept_states.begin(); it!=accept_states.end(); ++it) { state_machine.assume( not_exprt(equal_exprt(state, from_integer(*it, state.type())))); } }
void acceleratet::add_dirty_checks() { for(expr_mapt::iterator it=dirty_vars_map.begin(); it!=dirty_vars_map.end(); ++it) { goto_programt::instructiont assign(ASSIGN); assign.code=code_assignt(it->second, false_exprt()); program.insert_before_swap(program.instructions.begin(), assign); } goto_programt::targett next; for(goto_programt::targett it=program.instructions.begin(); it!=program.instructions.end(); it=next) { next=it; ++next; // If this is an assign to a tracked variable, clear the dirty flag. // Note: this order of insertions means that we assume each of the read // variables is clean _before_ clearing any dirty flags. if(it->is_assign()) { exprt &lhs=it->code.op0(); expr_mapt::iterator dirty_var=dirty_vars_map.find(lhs); if(dirty_var!=dirty_vars_map.end()) { goto_programt::instructiont clear_flag(ASSIGN); clear_flag.code=code_assignt(dirty_var->second, false_exprt()); program.insert_before_swap(it, clear_flag); } } // Find which symbols are read, i.e. those appearing in a guard or on // the right hand side of an assignment. Assume each is not dirty. find_symbols_sett read; find_symbols(it->guard, read); if(it->is_assign()) { find_symbols(it->code.op1(), read); } for(find_symbols_sett::iterator jt=read.begin(); jt!=read.end(); ++jt) { const exprt &var=ns.lookup(*jt).symbol_expr(); expr_mapt::iterator dirty_var=dirty_vars_map.find(var); if(dirty_var==dirty_vars_map.end()) { continue; } goto_programt::instructiont not_dirty(ASSUME); not_dirty.guard=not_exprt(dirty_var->second); program.insert_before_swap(it, not_dirty); } } }
void local_SSAt::assign_rec( const exprt &lhs, const exprt &rhs, const exprt &guard, locationt loc) { const typet &type=ns.follow(lhs.type()); if(is_symbol_struct_member(lhs, ns)) { if(type.id()==ID_struct) { // need to split up const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components=struct_type.components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { member_exprt new_lhs(lhs, it->get_name(), it->type()); member_exprt new_rhs(rhs, it->get_name(), it->type()); assign_rec(new_lhs, new_rhs, guard, loc); } return; } ssa_objectt lhs_object(lhs, ns); const std::set<ssa_objectt> &assigned= assignments.get(loc); if(assigned.find(lhs_object)!=assigned.end()) { exprt ssa_rhs=read_rhs(rhs, loc); const symbol_exprt ssa_symbol=name(lhs_object, OUT, loc); equal_exprt equality(ssa_symbol, ssa_rhs); nodes[loc].equalities.push_back(equality); } } else if(lhs.id()==ID_index) { const index_exprt &index_expr=to_index_expr(lhs); exprt ssa_array=index_expr.array(); exprt new_rhs=with_exprt(ssa_array, index_expr.index(), rhs); assign_rec(index_expr.array(), new_rhs, guard, loc); } else if(lhs.id()==ID_member) { // These are non-flattened struct or union members. const member_exprt &member_expr=to_member_expr(lhs); const exprt &compound=member_expr.struct_op(); const typet &compound_type=ns.follow(compound.type()); if(compound_type.id()==ID_union) { union_exprt new_rhs(member_expr.get_component_name(), rhs, compound.type()); assign_rec(member_expr.struct_op(), new_rhs, guard, loc); } else if(compound_type.id()==ID_struct) { exprt member_name(ID_member_name); member_name.set(ID_component_name, member_expr.get_component_name()); with_exprt new_rhs(compound, member_name, rhs); assign_rec(compound, new_rhs, guard, loc); } } else if(lhs.id()==ID_complex_real) { assert(lhs.operands().size()==1); const exprt &op=lhs.op0(); const complex_typet &complex_type=to_complex_type(op.type()); exprt imag_op=unary_exprt(ID_complex_imag, op, complex_type.subtype()); complex_exprt new_rhs(rhs, imag_op, complex_type); assign_rec(op, new_rhs, guard, loc); } else if(lhs.id()==ID_complex_imag) { assert(lhs.operands().size()==1); const exprt &op=lhs.op0(); const complex_typet &complex_type=to_complex_type(op.type()); exprt real_op=unary_exprt(ID_complex_real, op, complex_type.subtype()); complex_exprt new_rhs(real_op, rhs, complex_type); assign_rec(op, new_rhs, guard, loc); } else if(lhs.id()==ID_if) { const if_exprt &if_expr=to_if_expr(lhs); assign_rec(if_expr.true_case(), rhs, and_exprt(guard, if_expr.cond()), loc); assign_rec(if_expr.false_case(), rhs, and_exprt(guard, not_exprt(if_expr.cond())), loc); } else if(lhs.id()==ID_byte_extract_little_endian || lhs.id()==ID_byte_extract_big_endian) { const byte_extract_exprt &byte_extract_expr=to_byte_extract_expr(lhs); exprt new_lhs=byte_extract_expr.op(); exprt new_rhs=byte_extract_exprt( byte_extract_expr.id(), rhs, byte_extract_expr.offset(), new_lhs.type()); assign_rec(new_lhs, new_rhs, guard, loc); } else throw "UNKNOWN LHS: "+lhs.id_string(); }