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));
 }
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
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>();
}
Beispiel #5
0
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);
    }
}
Beispiel #6
0
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));
}
Beispiel #7
0
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));
 }
Beispiel #9
0
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));
}