|
21 | 21 | #include <functional> |
22 | 22 | #include <numeric> |
23 | 23 |
|
| 24 | +/// \brief Converts operator expressions with 2 or more operands to terms |
| 25 | +/// expressed as binary operator application. |
| 26 | +/// \param expr: The expression to convert. |
| 27 | +/// \param factory: The factory function which makes applications of the |
| 28 | +/// relevant smt term, when applied to the term operands. |
| 29 | +/// \details The conversion used is left associative for instances with 3 or |
| 30 | +/// more operands. The SMT standard / core theory version 2.6 actually |
| 31 | +/// supports applying the `and`, `or` and `xor` to 3 or more operands. |
| 32 | +/// However our internal `smt_core_theoryt` does not support this currently |
| 33 | +/// and converting to binary application has the advantage of making the order |
| 34 | +/// of evaluation explicit. |
| 35 | +template <typename factoryt> |
| 36 | +static smt_termt convert_multiary_operator_to_terms( |
| 37 | + const multi_ary_exprt &expr, |
| 38 | + const factoryt &factory) |
| 39 | +{ |
| 40 | + PRECONDITION(expr.operands().size() >= 2); |
| 41 | + const auto operand_terms = |
| 42 | + make_range(expr.operands()).map([](const exprt &expr) { |
| 43 | + return convert_expr_to_smt(expr); |
| 44 | + }); |
| 45 | + return std::accumulate( |
| 46 | + ++operand_terms.begin(), |
| 47 | + operand_terms.end(), |
| 48 | + *operand_terms.begin(), |
| 49 | + factory); |
| 50 | +} |
| 51 | + |
| 52 | +/// \brief Ensures that all operands of the argument expression have related |
| 53 | +/// types. |
| 54 | +/// \param expr: The expression of which the operands we evaluate for type |
| 55 | +/// equality. |
| 56 | +template <typename target_typet> |
| 57 | +static bool operands_are_of_type(const exprt &expr) |
| 58 | +{ |
| 59 | + return std::all_of( |
| 60 | + expr.operands().cbegin(), expr.operands().cend(), [](const exprt &operand) { |
| 61 | + return can_cast_type<target_typet>(operand.type()); |
| 62 | + }); |
| 63 | +} |
| 64 | + |
24 | 65 | static smt_sortt convert_type_to_smt_sort(const bool_typet &type) |
25 | 66 | { |
26 | 67 | return smt_bool_sortt{}; |
@@ -126,30 +167,64 @@ static smt_termt convert_expr_to_smt(const concatenation_exprt &concatenation) |
126 | 167 |
|
127 | 168 | static smt_termt convert_expr_to_smt(const bitand_exprt &bitwise_and_expr) |
128 | 169 | { |
129 | | - UNIMPLEMENTED_FEATURE( |
130 | | - "Generation of SMT formula for bitwise and expression: " + |
131 | | - bitwise_and_expr.pretty()); |
| 170 | + if(operands_are_of_type<integer_bitvector_typet>(bitwise_and_expr)) |
| 171 | + { |
| 172 | + return convert_multiary_operator_to_terms( |
| 173 | + bitwise_and_expr, smt_bit_vector_theoryt::make_and); |
| 174 | + } |
| 175 | + else |
| 176 | + { |
| 177 | + UNIMPLEMENTED_FEATURE( |
| 178 | + "Generation of SMT formula for bitwise and expression: " + |
| 179 | + bitwise_and_expr.pretty()); |
| 180 | + } |
132 | 181 | } |
133 | 182 |
|
134 | 183 | static smt_termt convert_expr_to_smt(const bitor_exprt &bitwise_or_expr) |
135 | 184 | { |
136 | | - UNIMPLEMENTED_FEATURE( |
137 | | - "Generation of SMT formula for bitwise or expression: " + |
138 | | - bitwise_or_expr.pretty()); |
| 185 | + if(operands_are_of_type<integer_bitvector_typet>(bitwise_or_expr)) |
| 186 | + { |
| 187 | + return convert_multiary_operator_to_terms( |
| 188 | + bitwise_or_expr, smt_bit_vector_theoryt::make_or); |
| 189 | + } |
| 190 | + else |
| 191 | + { |
| 192 | + UNIMPLEMENTED_FEATURE( |
| 193 | + "Generation of SMT formula for bitwise or expression: " + |
| 194 | + bitwise_or_expr.pretty()); |
| 195 | + } |
139 | 196 | } |
140 | 197 |
|
141 | 198 | static smt_termt convert_expr_to_smt(const bitxor_exprt &bitwise_xor) |
142 | 199 | { |
143 | | - UNIMPLEMENTED_FEATURE( |
144 | | - "Generation of SMT formula for bitwise xor expression: " + |
145 | | - bitwise_xor.pretty()); |
| 200 | + if(operands_are_of_type<integer_bitvector_typet>(bitwise_xor)) |
| 201 | + { |
| 202 | + return convert_multiary_operator_to_terms( |
| 203 | + bitwise_xor, smt_bit_vector_theoryt::make_xor); |
| 204 | + } |
| 205 | + else |
| 206 | + { |
| 207 | + UNIMPLEMENTED_FEATURE( |
| 208 | + "Generation of SMT formula for bitwise xor expression: " + |
| 209 | + bitwise_xor.pretty()); |
| 210 | + } |
146 | 211 | } |
147 | 212 |
|
148 | 213 | static smt_termt convert_expr_to_smt(const bitnot_exprt &bitwise_not) |
149 | 214 | { |
150 | | - UNIMPLEMENTED_FEATURE( |
151 | | - "Generation of SMT formula for bitwise not expression: " + |
152 | | - bitwise_not.pretty()); |
| 215 | + const bool operand_is_bitvector = |
| 216 | + can_cast_type<integer_bitvector_typet>(bitwise_not.op().type()); |
| 217 | + |
| 218 | + if(operand_is_bitvector) |
| 219 | + { |
| 220 | + return smt_bit_vector_theoryt::make_not( |
| 221 | + convert_expr_to_smt(bitwise_not.op())); |
| 222 | + } |
| 223 | + else |
| 224 | + { |
| 225 | + UNIMPLEMENTED_FEATURE( |
| 226 | + "Generation of SMT formula for bitnot_exprt: " + bitwise_not.pretty()); |
| 227 | + } |
153 | 228 | } |
154 | 229 |
|
155 | 230 | 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) |
191 | 266 | convert_expr_to_smt(if_expression.false_case())); |
192 | 267 | } |
193 | 268 |
|
194 | | -/// \brief Converts operator expressions with 2 or more operands to terms |
195 | | -/// expressed as binary operator application. |
196 | | -/// \param expr: The expression to convert. |
197 | | -/// \param factory: The factory function which makes applications of the |
198 | | -/// relevant smt term, when applied to the term operands. |
199 | | -/// \details The conversion used is left associative for instances with 3 or |
200 | | -/// more operands. The SMT standard / core theory version 2.6 actually |
201 | | -/// supports applying the `and`, `or` and `xor` to 3 or more operands. |
202 | | -/// However our internal `smt_core_theoryt` does not support this currently |
203 | | -/// and converting to binary application has the advantage of making the order |
204 | | -/// of evaluation explicit. |
205 | | -template <typename factoryt> |
206 | | -static smt_termt convert_multiary_operator_to_terms( |
207 | | - const multi_ary_exprt &expr, |
208 | | - const factoryt &factory) |
209 | | -{ |
210 | | - PRECONDITION(expr.operands().size() >= 2); |
211 | | - const auto operand_terms = |
212 | | - make_range(expr.operands()).map([](const exprt &expr) { |
213 | | - return convert_expr_to_smt(expr); |
214 | | - }); |
215 | | - return std::accumulate( |
216 | | - ++operand_terms.begin(), |
217 | | - operand_terms.end(), |
218 | | - *operand_terms.begin(), |
219 | | - factory); |
220 | | -} |
221 | | - |
222 | 269 | static smt_termt convert_expr_to_smt(const and_exprt &and_expression) |
223 | 270 | { |
224 | 271 | return convert_multiary_operator_to_terms( |
@@ -498,9 +545,32 @@ static smt_termt convert_expr_to_smt(const index_exprt &index) |
498 | 545 |
|
499 | 546 | static smt_termt convert_expr_to_smt(const shift_exprt &shift) |
500 | 547 | { |
501 | | - // TODO: split into functions for separate types of shift including rotate. |
502 | | - UNIMPLEMENTED_FEATURE( |
503 | | - "Generation of SMT formula for shift expression: " + shift.pretty()); |
| 548 | + // TODO: Dispatch into different types of shifting |
| 549 | + const auto &first_operand = shift.op0(); |
| 550 | + const auto &second_operand = shift.op1(); |
| 551 | + |
| 552 | + if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift)) |
| 553 | + { |
| 554 | + return smt_bit_vector_theoryt::shift_left( |
| 555 | + convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand)); |
| 556 | + } |
| 557 | + else if( |
| 558 | + const auto right_logical_shift = expr_try_dynamic_cast<lshr_exprt>(shift)) |
| 559 | + { |
| 560 | + return smt_bit_vector_theoryt::logical_shift_right( |
| 561 | + convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand)); |
| 562 | + } |
| 563 | + else if( |
| 564 | + const auto right_arith_shift = expr_try_dynamic_cast<ashr_exprt>(shift)) |
| 565 | + { |
| 566 | + return smt_bit_vector_theoryt::arithmetic_shift_right( |
| 567 | + convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand)); |
| 568 | + } |
| 569 | + else |
| 570 | + { |
| 571 | + UNIMPLEMENTED_FEATURE( |
| 572 | + "Generation of SMT formula for shift expression: " + shift.pretty()); |
| 573 | + } |
504 | 574 | } |
505 | 575 |
|
506 | 576 | static smt_termt convert_expr_to_smt(const with_exprt &with) |
|
0 commit comments