LLVMValueRef gen_or_assign(struct node *ast) { LLVMValueRef result; result = gen_or(ast); check_store(result, lvalue(ast->one)); return result; }
static bool special_case_operator(compile_t* c, ast_t* ast, LLVMValueRef *value, bool short_circuit, bool native128) { AST_GET_CHILDREN(ast, positional, named, postfix); AST_GET_CHILDREN(postfix, left, method); ast_t* right = ast_child(positional); const char* name = ast_name(method); *value = NULL; if(name == c->str_add) *value = gen_add(c, left, right); else if(name == c->str_sub) *value = gen_sub(c, left, right); else if((name == c->str_mul) && native128) *value = gen_mul(c, left, right); else if((name == c->str_div) && native128) *value = gen_div(c, left, right); else if((name == c->str_mod) && native128) *value = gen_mod(c, left, right); else if(name == c->str_neg) *value = gen_neg(c, left); else if((name == c->str_and) && short_circuit) *value = gen_and_sc(c, left, right); else if((name == c->str_or) && short_circuit) *value = gen_or_sc(c, left, right); else if((name == c->str_and) && !short_circuit) *value = gen_and(c, left, right); else if((name == c->str_or) && !short_circuit) *value = gen_or(c, left, right); else if(name == c->str_xor) *value = gen_xor(c, left, right); else if(name == c->str_not) *value = gen_not(c, left); else if(name == c->str_shl) *value = gen_shl(c, left, right); else if(name == c->str_shr) *value = gen_shr(c, left, right); else if(name == c->str_eq) *value = gen_eq(c, left, right); else if(name == c->str_ne) *value = gen_ne(c, left, right); else if(name == c->str_lt) *value = gen_lt(c, left, right); else if(name == c->str_le) *value = gen_le(c, left, right); else if(name == c->str_ge) *value = gen_ge(c, left, right); else if(name == c->str_gt) *value = gen_gt(c, left, right); else return false; return true; }
void predicate_image_satqe( message_handlert &message_handler, const std::vector<exprt> &deref_curr_predicates, const std::vector<exprt> &deref_next_predicates, const std::list<exprt> &constraints, symex_target_equationt &equation, const namespacet &ns, abstract_transition_relationt & abstract_transition_relation) { const std::set<unsigned> &from_predicates= abstract_transition_relation.from_predicates; const std::set<unsigned> &to_predicates= abstract_transition_relation.to_predicates; assert(to_predicates.size()!=0); // create SAT solver object satqe_satcheckt satqe; bv_pointerst solver(satqe); solver.unbounded_array=boolbvt::U_ALL; solver.set_message_handler(message_handler); // turn equation into CNF equation.convert(solver); for(std::set<unsigned>::const_iterator it=from_predicates.begin(); it!=from_predicates.end(); it++) { unsigned i=*it; literalt li=make_pos(ns, solver, deref_curr_predicates[i]); satqe.quantify(li); } for(std::set<unsigned>::const_iterator it=to_predicates.begin(); it!=to_predicates.end(); it++) { unsigned i=*it; literalt lo=make_pos(ns, solver, deref_next_predicates[i]); satqe.quantify(lo); } // we want cubes cube_sett cube_set; satqe.set_cube_set(cube_set); // solve it switch(solver.dec_solve()) { case decision_proceduret::D_UNSATISFIABLE: // OK, this is what we expect break; default: throw "unexpected result from satqe.solve()"; } message_handler.print(9, "Generated "+ i2string(cube_set.no_insertions())+" cube(s)"); #if 0 std::cout << cube_set; #endif exprt constraint_cubes_disj = true_exprt(); // convert the cubes into constraints for(cubest::star_mapt::const_iterator it=cube_set.star_map.begin(); it!=cube_set.star_map.end(); it++) { for(cubest::bitssett::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++) { exprt constraint_cube_conj; unsigned bit=0; unsigned i=0; /* Assume it->first[i] is true iff the i-th predicate is in the cube. Assume predicates are stored in it->first in the order of from_predicates followed by to_predicates. Scan it->first and from/to_predicates in parallel to get the cube. */ for(std::set<unsigned>::const_iterator it3=from_predicates.begin(); it3!=from_predicates.end(); it3++) { unsigned id=*it3; if(!it->first[i]) { constraint_cube_conj.operands().push_back(exprt()); exprt &e=constraint_cube_conj.operands().back(); e=exprt(ID_predicate_symbol, typet(ID_bool)); e.set(ID_identifier, id); if(!(*it2)[bit]) e.make_not(); bit++; #if 0 std::cout << "C: " << from_expr(ns, "", e) << std::endl; #endif } i++; } for(std::set<unsigned>::const_iterator it3=to_predicates.begin(); it3!=to_predicates.end(); it3++) { unsigned id=*it3; if(!it->first[i]) { constraint_cube_conj.operands().push_back(exprt()); exprt &e=constraint_cube_conj.operands().back(); e=exprt(ID_predicate_next_symbol, typet(ID_bool)); e.set(ID_identifier, id); if(!(*it2)[bit]) e.make_not(); bit++; #if 0 std::cout << "C: " << from_expr(ns, "", e) << std::endl; #endif } i++; } assert(i==it->first.size()); /* Convert the cube into a conjunct. */ gen_and(constraint_cube_conj); /* Add the conjunct in disjunction to previous cubes. */ if(constraint_cubes_disj.is_true()) constraint_cubes_disj=constraint_cube_conj; else constraint_cubes_disj=gen_or( constraint_cubes_disj, constraint_cube_conj); } } /* Add the cubes to the contraints of the abstract transition relation. Warning: we may want to remove old constrains. */ abstract_transition_relation.constraints.push_back(constraint_cubes_disj); }
bool transition_refinert::check_assignment_transition( const predicatest &predicates, const abstract_stept &abstract_state_from, const abstract_stept &abstract_state_to, unsigned passive_id) { // Note that we take "thread_nr" from "abstract_state_from", not from "abstract_state_to", as the "from" state determines which thread is executing const unsigned active_id=abstract_state_from.thread_nr; const unsigned num_threads=abstract_state_from.thread_states.size(); std::vector<predicatest> active_passive_preds(num_threads, predicatest()); std::vector<std::vector<exprt> > predicates_wp(num_threads, std::vector<exprt>()); std::list<exprt> constraints; for(unsigned int t=0; t < num_threads; ++t) { if(active_id!=t && passive_id < num_threads && t!=passive_id) continue; for(unsigned int i = 0; i < predicates.size(); i++) { active_passive_preds[t].lookup(active_id==t? predicates[i] : predicatest::make_expr_passive(predicates[i], concrete_model.ns, t)); } assert(active_passive_preds[t].size() == predicates.size()); std::list<exprt> constraints_t; build_equation( concrete_model.ns, active_passive_preds[t], abstract_state_from.pc->code.concrete_pc, constraints_t, predicates_wp[t]); constraints.splice(constraints.end(), constraints_t); } // create SAT solver object satcheckt satcheck; bv_pointerst solver(concrete_model.ns, satcheck); solver.unbounded_array=boolbvt::U_NONE; // convert constraints for(std::list<exprt>::const_iterator it=constraints.begin(); it!=constraints.end(); it++) { exprt tmp(*it); solver.set_to_true(tmp); } abstract_transition_relationt &abstract_transition_relation= abstract_state_from.pc->code.get_transition_relation(); std::vector<std::vector<literalt> > predicate_variables_from(num_threads, std::vector<literalt>(predicates.size(), literalt())), predicate_variables_to(num_threads, std::vector<literalt>(predicates.size(), literalt())); bvt assumptions; std::vector<abstract_stept::thread_to_predicate_valuest::const_iterator> from_predicates(num_threads, abstract_state_from.thread_states.end()), to_predicates(num_threads, abstract_state_to.thread_states.end()); for(unsigned int t=0; t < num_threads; ++t) { from_predicates[t]=abstract_state_from.thread_states.find(t); assert(abstract_state_from.thread_states.end() != from_predicates[t]); to_predicates[t]=abstract_state_to.thread_states.find(t); assert(abstract_state_to.thread_states.end() != to_predicates[t]); } // we use all predicates in order to also find constraints over invalid // from/to states for(unsigned i=0; i < predicates.size(); ++i) { assert(abstract_transition_relation.to_predicates.find(i) != abstract_transition_relation.to_predicates.end() || abstract_transition_relation.from_predicates.find(i) != abstract_transition_relation.from_predicates.end() || (from_predicates[active_id]->second[i] == to_predicates[active_id]->second[i] && (passive_id >= num_threads || from_predicates[passive_id]->second[i] == to_predicates[passive_id]->second[i]))); for(unsigned int t=0; t < num_threads; ++t) { if(active_id!=t && passive_id < num_threads && t!=passive_id) continue; // not sure whether we really want the following check if(active_id!=t && active_passive_preds[t][i]==predicates[i]) continue; literalt li=make_pos(concrete_model.ns, solver, active_passive_preds[t][i]); predicate_variables_from[t][i]=li; assumptions.push_back(li.cond_negation( !from_predicates[t]->second[i])); #ifdef DEBUG const std::string predname= (active_id==t?"P#":"PP"+i2string(t)+"#")+i2string(i); std::cerr << "F: " << predname << ": " << (from_predicates[t]->second[i]?"":"!") << "(" << from_expr(concrete_model.ns, "", active_passive_preds[t][i]) << ")" << std::endl; #endif literalt lo=make_pos(concrete_model.ns, solver, predicates_wp[t][i]); predicate_variables_to[t][i]=lo; assumptions.push_back(lo.cond_negation( !to_predicates[t]->second[i])); #ifdef DEBUG std::cerr << "T: " << predname << ": " << (to_predicates[t]->second[i]?"":"!") << "(" << from_expr(concrete_model.ns, "", predicates_wp[t][i]) << ")" << std::endl; #endif } } satcheck.set_assumptions(assumptions); // solve it if(is_satisfiable(solver)) { print(9, "Transition is OK"); #ifdef DEBUG std::cout << "********\n"; solver.print_assignment(std::cout); std::cout << "********\n"; #endif return false; // ok } if(passive_id >= num_threads) { const std::string opt="Spurious assignment transitions requiring more than 1 passive thread"; assert(stats.find(opt)!=stats.end()); ++(stats[opt].val); return false; // can't do anything } print(9, "Assignment transition is spurious, refining"); exprt constraint; for(unsigned i=0; i < predicates.size(); ++i) { if(satcheck.is_in_conflict(predicate_variables_from[active_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_predicate_symbol, bool_typet()); e.set(ID_identifier, i); if(from_predicates[active_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-F: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(passive_id!=active_id && satcheck.is_in_conflict(predicate_variables_from[passive_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_predicate_passive_symbol, bool_typet()); e.set(ID_identifier, i); if(from_predicates[passive_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-F: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(satcheck.is_in_conflict(predicate_variables_to[active_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_predicate_next_symbol, bool_typet()); e.set(ID_identifier, i); if(to_predicates[active_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-T: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(passive_id!=active_id && satcheck.is_in_conflict(predicate_variables_to[passive_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_next_symbol, bool_typet()); e.operands().resize(1); e.op0()=exprt(ID_predicate_passive_symbol, bool_typet()); e.op0().set(ID_identifier, i); if(to_predicates[passive_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-T: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } } #ifdef DEBUG ::std::cerr << "Spurious in thread " << passive_id << " (active: " << abstract_state_from.thread_nr << "): " << ::std::endl; ::std::cerr << abstract_state_from << ::std::endl; goto_programt tmp; tmp.output_instruction(concrete_model.ns, "", std::cerr, abstract_state_from.pc->code.concrete_pc); ::std::cerr << abstract_state_to << ::std::endl; #endif if(constraint.operands().empty()) constraint.make_false(); // this can happen if else // the invariants are inconsistent gen_or(constraint); abstract_transition_relation.constraints.push_back(constraint); // spurious! return true; }
static bool special_case_operator(compile_t* c, ast_t* ast, LLVMValueRef *value, bool short_circuit, bool native128) { AST_GET_CHILDREN(ast, postfix, positional, named, question); AST_GET_CHILDREN(postfix, left, method); ast_t* right = ast_child(positional); const char* name = ast_name(method); bool special_case = true; *value = NULL; codegen_debugloc(c, ast); if(name == c->str_add) *value = gen_add(c, left, right, true); else if(name == c->str_sub) *value = gen_sub(c, left, right, true); else if((name == c->str_mul) && native128) *value = gen_mul(c, left, right, true); else if((name == c->str_div) && native128) *value = gen_div(c, left, right, true); else if((name == c->str_rem) && native128) *value = gen_rem(c, left, right, true); else if(name == c->str_neg) *value = gen_neg(c, left, true); else if(name == c->str_add_unsafe) *value = gen_add(c, left, right, false); else if(name == c->str_sub_unsafe) *value = gen_sub(c, left, right, false); else if((name == c->str_mul_unsafe) && native128) *value = gen_mul(c, left, right, false); else if((name == c->str_div_unsafe) && native128) *value = gen_div(c, left, right, false); else if((name == c->str_rem_unsafe) && native128) *value = gen_rem(c, left, right, false); else if(name == c->str_neg_unsafe) *value = gen_neg(c, left, false); else if((name == c->str_and) && short_circuit) *value = gen_and_sc(c, left, right); else if((name == c->str_or) && short_circuit) *value = gen_or_sc(c, left, right); else if((name == c->str_and) && !short_circuit) *value = gen_and(c, left, right); else if((name == c->str_or) && !short_circuit) *value = gen_or(c, left, right); else if(name == c->str_xor) *value = gen_xor(c, left, right); else if(name == c->str_not) *value = gen_not(c, left); else if(name == c->str_shl) *value = gen_shl(c, left, right, true); else if(name == c->str_shr) *value = gen_shr(c, left, right, true); else if(name == c->str_shl_unsafe) *value = gen_shl(c, left, right, false); else if(name == c->str_shr_unsafe) *value = gen_shr(c, left, right, false); else if(name == c->str_eq) *value = gen_eq(c, left, right, true); else if(name == c->str_ne) *value = gen_ne(c, left, right, true); else if(name == c->str_lt) *value = gen_lt(c, left, right, true); else if(name == c->str_le) *value = gen_le(c, left, right, true); else if(name == c->str_ge) *value = gen_ge(c, left, right, true); else if(name == c->str_gt) *value = gen_gt(c, left, right, true); else if(name == c->str_eq_unsafe) *value = gen_eq(c, left, right, false); else if(name == c->str_ne_unsafe) *value = gen_ne(c, left, right, false); else if(name == c->str_lt_unsafe) *value = gen_lt(c, left, right, false); else if(name == c->str_le_unsafe) *value = gen_le(c, left, right, false); else if(name == c->str_ge_unsafe) *value = gen_ge(c, left, right, false); else if(name == c->str_gt_unsafe) *value = gen_gt(c, left, right, false); else special_case = false; codegen_debugloc(c, NULL); return special_case; }