-
Notifications
You must be signed in to change notification settings - Fork 274
Conversion of bitwise exprt
s to SMT terms in new SMT backend
#6676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1ffb405
8b35bf7
f09c9f9
f6a832f
67c2503
98783da
0652b4e
05e1fd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,47 @@ | |
#include <functional> | ||
#include <numeric> | ||
|
||
/// \brief Converts operator expressions with 2 or more operands to terms | ||
/// expressed as binary operator application. | ||
/// \param expr: The expression to convert. | ||
/// \param factory: The factory function which makes applications of the | ||
/// relevant smt term, when applied to the term operands. | ||
/// \details The conversion used is left associative for instances with 3 or | ||
/// more operands. The SMT standard / core theory version 2.6 actually | ||
/// supports applying the `and`, `or` and `xor` to 3 or more operands. | ||
/// However our internal `smt_core_theoryt` does not support this currently | ||
/// and converting to binary application has the advantage of making the order | ||
/// of evaluation explicit. | ||
template <typename factoryt> | ||
static smt_termt convert_multiary_operator_to_terms( | ||
const multi_ary_exprt &expr, | ||
const factoryt &factory) | ||
{ | ||
PRECONDITION(expr.operands().size() >= 2); | ||
const auto operand_terms = | ||
make_range(expr.operands()).map([](const exprt &expr) { | ||
return convert_expr_to_smt(expr); | ||
}); | ||
return std::accumulate( | ||
++operand_terms.begin(), | ||
operand_terms.end(), | ||
*operand_terms.begin(), | ||
factory); | ||
} | ||
|
||
/// \brief Ensures that all operands of the argument expression have related | ||
/// types. | ||
/// \param expr: The expression of which the operands we evaluate for type | ||
/// equality. | ||
template <typename target_typet> | ||
static bool operands_are_of_type(const exprt &expr) | ||
{ | ||
return std::all_of( | ||
expr.operands().cbegin(), expr.operands().cend(), [](const exprt &operand) { | ||
return can_cast_type<target_typet>(operand.type()); | ||
}); | ||
} | ||
|
||
static smt_sortt convert_type_to_smt_sort(const bool_typet &type) | ||
{ | ||
return smt_bool_sortt{}; | ||
|
@@ -126,30 +167,64 @@ static smt_termt convert_expr_to_smt(const concatenation_exprt &concatenation) | |
|
||
static smt_termt convert_expr_to_smt(const bitand_exprt &bitwise_and_expr) | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise and expression: " + | ||
bitwise_and_expr.pretty()); | ||
if(operands_are_of_type<integer_bitvector_typet>(bitwise_and_expr)) | ||
{ | ||
return convert_multiary_operator_to_terms( | ||
bitwise_and_expr, smt_bit_vector_theoryt::make_and); | ||
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise and expression: " + | ||
bitwise_and_expr.pretty()); | ||
} | ||
} | ||
|
||
static smt_termt convert_expr_to_smt(const bitor_exprt &bitwise_or_expr) | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise or expression: " + | ||
bitwise_or_expr.pretty()); | ||
if(operands_are_of_type<integer_bitvector_typet>(bitwise_or_expr)) | ||
{ | ||
return convert_multiary_operator_to_terms( | ||
bitwise_or_expr, smt_bit_vector_theoryt::make_or); | ||
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise or expression: " + | ||
bitwise_or_expr.pretty()); | ||
} | ||
} | ||
|
||
static smt_termt convert_expr_to_smt(const bitxor_exprt &bitwise_xor) | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise xor expression: " + | ||
bitwise_xor.pretty()); | ||
if(operands_are_of_type<integer_bitvector_typet>(bitwise_xor)) | ||
{ | ||
return convert_multiary_operator_to_terms( | ||
bitwise_xor, smt_bit_vector_theoryt::make_xor); | ||
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise xor expression: " + | ||
bitwise_xor.pretty()); | ||
} | ||
} | ||
|
||
static smt_termt convert_expr_to_smt(const bitnot_exprt &bitwise_not) | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for bitwise not expression: " + | ||
bitwise_not.pretty()); | ||
const bool operand_is_bitvector = | ||
can_cast_type<integer_bitvector_typet>(bitwise_not.op().type()); | ||
|
||
if(operand_is_bitvector) | ||
{ | ||
return smt_bit_vector_theoryt::make_not( | ||
convert_expr_to_smt(bitwise_not.op())); | ||
thomasspriggs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🐸 |
||
"Generation of SMT formula for bitnot_exprt: " + bitwise_not.pretty()); | ||
} | ||
} | ||
|
||
static smt_termt convert_expr_to_smt(const unary_minus_exprt &unary_minus) | ||
|
@@ -191,34 +266,6 @@ static smt_termt convert_expr_to_smt(const if_exprt &if_expression) | |
convert_expr_to_smt(if_expression.false_case())); | ||
} | ||
|
||
/// \brief Converts operator expressions with 2 or more operands to terms | ||
/// expressed as binary operator application. | ||
/// \param expr: The expression to convert. | ||
/// \param factory: The factory function which makes applications of the | ||
/// relevant smt term, when applied to the term operands. | ||
/// \details The conversion used is left associative for instances with 3 or | ||
/// more operands. The SMT standard / core theory version 2.6 actually | ||
/// supports applying the `and`, `or` and `xor` to 3 or more operands. | ||
/// However our internal `smt_core_theoryt` does not support this currently | ||
/// and converting to binary application has the advantage of making the order | ||
/// of evaluation explicit. | ||
template <typename factoryt> | ||
static smt_termt convert_multiary_operator_to_terms( | ||
const multi_ary_exprt &expr, | ||
const factoryt &factory) | ||
{ | ||
PRECONDITION(expr.operands().size() >= 2); | ||
const auto operand_terms = | ||
make_range(expr.operands()).map([](const exprt &expr) { | ||
return convert_expr_to_smt(expr); | ||
}); | ||
return std::accumulate( | ||
++operand_terms.begin(), | ||
operand_terms.end(), | ||
*operand_terms.begin(), | ||
factory); | ||
} | ||
|
||
static smt_termt convert_expr_to_smt(const and_exprt &and_expression) | ||
{ | ||
return convert_multiary_operator_to_terms( | ||
|
@@ -498,9 +545,32 @@ static smt_termt convert_expr_to_smt(const index_exprt &index) | |
|
||
static smt_termt convert_expr_to_smt(const shift_exprt &shift) | ||
{ | ||
// TODO: split into functions for separate types of shift including rotate. | ||
UNIMPLEMENTED_FEATURE( | ||
"Generation of SMT formula for shift expression: " + shift.pretty()); | ||
// TODO: Dispatch into different types of shifting | ||
const auto &first_operand = shift.op0(); | ||
const auto &second_operand = shift.op1(); | ||
|
||
if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift)) | ||
{ | ||
return smt_bit_vector_theoryt::shift_left( | ||
convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand)); | ||
} | ||
else if( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 If you get rid of the unneeded |
||
const auto right_logical_shift = expr_try_dynamic_cast<lshr_exprt>(shift)) | ||
{ | ||
return smt_bit_vector_theoryt::logical_shift_right( | ||
convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand)); | ||
} | ||
else if( | ||
const auto right_arith_shift = expr_try_dynamic_cast<ashr_exprt>(shift)) | ||
{ | ||
return smt_bit_vector_theoryt::arithmetic_shift_right( | ||
convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand)); | ||
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🐸 |
||
"Generation of SMT formula for shift expression: " + shift.pretty()); | ||
} | ||
} | ||
|
||
static smt_termt convert_expr_to_smt(const with_exprt &with) | ||
|
Uh oh!
There was an error while loading. Please reload this page.