3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-02 09:20:22 +00:00

Implement proposed smtlib2 bitvector overflow predicates (#6715)

* Logical names for function declarations in c++

Currently, for example, the function declaration symbol member for
checking whether multiplication *does not* overflow is called
`m_bv_smul_ovfl`.  Since we are introducing the upcoming smtlib2 symbols
that check that multpliciation *does* overflow, the not overflow check
symbols are renamed to `m_bv_smul_no_ovfl` etc.

* Implement smtlib overflow preds for multiplication

Smtlib2 is being extended to include overflow predicates for bit
vectors (see https://groups.google.com/u/1/g/smt-lib/c/J4D99wT0aKI).
This commit introduces the predicates `bvumulo` and `bvsmulo` that
return `true` if the unsigned multiplication overflows or the signed
multiplication underflows or overflows, respectively.

* Move mul overflow predicates to BV logic

* Add a todo on illogical argument order

* Implement mk_unary_pred for bv

* Implement bvnego

* Implement bvuaddo

* Implement bvsaddo

* Implement bvusubo

* Implement bvssubo

* Implement bvsdivo
This commit is contained in:
Antti Hyvärinen 2023-05-09 19:37:46 +02:00 committed by GitHub
parent 62e1ec0698
commit 12e45c9d17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 222 additions and 7 deletions

View file

@ -118,9 +118,22 @@ void bv_decl_plugin::finalize() {
DEC_REF(m_bv_redand);
DEC_REF(m_bv_comp);
DEC_REF(m_bv_mul_no_ovfl);
DEC_REF(m_bv_smul_no_ovfl);
DEC_REF(m_bv_smul_no_udfl);
DEC_REF(m_bv_mul_ovfl);
DEC_REF(m_bv_smul_ovfl);
DEC_REF(m_bv_smul_udfl);
DEC_REF(m_bv_neg_ovfl);
DEC_REF(m_bv_uadd_ovfl);
DEC_REF(m_bv_sadd_ovfl);
DEC_REF(m_bv_usub_ovfl);
DEC_REF(m_bv_ssub_ovfl);
DEC_REF(m_bv_sdiv_ovfl);
DEC_REF(m_bv_shl);
DEC_REF(m_bv_lshr);
@ -245,6 +258,16 @@ func_decl * bv_decl_plugin::mk_bv2int(unsigned bv_size, unsigned num_parameters,
return m_bv2int[bv_size];
}
func_decl * bv_decl_plugin::mk_unary_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size) {
force_ptr_array_size(decls, bv_size+1);
if (decls[bv_size] == 0) {
decls[bv_size] = m_manager->mk_func_decl(symbol(name), get_bv_sort(bv_size), m_manager->mk_bool_sort(), func_decl_info(m_family_id, k));
m_manager->inc_ref(decls[bv_size]);
}
return decls[bv_size];
}
func_decl * bv_decl_plugin::mk_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size) {
force_ptr_array_size(decls, bv_size + 1);
@ -289,6 +312,7 @@ func_decl * bv_decl_plugin::mk_comp(unsigned bv_size) {
func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned bv_size) {
switch (k) {
case OP_BNEG: return mk_unary(m_bv_neg, k, "bvneg", bv_size);
case OP_BNEG_OVFL: return mk_unary_pred(m_bv_neg_ovfl, k, "bvnego", bv_size);
case OP_BADD: return mk_binary(m_bv_add, k, "bvadd", bv_size, true);
case OP_BSUB: return mk_binary(m_bv_sub, k, "bvsub", bv_size, false);
case OP_BMUL: return mk_binary(m_bv_mul, k, "bvmul", bv_size, true);
@ -327,9 +351,16 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned bv_size) {
case OP_BREDOR: return mk_reduction(m_bv_redor, k, "bvredor", bv_size);
case OP_BREDAND: return mk_reduction(m_bv_redand, k, "bvredand", bv_size);
case OP_BCOMP: return mk_comp(bv_size);
case OP_BUMUL_NO_OVFL: return mk_pred(m_bv_mul_ovfl, k, "bvumul_noovfl", bv_size);
case OP_BSMUL_NO_OVFL: return mk_pred(m_bv_smul_ovfl, k, "bvsmul_noovfl", bv_size);
case OP_BSMUL_NO_UDFL: return mk_pred(m_bv_smul_udfl, k, "bvsmul_noudfl", bv_size);
case OP_BUMUL_NO_OVFL: return mk_pred(m_bv_mul_no_ovfl, k, "bvumul_noovfl", bv_size);
case OP_BSMUL_NO_OVFL: return mk_pred(m_bv_smul_no_ovfl, k, "bvsmul_noovfl", bv_size);
case OP_BSMUL_NO_UDFL: return mk_pred(m_bv_smul_no_udfl, k, "bvsmul_noudfl", bv_size);
case OP_BUMUL_OVFL: return mk_pred(m_bv_mul_ovfl, k, "bvumulo", bv_size);
case OP_BSMUL_OVFL: return mk_pred(m_bv_smul_ovfl, k, "bvsmulo", bv_size);
case OP_BSDIV_OVFL: return mk_pred(m_bv_sdiv_ovfl, k, "bvsdivo", bv_size);
case OP_BUADD_OVFL: return mk_pred(m_bv_uadd_ovfl, k, "bvuaddo", bv_size);
case OP_BSADD_OVFL: return mk_pred(m_bv_sadd_ovfl, k, "bvsaddo", bv_size);
case OP_BUSUB_OVFL: return mk_pred(m_bv_usub_ovfl, k, "bvusubo", bv_size);
case OP_BSSUB_OVFL: return mk_pred(m_bv_ssub_ovfl, k, "bvssubo", bv_size);
case OP_BSHL: return mk_binary(m_bv_shl, k, "bvshl", bv_size, false);
case OP_BLSHR: return mk_binary(m_bv_lshr, k, "bvlshr", bv_size, false);
@ -681,10 +712,18 @@ void bv_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
op_names.push_back(builtin_name("bit1",OP_BIT1));
op_names.push_back(builtin_name("bit0",OP_BIT0));
op_names.push_back(builtin_name("bvneg",OP_BNEG));
op_names.push_back(builtin_name("bvnego", OP_BNEG_OVFL));
op_names.push_back(builtin_name("bvadd",OP_BADD));
op_names.push_back(builtin_name("bvuaddo",OP_BUADD_OVFL));
op_names.push_back(builtin_name("bvsaddo",OP_BSADD_OVFL));
op_names.push_back(builtin_name("bvsub",OP_BSUB));
op_names.push_back(builtin_name("bvusubo",OP_BUSUB_OVFL));
op_names.push_back(builtin_name("bvssubo",OP_BSSUB_OVFL));
op_names.push_back(builtin_name("bvmul",OP_BMUL));
op_names.push_back(builtin_name("bvumulo",OP_BUMUL_OVFL));
op_names.push_back(builtin_name("bvsmulo",OP_BSMUL_OVFL));
op_names.push_back(builtin_name("bvsdiv",OP_BSDIV));
op_names.push_back(builtin_name("bvsdivo",OP_BSDIV_OVFL));
op_names.push_back(builtin_name("bvudiv",OP_BUDIV));
op_names.push_back(builtin_name("bvsrem",OP_BSREM));
op_names.push_back(builtin_name("bvurem",OP_BUREM));