LLVMValueRef gen_and_assign(struct node *ast) { LLVMValueRef result; result = gen_and(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_guarded_transition( const predicatest &predicates, const abstract_stept &abstract_state_from, unsigned passive_id, bool &inconsistent_initial_state) { // get the concrete basic block const goto_programt::instructiont &c_instruction= *abstract_state_from.pc->code.concrete_pc; if (!c_instruction.is_goto() && !c_instruction.is_assume()) return false; // whatever // this is the original guard exprt guard=c_instruction.guard; if(guard.is_true()) // boring return false; // we might need to negate it if the branch was not taken if (c_instruction.is_goto() && !abstract_state_from.branch_taken) guard.make_not(); abstract_transition_relationt &abstract_transition_relation= abstract_state_from.pc->code.get_transition_relation(); #ifdef SATCHECK_MINISAT2 satcheck_minisat_no_simplifiert satcheck; #else satcheckt satcheck; #endif bv_pointerst solver(concrete_model.ns, satcheck); solver.unbounded_array=boolbvt::U_NONE; // 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()); 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::vector<std::vector<literalt> > predicate_variables_from(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()); 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]); } // we use all predicates in order to also find constraints over invalid // from states for(unsigned i=0; i < predicates.size(); ++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 << "G-F: " << predname << ": " << (from_predicates[t]->second[i]?"":"!") << "(" << from_expr(concrete_model.ns, "", active_passive_preds[t][i]) << ")" << std::endl; #endif } } satcheck.set_assumptions(assumptions); if(!is_satisfiable(solver)) { if(passive_id >= num_threads) { const std::string opt="Invalid states requiring more than 1 passive thread"; assert(stats.find(opt)!=stats.end()); ++(stats[opt].val); } inconsistent_initial_state = true; print(9, "Guarded transition spurious due to invalid abstract state"); return false; // this has to be fixed in the respective assignment } // now add the guard solver.set_to_true(guard); // solve it incrementally 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 guard transitions requiring more than 1 passive thread"; assert(stats.find(opt)!=stats.end()); ++(stats[opt].val); return false; // can't do anything } print(9, "Guarded transition is spurious, refining"); exprt condition; for(unsigned i=0; i < predicates.size(); ++i) { if(satcheck.is_in_conflict(predicate_variables_from[active_id][i])) { condition.operands().push_back(exprt()); exprt &e=condition.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 << "G-C: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(passive_id!=active_id && satcheck.is_in_conflict(predicate_variables_from[passive_id][i])) { condition.operands().push_back(exprt()); exprt &e=condition.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 << "G-C-F: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } } gen_and(condition); if(c_instruction.is_goto()) { bool neg=abstract_state_from.branch_taken; constrain_goto_transition(abstract_transition_relation, condition, neg); } else { assert(c_instruction.is_assume()); constrain_assume_transition(abstract_transition_relation, condition); } // 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; }