|
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