z3::expr operator()(const z3::expr& v1, const z3::expr& v2) { z3::context& ctxt = v1.ctx(); z3::expr zero(ctxt.bv_val(0, v1.get_sort().bv_size())); z3::expr guard(v2 == zero); z3::expr ans(ctxt, Z3_mk_bvsrem(ctxt, v1, v2)); return z3::expr(ctxt, Z3_mk_ite(ctxt, guard, zero, ans)); }
z3::expr ite(z3::expr const & c, z3::expr const & t, z3::expr const & e) { check_context(c, t); check_context(c, e); assert(c.is_bool()); Z3_ast r = Z3_mk_ite(c.ctx(), c, t, e); c.check_error(); return z3::expr(c.ctx(), r); }
bool ModelValidator::isValid(z3::expr smt_expr, const std::vector<double>& model) { auto var_symbols = m_ir_gen->getVars(); assert((var_symbols.size() == model.size()) && "Model size mismatch!"); // now substituting fpa wrapped variables with consts from model z3::expr_vector src_1(smt_expr.ctx()), dst_1(smt_expr.ctx()); for (const auto& symbol_pair:m_ir_gen->getVarsFPAWrapped()) { src_1.push_back(*symbol_pair.first->expr()); // XXX: assuming TO_FPA should invert type casting auto kind = symbol_pair.second->kind() == SymbolKind::kFP32Var ? SymbolKind::kFP64Var : SymbolKind::kFP32Var; dst_1.push_back(genFPConst(smt_expr, kind, symbol_pair.second->id(), model)); } z3::expr expr_sub_1 = smt_expr.substitute(src_1, dst_1); // now substituting actual variables with consts from model z3::expr_vector src_2(smt_expr.ctx()), dst_2(smt_expr.ctx()); for (const auto symbol:var_symbols) { src_2.push_back(*symbol->expr()); dst_2.push_back(genFPConst(smt_expr, symbol->kind(), symbol->id(), model)); } z3::expr expr_sub_2 = expr_sub_1.substitute(src_2, dst_2); z3::solver solver(smt_expr.ctx()); solver.add(expr_sub_2); return solver.check() == z3::check_result::sat; }
hb_ptr integer::get_hb(const z3::expr& hb, bool allow_equal) const { bool possibly_equal = false; bool is_partial = false; z3::expr hb_p = hb; if( z3.is_implies( hb ) ) { hb_p = hb.arg(1); } if( z3.is_bool_const( hb_p ) ) { auto it = current_rf_map.find( z3.get_top_func_name( hb_p ) ); if( it != current_rf_map.end() ) { return it->second; } } auto p = get_locs(hb, possibly_equal, is_partial); integer::mapit loc1 = p.first, loc2 = p.second, end = tstamp_lookup.end(); if( (!possibly_equal || allow_equal || is_partial) && loc1!=end && loc2!=end){ hb_enc::tstamp_ptr l1 = get<1>(*loc1); hb_enc::tstamp_ptr l2 = get<1>(*loc2); se_ptr e1; if( event_lookup.find( l1->expr ) != event_lookup.end() ) e1 = event_lookup.at( l1->expr ); se_ptr e2; if( event_lookup.find( l2->expr ) != event_lookup.end() ) e2 = event_lookup.at( l2->expr ); if( is_partial ){ return shared_ptr<hb_enc::hb>(new hb_enc::hb( e1, l1, e2, l2, hb, possibly_equal,is_partial)); }else{ return shared_ptr<hb_enc::hb>(new hb_enc::hb(e1, l1, e2, l2, hb, possibly_equal)); } } else return shared_ptr<hb_enc::hb>(); }
z3::expr ModelValidator::genFPConst(z3::expr expr, SymbolKind kind, unsigned id, const std::vector<double>& model) const noexcept { if (kind == SymbolKind::kFP32Var) { auto var_ast = Z3_mk_fpa_numeral_float(expr.ctx(), static_cast<float>(model[id]), Z3_mk_fpa_sort_32(expr.ctx())); return z3::to_expr(expr.ctx(), var_ast); } else { assert(kind == SymbolKind::kFP64Var && "Bad variable kind!"); //TODO: handle FP16 and FP128 constants auto var_ast = Z3_mk_fpa_numeral_double(expr.ctx(), model[id], Z3_mk_fpa_sort_64(expr.ctx())); return z3::to_expr(expr.ctx(), var_ast); } }
pair<integer::mapit,integer::mapit> integer::get_locs( const z3::expr& hb, bool& possibly_equal, bool& is_partial ) const { // we need to flip that bool parameter in to know if we are sure about // this result or not (two tstamps can be assigned an equal integer) auto loc1 = tstamp_lookup.end(); auto loc2 = tstamp_lookup.end(); switch(hb.kind()) { case Z3_APP_AST: { z3::func_decl d = hb.decl(); Z3_decl_kind dk = d.decl_kind(); switch(dk) { case Z3_OP_LE: possibly_equal = true; // fallthrough case Z3_OP_LT: if (hb.arg(1).kind() == Z3_NUMERAL_AST) return get_locs(hb.arg(0), possibly_equal, is_partial); loc1 = tstamp_lookup.find(hb.arg(0)); loc2 = tstamp_lookup.find(hb.arg(1)); break; case Z3_OP_GE: possibly_equal = true; // fallthrough case Z3_OP_GT: if (hb.arg(1).kind() == Z3_NUMERAL_AST) { return swap_pair(get_locs(hb.arg(0), possibly_equal, is_partial)); } loc1 = tstamp_lookup.find(hb.arg(1)); loc2 = tstamp_lookup.find(hb.arg(0)); break; case Z3_OP_NOT: { auto neg_hb = get_locs(hb.arg(0), possibly_equal, is_partial); auto res = swap_pair( neg_hb ); possibly_equal = !possibly_equal; return res; break; } case Z3_OP_ADD: { loc1 = tstamp_lookup.find(hb.arg(0)); z3::expr t1 = hb.arg(1); if (t1.decl().decl_kind() == Z3_OP_MUL) { // todo: check the the other multiplicant is -1 loc2 = tstamp_lookup.find(t1.arg(1)); } break; } case Z3_OP_SPECIAL_RELATION_PO: { is_partial = true; loc1 = tstamp_lookup.find(hb.arg(0)); loc2 = tstamp_lookup.find(hb.arg(1)); break; } default: break; } break; } default: break; } return make_pair<integer::mapit,integer::mapit>(std::move(loc1),std::move(loc2)); }
static z3::expr insert(z3::expr set, unsigned element) { z3::context& context = set.ctx(); return z3::store(set, context.int_val(element), context.bool_val(true)); }
z3::expr operator()(const z3::expr& v1, const z3::expr& v2) { return z3::expr(v1.ctx(), Z3_mk_bvule(v1.ctx(), v1, v2)); }
pair<integer::mapit,integer::mapit> integer::get_locs(const z3::expr& hb, bool& possibly_equal) const { // we need to flip that bool parameter in to know if we are sure about this result or not (two locations can be assigned an equal integer) auto loc1 = location_lookup.end(); auto loc2 = location_lookup.end(); switch(hb.kind()) { case Z3_APP_AST: { z3::func_decl d = hb.decl(); Z3_decl_kind dk = d.decl_kind(); switch(dk) { case Z3_OP_LE: possibly_equal = true; // fallthrough case Z3_OP_LT: if (hb.arg(1).kind() == Z3_NUMERAL_AST) return get_locs(hb.arg(0), possibly_equal); loc1 = location_lookup.find(hb.arg(0)); loc2 = location_lookup.find(hb.arg(1)); break; case Z3_OP_GE: possibly_equal = true; // fallthrough case Z3_OP_GT: if (hb.arg(1).kind() == Z3_NUMERAL_AST) { return swap_pair(get_locs(hb.arg(0), possibly_equal)); } loc1 = location_lookup.find(hb.arg(1)); loc2 = location_lookup.find(hb.arg(0)); break; case Z3_OP_NOT: { auto res = swap_pair(get_locs(hb.arg(0), possibly_equal)); possibly_equal = !possibly_equal; return res; break; } case Z3_OP_ADD: { loc1 = location_lookup.find(hb.arg(0)); z3::expr t1 = hb.arg(1); if (t1.decl().decl_kind() == Z3_OP_MUL) { loc2 = location_lookup.find(t1.arg(1)); } } default: break; } break; } default: break; } return make_pair<integer::mapit,integer::mapit>(std::move(loc1),std::move(loc2)); }