|
3 | 3 | #include <util/arith_tools.h>
|
4 | 4 | #include <util/bitvector_expr.h>
|
5 | 5 | #include <util/bitvector_types.h>
|
| 6 | +#include <util/c_types.h> |
| 7 | +#include <util/config.h> |
| 8 | +#include <util/constructor_of.h> |
6 | 9 | #include <util/format.h>
|
7 | 10 | #include <util/std_expr.h>
|
8 | 11 |
|
9 | 12 | #include <solvers/smt2_incremental/convert_expr_to_smt.h>
|
10 | 13 | #include <solvers/smt2_incremental/smt_bit_vector_theory.h>
|
11 | 14 | #include <solvers/smt2_incremental/smt_core_theory.h>
|
12 | 15 | #include <solvers/smt2_incremental/smt_terms.h>
|
| 16 | +#include <solvers/smt2_incremental/smt_to_smt2_string.h> |
13 | 17 | #include <testing-utils/use_catch.h>
|
14 | 18 |
|
15 | 19 | TEST_CASE("\"typet\" to smt sort conversion", "[core][smt2_incremental]")
|
@@ -814,3 +818,126 @@ SCENARIO(
|
814 | 818 | }
|
815 | 819 | }
|
816 | 820 | }
|
| 821 | + |
| 822 | +TEST_CASE("expr to smt conversion for type casts", "[core][smt2_incremental]") |
| 823 | +{ |
| 824 | + const symbol_exprt bool_expr{"foo", bool_typet{}}; |
| 825 | + const smt_termt bool_term = smt_identifier_termt{"foo", smt_bool_sortt{}}; |
| 826 | + const symbol_exprt bv_expr{"bar", signedbv_typet(12)}; |
| 827 | + const smt_termt bv_term = |
| 828 | + smt_identifier_termt{"bar", smt_bit_vector_sortt{12}}; |
| 829 | + SECTION("Casts to bool") |
| 830 | + { |
| 831 | + CHECK( |
| 832 | + convert_expr_to_smt(typecast_exprt{bool_expr, bool_typet{}}) == |
| 833 | + bool_term); |
| 834 | + CHECK( |
| 835 | + convert_expr_to_smt(typecast_exprt{bv_expr, bool_typet{}}) == |
| 836 | + smt_core_theoryt::distinct( |
| 837 | + bv_term, smt_bit_vector_constant_termt{0, 12})); |
| 838 | + } |
| 839 | + SECTION("Casts to C bool") |
| 840 | + { |
| 841 | + // The config lines are necessary because when we do casting to C bool the |
| 842 | + // bit width depends on the configuration. |
| 843 | + config.ansi_c.mode = configt::ansi_ct::flavourt::GCC; |
| 844 | + config.ansi_c.set_arch_spec_i386(); |
| 845 | + const std::size_t c_bool_width = config.ansi_c.bool_width; |
| 846 | + const smt_bit_vector_constant_termt c_true{1, c_bool_width}; |
| 847 | + const smt_bit_vector_constant_termt c_false{0, c_bool_width}; |
| 848 | + SECTION("from bool") |
| 849 | + { |
| 850 | + const auto cast_bool = |
| 851 | + convert_expr_to_smt(typecast_exprt{bool_expr, c_bool_type()}); |
| 852 | + const auto expected_bool_conversion = |
| 853 | + smt_core_theoryt::if_then_else(bool_term, c_true, c_false); |
| 854 | + CHECK(cast_bool == expected_bool_conversion); |
| 855 | + } |
| 856 | + SECTION("from bit vector") |
| 857 | + { |
| 858 | + const auto cast_bit_vector = |
| 859 | + convert_expr_to_smt(typecast_exprt{bv_expr, c_bool_type()}); |
| 860 | + const auto expected_bit_vector_conversion = |
| 861 | + smt_core_theoryt::if_then_else( |
| 862 | + smt_core_theoryt::distinct( |
| 863 | + bv_term, smt_bit_vector_constant_termt{0, 12}), |
| 864 | + c_true, |
| 865 | + c_false); |
| 866 | + CHECK(cast_bit_vector == expected_bit_vector_conversion); |
| 867 | + } |
| 868 | + } |
| 869 | + SECTION("Casts to bit vector") |
| 870 | + { |
| 871 | + SECTION("Matched width casts") |
| 872 | + { |
| 873 | + typet from_type, to_type; |
| 874 | + using rowt = std::pair<typet, typet>; |
| 875 | + std::tie(from_type, to_type) = GENERATE( |
| 876 | + rowt{unsignedbv_typet{8}, unsignedbv_typet{8}}, |
| 877 | + rowt{unsignedbv_typet{8}, signedbv_typet{8}}, |
| 878 | + rowt{signedbv_typet{8}, unsignedbv_typet{8}}); |
| 879 | + CHECK( |
| 880 | + convert_expr_to_smt( |
| 881 | + typecast_exprt{from_integer(1, from_type), to_type}) == |
| 882 | + smt_bit_vector_constant_termt{1, 8}); |
| 883 | + } |
| 884 | + SECTION("Narrowing casts") |
| 885 | + { |
| 886 | + CHECK( |
| 887 | + convert_expr_to_smt(typecast_exprt{bv_expr, signedbv_typet{8}}) == |
| 888 | + smt_bit_vector_theoryt::extract(7, 0)(bv_term)); |
| 889 | + CHECK( |
| 890 | + convert_expr_to_smt(typecast_exprt{ |
| 891 | + from_integer(42, unsignedbv_typet{32}), unsignedbv_typet{16}}) == |
| 892 | + smt_bit_vector_theoryt::extract(15, 0)( |
| 893 | + smt_bit_vector_constant_termt{42, 32})); |
| 894 | + } |
| 895 | + SECTION("Widening casts") |
| 896 | + { |
| 897 | + std::size_t from_width, to_width, extension_width; |
| 898 | + using size_rowt = std::tuple<std::size_t, std::size_t, std::size_t>; |
| 899 | + std::tie(from_width, to_width, extension_width) = GENERATE( |
| 900 | + size_rowt{8, 64, 56}, size_rowt{16, 32, 16}, size_rowt{16, 128, 112}); |
| 901 | + PRECONDITION(from_width < to_width); |
| 902 | + PRECONDITION(to_width - from_width == extension_width); |
| 903 | + using make_typet = std::function<typet(std::size_t)>; |
| 904 | + const make_typet make_unsigned = constructor_oft<unsignedbv_typet>{}; |
| 905 | + const make_typet make_signed = constructor_oft<signedbv_typet>{}; |
| 906 | + using make_extensiont = |
| 907 | + std::function<std::function<smt_termt(smt_termt)>(std::size_t)>; |
| 908 | + const make_extensiont zero_extend = smt_bit_vector_theoryt::zero_extend; |
| 909 | + const make_extensiont sign_extend = smt_bit_vector_theoryt::sign_extend; |
| 910 | + make_typet make_source_type, make_destination_type; |
| 911 | + make_extensiont make_extension; |
| 912 | + using types_rowt = std::tuple<make_typet, make_typet, make_extensiont>; |
| 913 | + std::tie(make_source_type, make_destination_type, make_extension) = |
| 914 | + GENERATE_REF( |
| 915 | + types_rowt{make_unsigned, make_unsigned, zero_extend}, |
| 916 | + types_rowt{make_signed, make_signed, sign_extend}, |
| 917 | + types_rowt{make_signed, make_unsigned, sign_extend}, |
| 918 | + types_rowt{make_unsigned, make_signed, zero_extend}); |
| 919 | + const typecast_exprt cast{ |
| 920 | + from_integer(42, make_source_type(from_width)), |
| 921 | + make_destination_type(to_width)}; |
| 922 | + const smt_termt expected_term = make_extension(extension_width)( |
| 923 | + smt_bit_vector_constant_termt{42, from_width}); |
| 924 | + CHECK(convert_expr_to_smt(cast) == expected_term); |
| 925 | + } |
| 926 | + SECTION("from bool") |
| 927 | + { |
| 928 | + const exprt from_expr = GENERATE( |
| 929 | + exprt{symbol_exprt{"baz", bool_typet{}}}, |
| 930 | + exprt{true_exprt{}}, |
| 931 | + exprt{false_exprt{}}); |
| 932 | + const smt_termt from_term = convert_expr_to_smt(from_expr); |
| 933 | + const std::size_t width = GENERATE(1, 8, 16, 32, 64); |
| 934 | + const typecast_exprt cast{from_expr, bitvector_typet{ID_bv, width}}; |
| 935 | + CHECK( |
| 936 | + convert_expr_to_smt(cast) == |
| 937 | + smt_core_theoryt::if_then_else( |
| 938 | + from_term, |
| 939 | + smt_bit_vector_constant_termt{1, width}, |
| 940 | + smt_bit_vector_constant_termt{0, width})); |
| 941 | + } |
| 942 | + } |
| 943 | +} |
0 commit comments